From dfd45e89bc8040c45ad5df89fb01d7d0138ec953 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 13 Jul 2012 13:35:36 -0400 Subject: [PATCH 0001/1799] Remove easily user-triggerable BUG from generic_setlease commit 8d657eb3b43861064d36241e88d9d61c709f33f0 upstream. This can be trivially triggered from userspace by passing in something unexpected. kernel BUG at fs/locks.c:1468! invalid opcode: 0000 [#1] SMP RIP: 0010:generic_setlease+0xc2/0x100 Call Trace: __vfs_setlease+0x35/0x40 fcntl_setlease+0x76/0x150 sys_fcntl+0x1c6/0x810 system_call_fastpath+0x1a/0x1f Signed-off-by: Dave Jones Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/locks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/locks.c b/fs/locks.c index 0d68f1f81799..6a64f154db04 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1465,7 +1465,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp) case F_WRLCK: return generic_add_lease(filp, arg, flp); default: - BUG(); + return -EINVAL; } } EXPORT_SYMBOL(generic_setlease); -- GitLab From 9ab2f39f3ebbd4ccf2cdd75d564ee09c77c722ab Mon Sep 17 00:00:00 2001 From: David Dillow Date: Mon, 18 Jun 2012 00:15:21 -0300 Subject: [PATCH 0002/1799] media: cx231xx: don't DMA to random addresses commit a7deca6fa79d5c65575532e780f3c93f6bf8ddad upstream. Commit 7a6f6c29d264cdd2fe0eb3d923217eed5f0ad134 (cx231xx: use URB_NO_TRANSFER_DMA_MAP) was intended to avoid mapping the DMA buffer for URB twice. This works for the URBs allocated with usb_alloc_urb(), as those are allocated from cohernent DMA pools, but the flag was also added for the VBI and audio URBs, which have a manually allocated area. This leaves the random trash in the structure after allocation as the DMA address, corrupting memory and preventing VBI and audio from working. Letting the USB core map the buffers solves the problem. Signed-off-by: David Dillow Cc: Sri Deevi Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/cx231xx/cx231xx-audio.c | 4 ++-- drivers/media/video/cx231xx/cx231xx-vbi.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/video/cx231xx/cx231xx-audio.c index a2c2b7d343ec..e5742a0e19a0 100644 --- a/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/drivers/media/video/cx231xx/cx231xx-audio.c @@ -307,7 +307,7 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) urb->context = dev; urb->pipe = usb_rcvisocpipe(dev->udev, dev->adev.end_point_addr); - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; + urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = dev->adev.transfer_buffer[i]; urb->interval = 1; urb->complete = cx231xx_audio_isocirq; @@ -368,7 +368,7 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev) urb->context = dev; urb->pipe = usb_rcvbulkpipe(dev->udev, dev->adev.end_point_addr); - urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; + urb->transfer_flags = 0; urb->transfer_buffer = dev->adev.transfer_buffer[i]; urb->complete = cx231xx_audio_bulkirq; urb->transfer_buffer_length = sb_size; diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c index 8cdee5f78f13..9c5967e1d0c6 100644 --- a/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/drivers/media/video/cx231xx/cx231xx-vbi.c @@ -452,7 +452,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, return -ENOMEM; } dev->vbi_mode.bulk_ctl.urb[i] = urb; - urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; + urb->transfer_flags = 0; dev->vbi_mode.bulk_ctl.transfer_buffer[i] = kzalloc(sb_size, GFP_KERNEL); -- GitLab From 175063bccaefa0b6a4934ffaf3a9639a4a7616d0 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 12 Jul 2012 22:47:37 +0200 Subject: [PATCH 0003/1799] hwmon: (it87) Preserve configuration register bits on init commit 41002f8dd5938d5ad1d008ce5bfdbfe47fa7b4e8 upstream. We were accidentally losing one bit in the configuration register on device initialization. It was reported to freeze one specific system right away. Properly preserve all bits we don't explicitly want to change in order to prevent that. Reported-by: Stevie Trujillo Signed-off-by: Jean Delvare Reviewed-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/it87.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 0b204e4cf51c..f524882aaeb1 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -2157,7 +2157,7 @@ static void __devinit it87_init_device(struct platform_device *pdev) /* Start monitoring */ it87_write_value(data, IT87_REG_CONFIG, - (it87_read_value(data, IT87_REG_CONFIG) & 0x36) + (it87_read_value(data, IT87_REG_CONFIG) & 0x3e) | (update_vbat ? 0x41 : 0x01)); } -- GitLab From e2ea6a3e16a36e26af184f781ede7a12f6cff8b5 Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Thu, 12 Jul 2012 09:43:14 -0400 Subject: [PATCH 0004/1799] block: fix infinite loop in __getblk_slow commit 91f68c89d8f35fe98ea04159b9a3b42d0149478f upstream. Commit 080399aaaf35 ("block: don't mark buffers beyond end of disk as mapped") exposed a bug in __getblk_slow that causes mount to hang as it loops infinitely waiting for a buffer that lies beyond the end of the disk to become uptodate. The problem was initially reported by Torsten Hilbrich here: https://lkml.org/lkml/2012/6/18/54 and also reported independently here: http://www.sysresccd.org/forums/viewtopic.php?f=13&t=4511 and then Richard W.M. Jones and Marcos Mello noted a few separate bugzillas also associated with the same issue. This patch has been confirmed to fix: https://bugzilla.redhat.com/show_bug.cgi?id=835019 The main problem is here, in __getblk_slow: for (;;) { struct buffer_head * bh; int ret; bh = __find_get_block(bdev, block, size); if (bh) return bh; ret = grow_buffers(bdev, block, size); if (ret < 0) return NULL; if (ret == 0) free_more_memory(); } __find_get_block does not find the block, since it will not be marked as mapped, and so grow_buffers is called to fill in the buffers for the associated page. I believe the for (;;) loop is there primarily to retry in the case of memory pressure keeping grow_buffers from succeeding. However, we also continue to loop for other cases, like the block lying beond the end of the disk. So, the fix I came up with is to only loop when grow_buffers fails due to memory allocation issues (return value of 0). The attached patch was tested by myself, Torsten, and Rich, and was found to resolve the problem in call cases. Signed-off-by: Jeff Moyer Reported-and-Tested-by: Torsten Hilbrich Tested-by: Richard W.M. Jones Reviewed-by: Josh Boyer [ Jens is on vacation, taking this directly - Linus ] Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/buffer.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index ad5938ca357c..0bc1bed6c4e0 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1036,6 +1036,9 @@ grow_buffers(struct block_device *bdev, sector_t block, int size) static struct buffer_head * __getblk_slow(struct block_device *bdev, sector_t block, int size) { + int ret; + struct buffer_head *bh; + /* Size must be multiple of hard sectorsize */ if (unlikely(size & (bdev_logical_block_size(bdev)-1) || (size < 512 || size > PAGE_SIZE))) { @@ -1048,20 +1051,21 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size) return NULL; } - for (;;) { - struct buffer_head * bh; - int ret; +retry: + bh = __find_get_block(bdev, block, size); + if (bh) + return bh; + ret = grow_buffers(bdev, block, size); + if (ret == 0) { + free_more_memory(); + goto retry; + } else if (ret > 0) { bh = __find_get_block(bdev, block, size); if (bh) return bh; - - ret = grow_buffers(bdev, block, size); - if (ret < 0) - return NULL; - if (ret == 0) - free_more_memory(); } + return NULL; } /* -- GitLab From a3fa551238b526b7b345da724b988650468cf36e Mon Sep 17 00:00:00 2001 From: Santosh Nayak Date: Sat, 23 Jun 2012 07:59:54 -0300 Subject: [PATCH 0005/1799] media: dvb-core: Release semaphore on error path dvb_register_device() commit 82163edcdfa4eb3d74516cc8e9f38dd3d039b67d upstream. There is a missing "up_write()" here. Semaphore should be released before returning error value. Signed-off-by: Santosh Nayak Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb/dvb-core/dvbdev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 00a67326c193..39eab73b01ae 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -243,6 +243,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, if (minor == MAX_DVB_MINORS) { kfree(dvbdevfops); kfree(dvbdev); + up_write(&minor_rwsem); mutex_unlock(&dvbdev_register_lock); return -EINVAL; } -- GitLab From a3a13c9974160030550ae28b3fa2c1ea8992b9c5 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Wed, 16 May 2012 16:21:52 -0300 Subject: [PATCH 0006/1799] mtd: nandsim: don't open code a do_div helper commit 596fd46268634082314b3af1ded4612e1b7f3f03 upstream. We don't need to open code the divide function, just use div_u64 that already exists and do the same job. While this is a straightforward clean up, there is more to that, the real motivation for this. While building on a cross compiling environment in armel, using gcc 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5), I was getting the following build error: ERROR: "__aeabi_uldivmod" [drivers/mtd/nand/nandsim.ko] undefined! After investigating with objdump and hand built assembly version generated with the compiler, I narrowed __aeabi_uldivmod as being generated from the divide function. When nandsim.c is built with -fno-inline-functions-called-once, that happens when CONFIG_DEBUG_SECTION_MISMATCH is enabled, the do_div optimization in arch/arm/include/asm/div64.h doesn't work as expected with the open coded divide function: even if the do_div we are using doesn't have a constant divisor, the compiler still includes the else parts of the optimized do_div macro, and translates the divisions there to use __aeabi_uldivmod, instead of only calling __do_div_asm -> __do_div64 and optimizing/removing everything else out. So to reproduce, gcc 4.6 plus CONFIG_DEBUG_SECTION_MISMATCH=y and CONFIG_MTD_NAND_NANDSIM=m should do it, building on armel. After this change, the compiler does the intended thing even with -fno-inline-functions-called-once, and optimizes out as expected the constant handling in the optimized do_div on arm. As this also avoids a build issue, I'm marking for Stable, as I think is applicable for this case. Signed-off-by: Herton Ronaldo Krzesinski Acked-by: Nicolas Pitre Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/nandsim.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 261f478f8cc3..c606b6afd7aa 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -547,12 +547,6 @@ static char *get_partition_name(int i) return kstrdup(buf, GFP_KERNEL); } -static uint64_t divide(uint64_t n, uint32_t d) -{ - do_div(n, d); - return n; -} - /* * Initialize the nandsim structure. * @@ -581,7 +575,7 @@ static int init_nandsim(struct mtd_info *mtd) ns->geom.oobsz = mtd->oobsize; ns->geom.secsz = mtd->erasesize; ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz; - ns->geom.pgnum = divide(ns->geom.totsz, ns->geom.pgsz); + ns->geom.pgnum = div_u64(ns->geom.totsz, ns->geom.pgsz); ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz; ns->geom.secshift = ffs(ns->geom.secsz) - 1; ns->geom.pgshift = chip->page_shift; @@ -924,7 +918,7 @@ static int setup_wear_reporting(struct mtd_info *mtd) if (!rptwear) return 0; - wear_eb_count = divide(mtd->size, mtd->erasesize); + wear_eb_count = div_u64(mtd->size, mtd->erasesize); mem = wear_eb_count * sizeof(unsigned long); if (mem / sizeof(unsigned long) != wear_eb_count) { NS_ERR("Too many erase blocks for wear reporting\n"); -- GitLab From e301f7b1dbbb0af6dcb8ed10c800fa95bb34917a Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 9 Jul 2012 11:34:13 +1000 Subject: [PATCH 0007/1799] md/raid1: fix use-after-free bug in RAID1 data-check code. commit 2d4f4f3384d4ef4f7c571448e803a1ce721113d5 upstream. This bug has been present ever since data-check was introduce in 2.6.16. However it would only fire if a data-check were done on a degraded array, which was only possible if the array has 3 or more devices. This is certainly possible, but is quite uncommon. Since hot-replace was added in 3.3 it can happen more often as the same condition can arise if not all possible replacements are present. The problem is that as soon as we submit the last read request, the 'r1_bio' structure could be freed at any time, so we really should stop looking at it. If the last device is being read from we will stop looking at it. However if the last device is not due to be read from, we will still check the bio pointer in the r1_bio, but the r1_bio might already be free. So use the read_targets counter to make sure we stop looking for bios to submit as soon as we have submitted them all. This fix is suitable for any -stable kernel since 2.6.16. Reported-by: Arnold Schulz Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid1.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d7e957721456..d1f74ab13966 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2486,9 +2486,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp */ if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { atomic_set(&r1_bio->remaining, read_targets); - for (i = 0; i < conf->raid_disks * 2; i++) { + for (i = 0; i < conf->raid_disks * 2 && read_targets; i++) { bio = r1_bio->bios[i]; if (bio->bi_end_io == end_sync_read) { + read_targets--; md_sync_acct(bio->bi_bdev, nr_sectors); generic_make_request(bio); } -- GitLab From 5c77ea89ed79a692b0097dbca3652fbc83e30619 Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Fri, 13 Jul 2012 15:30:48 +0900 Subject: [PATCH 0008/1799] ARM: SAMSUNG: fix race in s3c_adc_start for ADC commit 8265981bb439f3ecc5356fb877a6c2a6636ac88a upstream. Checking for adc->ts_pend already claimed should be done with the lock held. Signed-off-by: Todd Poynor Acked-by: Ben Dooks Signed-off-by: Kukjin Kim Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-samsung/adc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c index 33ecd0c9f0c3..b1e05ccff3ac 100644 --- a/arch/arm/plat-samsung/adc.c +++ b/arch/arm/plat-samsung/adc.c @@ -157,11 +157,13 @@ int s3c_adc_start(struct s3c_adc_client *client, return -EINVAL; } - if (client->is_ts && adc->ts_pend) - return -EAGAIN; - spin_lock_irqsave(&adc->lock, flags); + if (client->is_ts && adc->ts_pend) { + spin_unlock_irqrestore(&adc->lock, flags); + return -EAGAIN; + } + client->channel = channel; client->nr_samples = nr_samples; -- GitLab From af3a2390c0f80345516524c3fe7e717f465ce6bd Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 4 Jul 2012 10:02:32 +0800 Subject: [PATCH 0009/1799] ACPICA: Fix possible fault in return package object repair code commit 46befd6b38d802dfc5998e7d7938854578b45d9d upstream. Fixes a problem that can occur when a lone package object is wrapped with an outer package object in order to conform to the ACPI specification. Can affect these predefined names: _ALR,_MLS,_PSS,_TRT,_TSS,_PRT,_HPX,_DLM,_CSD,_PSD,_TSD https://bugzilla.kernel.org/show_bug.cgi?id=44171 This problem was introduced in 3.4-rc1 by commit 6a99b1c94d053b3420eaa4a4bc8b2883dd90a2f9 (ACPICA: Object repair code: Support to add Package wrappers) Reported-by: Vlastimil Babka Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/acpica/nspredef.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 23ce09686418..fe6626035495 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -638,7 +638,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* Create the new outer package and populate it */ status = - acpi_ns_wrap_with_package(data, *elements, + acpi_ns_wrap_with_package(data, return_object, return_object_ptr); if (ACPI_FAILURE(status)) { return (status); -- GitLab From 667fb5508900340d657645e0bfc9bf210a1fc363 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Thu, 12 Jul 2012 12:24:33 +0200 Subject: [PATCH 0010/1799] cpufreq / ACPI: Fix not loading acpi-cpufreq driver regression commit c4686c71a9183f76e3ef59098da5c098748672f6 upstream. Commit d640113fe80e45ebd4a5b420b introduced a regression on SMP systems where the processor core with ACPI id zero is disabled (typically should be the case because of hyperthreading). The regression got spread through stable kernels. On 3.0.X it got introduced via 3.0.18. Such platforms may be rare, but do exist. Look out for a disabled processor with acpi_id 0 in dmesg: ACPI: LAPIC (acpi_id[0x00] lapic_id[0x10] disabled) This problem has been observed on a: HP Proliant BL280c G6 blade This patch restricts the introduced workaround to platforms with nr_cpu_ids <= 1. Signed-off-by: Thomas Renninger Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/processor_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index c850de4c9a14..eff722278ff5 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -189,10 +189,12 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) * Processor (CPU3, 0x03, 0x00000410, 0x06) {} * } * - * Ignores apic_id and always return 0 for CPU0's handle. + * Ignores apic_id and always returns 0 for the processor + * handle with acpi id 0 if nr_cpu_ids is 1. + * This should be the case if SMP tables are not found. * Return -1 for other CPU's handle. */ - if (acpi_id == 0) + if (nr_cpu_ids <= 1 && acpi_id == 0) return acpi_id; else return apic_id; -- GitLab From 7490d0a4cfefa16f9d8ce636eb5b2e13d2432db3 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 22 Jun 2012 15:52:09 +0200 Subject: [PATCH 0011/1799] sched/nohz: Rewrite and fix load-avg computation -- again commit 5167e8d5417bf5c322a703d2927daec727ea40dd upstream. Thanks to Charles Wang for spotting the defects in the current code: - If we go idle during the sample window -- after sampling, we get a negative bias because we can negate our own sample. - If we wake up during the sample window we get a positive bias because we push the sample to a known active period. So rewrite the entire nohz load-avg muck once again, now adding copious documentation to the code. Reported-and-tested-by: Doug Smythies Reported-and-tested-by: Charles Wang Signed-off-by: Peter Zijlstra Cc: Linus Torvalds Cc: Andrew Morton Link: http://lkml.kernel.org/r/1340373782.18025.74.camel@twins [ minor edits ] Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- include/linux/sched.h | 8 ++ kernel/sched/core.c | 275 +++++++++++++++++++++++++++++---------- kernel/sched/idle_task.c | 1 - kernel/sched/sched.h | 2 - kernel/time/tick-sched.c | 2 + 5 files changed, 213 insertions(+), 75 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 81a173c0897d..7b06169d7241 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1933,6 +1933,14 @@ static inline int set_cpus_allowed_ptr(struct task_struct *p, } #endif +#ifdef CONFIG_NO_HZ +void calc_load_enter_idle(void); +void calc_load_exit_idle(void); +#else +static inline void calc_load_enter_idle(void) { } +static inline void calc_load_exit_idle(void) { } +#endif /* CONFIG_NO_HZ */ + #ifndef CONFIG_CPUMASK_OFFSTACK static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask) { diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2000e069fc9e..817bf7018834 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2162,11 +2162,73 @@ unsigned long this_cpu_load(void) } +/* + * Global load-average calculations + * + * We take a distributed and async approach to calculating the global load-avg + * in order to minimize overhead. + * + * The global load average is an exponentially decaying average of nr_running + + * nr_uninterruptible. + * + * Once every LOAD_FREQ: + * + * nr_active = 0; + * for_each_possible_cpu(cpu) + * nr_active += cpu_of(cpu)->nr_running + cpu_of(cpu)->nr_uninterruptible; + * + * avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n) + * + * Due to a number of reasons the above turns in the mess below: + * + * - for_each_possible_cpu() is prohibitively expensive on machines with + * serious number of cpus, therefore we need to take a distributed approach + * to calculating nr_active. + * + * \Sum_i x_i(t) = \Sum_i x_i(t) - x_i(t_0) | x_i(t_0) := 0 + * = \Sum_i { \Sum_j=1 x_i(t_j) - x_i(t_j-1) } + * + * So assuming nr_active := 0 when we start out -- true per definition, we + * can simply take per-cpu deltas and fold those into a global accumulate + * to obtain the same result. See calc_load_fold_active(). + * + * Furthermore, in order to avoid synchronizing all per-cpu delta folding + * across the machine, we assume 10 ticks is sufficient time for every + * cpu to have completed this task. + * + * This places an upper-bound on the IRQ-off latency of the machine. Then + * again, being late doesn't loose the delta, just wrecks the sample. + * + * - cpu_rq()->nr_uninterruptible isn't accurately tracked per-cpu because + * this would add another cross-cpu cacheline miss and atomic operation + * to the wakeup path. Instead we increment on whatever cpu the task ran + * when it went into uninterruptible state and decrement on whatever cpu + * did the wakeup. This means that only the sum of nr_uninterruptible over + * all cpus yields the correct result. + * + * This covers the NO_HZ=n code, for extra head-aches, see the comment below. + */ + /* Variables and functions for calc_load */ static atomic_long_t calc_load_tasks; static unsigned long calc_load_update; unsigned long avenrun[3]; -EXPORT_SYMBOL(avenrun); +EXPORT_SYMBOL(avenrun); /* should be removed */ + +/** + * get_avenrun - get the load average array + * @loads: pointer to dest load array + * @offset: offset to add + * @shift: shift count to shift the result left + * + * These values are estimates at best, so no need for locking. + */ +void get_avenrun(unsigned long *loads, unsigned long offset, int shift) +{ + loads[0] = (avenrun[0] + offset) << shift; + loads[1] = (avenrun[1] + offset) << shift; + loads[2] = (avenrun[2] + offset) << shift; +} static long calc_load_fold_active(struct rq *this_rq) { @@ -2183,6 +2245,9 @@ static long calc_load_fold_active(struct rq *this_rq) return delta; } +/* + * a1 = a0 * e + a * (1 - e) + */ static unsigned long calc_load(unsigned long load, unsigned long exp, unsigned long active) { @@ -2194,30 +2259,118 @@ calc_load(unsigned long load, unsigned long exp, unsigned long active) #ifdef CONFIG_NO_HZ /* - * For NO_HZ we delay the active fold to the next LOAD_FREQ update. + * Handle NO_HZ for the global load-average. + * + * Since the above described distributed algorithm to compute the global + * load-average relies on per-cpu sampling from the tick, it is affected by + * NO_HZ. + * + * The basic idea is to fold the nr_active delta into a global idle-delta upon + * entering NO_HZ state such that we can include this as an 'extra' cpu delta + * when we read the global state. + * + * Obviously reality has to ruin such a delightfully simple scheme: + * + * - When we go NO_HZ idle during the window, we can negate our sample + * contribution, causing under-accounting. + * + * We avoid this by keeping two idle-delta counters and flipping them + * when the window starts, thus separating old and new NO_HZ load. + * + * The only trick is the slight shift in index flip for read vs write. + * + * 0s 5s 10s 15s + * +10 +10 +10 +10 + * |-|-----------|-|-----------|-|-----------|-| + * r:0 0 1 1 0 0 1 1 0 + * w:0 1 1 0 0 1 1 0 0 + * + * This ensures we'll fold the old idle contribution in this window while + * accumlating the new one. + * + * - When we wake up from NO_HZ idle during the window, we push up our + * contribution, since we effectively move our sample point to a known + * busy state. + * + * This is solved by pushing the window forward, and thus skipping the + * sample, for this cpu (effectively using the idle-delta for this cpu which + * was in effect at the time the window opened). This also solves the issue + * of having to deal with a cpu having been in NOHZ idle for multiple + * LOAD_FREQ intervals. * * When making the ILB scale, we should try to pull this in as well. */ -static atomic_long_t calc_load_tasks_idle; +static atomic_long_t calc_load_idle[2]; +static int calc_load_idx; -void calc_load_account_idle(struct rq *this_rq) +static inline int calc_load_write_idx(void) { + int idx = calc_load_idx; + + /* + * See calc_global_nohz(), if we observe the new index, we also + * need to observe the new update time. + */ + smp_rmb(); + + /* + * If the folding window started, make sure we start writing in the + * next idle-delta. + */ + if (!time_before(jiffies, calc_load_update)) + idx++; + + return idx & 1; +} + +static inline int calc_load_read_idx(void) +{ + return calc_load_idx & 1; +} + +void calc_load_enter_idle(void) +{ + struct rq *this_rq = this_rq(); long delta; + /* + * We're going into NOHZ mode, if there's any pending delta, fold it + * into the pending idle delta. + */ delta = calc_load_fold_active(this_rq); - if (delta) - atomic_long_add(delta, &calc_load_tasks_idle); + if (delta) { + int idx = calc_load_write_idx(); + atomic_long_add(delta, &calc_load_idle[idx]); + } } -static long calc_load_fold_idle(void) +void calc_load_exit_idle(void) { - long delta = 0; + struct rq *this_rq = this_rq(); + + /* + * If we're still before the sample window, we're done. + */ + if (time_before(jiffies, this_rq->calc_load_update)) + return; /* - * Its got a race, we don't care... + * We woke inside or after the sample window, this means we're already + * accounted through the nohz accounting, so skip the entire deal and + * sync up for the next window. */ - if (atomic_long_read(&calc_load_tasks_idle)) - delta = atomic_long_xchg(&calc_load_tasks_idle, 0); + this_rq->calc_load_update = calc_load_update; + if (time_before(jiffies, this_rq->calc_load_update + 10)) + this_rq->calc_load_update += LOAD_FREQ; +} + +static long calc_load_fold_idle(void) +{ + int idx = calc_load_read_idx(); + long delta = 0; + + if (atomic_long_read(&calc_load_idle[idx])) + delta = atomic_long_xchg(&calc_load_idle[idx], 0); return delta; } @@ -2303,66 +2456,39 @@ static void calc_global_nohz(void) { long delta, active, n; - /* - * 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); - - /* - * It could be the one fold was all it took, we done! - */ - if (time_before(jiffies, calc_load_update + 10)) - return; - - /* - * Catch-up, fold however many we are behind still - */ - delta = jiffies - calc_load_update - 10; - n = 1 + (delta / LOAD_FREQ); + if (!time_before(jiffies, calc_load_update + 10)) { + /* + * Catch-up, fold however many we are behind still + */ + delta = jiffies - calc_load_update - 10; + n = 1 + (delta / LOAD_FREQ); - active = atomic_long_read(&calc_load_tasks); - active = active > 0 ? active * FIXED_1 : 0; + 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); + 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; -} -#else -void calc_load_account_idle(struct rq *this_rq) -{ -} + calc_load_update += n * LOAD_FREQ; + } -static inline long calc_load_fold_idle(void) -{ - return 0; + /* + * Flip the idle index... + * + * Make sure we first write the new time then flip the index, so that + * calc_load_write_idx() will see the new time when it reads the new + * index, this avoids a double flip messing things up. + */ + smp_wmb(); + calc_load_idx++; } +#else /* !CONFIG_NO_HZ */ -static void calc_global_nohz(void) -{ -} -#endif +static inline long calc_load_fold_idle(void) { return 0; } +static inline void calc_global_nohz(void) { } -/** - * get_avenrun - get the load average array - * @loads: pointer to dest load array - * @offset: offset to add - * @shift: shift count to shift the result left - * - * These values are estimates at best, so no need for locking. - */ -void get_avenrun(unsigned long *loads, unsigned long offset, int shift) -{ - loads[0] = (avenrun[0] + offset) << shift; - loads[1] = (avenrun[1] + offset) << shift; - loads[2] = (avenrun[2] + offset) << shift; -} +#endif /* CONFIG_NO_HZ */ /* * calc_load - update the avenrun load estimates 10 ticks after the @@ -2370,11 +2496,18 @@ void get_avenrun(unsigned long *loads, unsigned long offset, int shift) */ void calc_global_load(unsigned long ticks) { - long active; + long active, delta; if (time_before(jiffies, calc_load_update + 10)) return; + /* + * Fold the 'old' idle-delta to include all NO_HZ cpus. + */ + delta = calc_load_fold_idle(); + if (delta) + atomic_long_add(delta, &calc_load_tasks); + active = atomic_long_read(&calc_load_tasks); active = active > 0 ? active * FIXED_1 : 0; @@ -2385,12 +2518,7 @@ void calc_global_load(unsigned long ticks) calc_load_update += LOAD_FREQ; /* - * Account one period with whatever state we found before - * folding in the nohz state and ageing the entire idle period. - * - * This avoids loosing a sample when we go idle between - * calc_load_account_active() (10 ticks ago) and now and thus - * under-accounting. + * In case we idled for multiple LOAD_FREQ intervals, catch up in bulk. */ calc_global_nohz(); } @@ -2407,13 +2535,16 @@ static void calc_load_account_active(struct rq *this_rq) return; delta = calc_load_fold_active(this_rq); - delta += calc_load_fold_idle(); if (delta) atomic_long_add(delta, &calc_load_tasks); this_rq->calc_load_update += LOAD_FREQ; } +/* + * End of global load-average stuff + */ + /* * The exact cpuload at various idx values, calculated at every tick would be * load = (2^idx - 1) / 2^idx * load + 1 / 2^idx * cur_load diff --git a/kernel/sched/idle_task.c b/kernel/sched/idle_task.c index 91b4c957f289..fdf752275724 100644 --- a/kernel/sched/idle_task.c +++ b/kernel/sched/idle_task.c @@ -25,7 +25,6 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl static struct task_struct *pick_next_task_idle(struct rq *rq) { schedstat_inc(rq, sched_goidle); - calc_load_account_idle(rq); return rq->idle; } diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index fb3acba4d52e..116ced06ecc0 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -940,8 +940,6 @@ static inline u64 sched_avg_period(void) return (u64)sysctl_sched_time_avg * NSEC_PER_MSEC / 2; } -void calc_load_account_idle(struct rq *this_rq); - #ifdef CONFIG_SCHED_HRTICK /* diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 6a3a5b9ff561..fd4e160aa9c4 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -401,6 +401,7 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts) */ if (!ts->tick_stopped) { select_nohz_load_balancer(1); + calc_load_enter_idle(); ts->idle_tick = hrtimer_get_expires(&ts->sched_timer); ts->tick_stopped = 1; @@ -591,6 +592,7 @@ void tick_nohz_idle_exit(void) account_idle_ticks(ticks); #endif + calc_load_exit_idle(); touch_softlockup_watchdog(); /* * Cancel the scheduled timer and restore the tick -- GitLab From 665c7a83a1a64582c4393dd45430c848150a10dd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 25 Jun 2012 15:07:17 +0200 Subject: [PATCH 0012/1799] intel_ips: blacklist HP ProBook laptops commit 88ca518b0bb4161e5f20f8a1d9cc477cae294e54 upstream. intel_ips driver spews the warning message "ME failed to update for more than 1s, likely hung" at each second endlessly on HP ProBook laptops with IronLake. As this has never worked, better to blacklist the driver for now. Signed-off-by: Takashi Iwai Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/intel_ips.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 0ffdb3cde2bb..9af4257d4901 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #include #include @@ -1485,6 +1486,24 @@ static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = { MODULE_DEVICE_TABLE(pci, ips_id_table); +static int ips_blacklist_callback(const struct dmi_system_id *id) +{ + pr_info("Blacklisted intel_ips for %s\n", id->ident); + return 1; +} + +static const struct dmi_system_id ips_blacklist[] = { + { + .callback = ips_blacklist_callback, + .ident = "HP ProBook", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook"), + }, + }, + { } /* terminating entry */ +}; + static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) { u64 platform_info; @@ -1494,6 +1513,9 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) u16 htshi, trc, trc_required_mask; u8 tse; + if (dmi_check_system(ips_blacklist)) + return -ENODEV; + ips = kzalloc(sizeof(struct ips_driver), GFP_KERNEL); if (!ips) return -ENOMEM; -- GitLab From b9311277c28fab089ee0816307035c3a5f546bcf Mon Sep 17 00:00:00 2001 From: Anders Kaseorg Date: Sun, 15 Jul 2012 17:14:25 -0400 Subject: [PATCH 0013/1799] fifo: Do not restart open() if it already found a partner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 05d290d66be6ef77a0b962ebecf01911bd984a78 upstream. If a parent and child process open the two ends of a fifo, and the child immediately exits, the parent may receive a SIGCHLD before its open() returns. In that case, we need to make sure that open() will return successfully after the SIGCHLD handler returns, instead of throwing EINTR or being restarted. Otherwise, the restarted open() would incorrectly wait for a second partner on the other end. The following test demonstrates the EINTR that was wrongly thrown from the parent’s open(). Change .sa_flags = 0 to .sa_flags = SA_RESTART to see a deadlock instead, in which the restarted open() waits for a second reader that will never come. (On my systems, this happens pretty reliably within about 5 to 500 iterations. Others report that it manages to loop ~forever sometimes; YMMV.) #include #include #include #include #include #include #include #include #define CHECK(x) do if ((x) == -1) {perror(#x); abort();} while(0) void handler(int signum) {} int main() { struct sigaction act = {.sa_handler = handler, .sa_flags = 0}; CHECK(sigaction(SIGCHLD, &act, NULL)); CHECK(mknod("fifo", S_IFIFO | S_IRWXU, 0)); for (;;) { int fd; pid_t pid; putc('.', stderr); CHECK(pid = fork()); if (pid == 0) { CHECK(fd = open("fifo", O_RDONLY)); _exit(0); } CHECK(fd = open("fifo", O_WRONLY)); CHECK(close(fd)); CHECK(waitpid(pid, NULL, 0)); } } This is what I suspect was causing the Git test suite to fail in t9010-svn-fe.sh: http://bugs.debian.org/678852 Signed-off-by: Anders Kaseorg Reviewed-by: Jonathan Nieder Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/fifo.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/fifo.c b/fs/fifo.c index b1a524d798e7..cf6f4345ceb0 100644 --- a/fs/fifo.c +++ b/fs/fifo.c @@ -14,7 +14,7 @@ #include #include -static void wait_for_partner(struct inode* inode, unsigned int *cnt) +static int wait_for_partner(struct inode* inode, unsigned int *cnt) { int cur = *cnt; @@ -23,6 +23,7 @@ static void wait_for_partner(struct inode* inode, unsigned int *cnt) if (signal_pending(current)) break; } + return cur == *cnt ? -ERESTARTSYS : 0; } static void wake_up_partner(struct inode* inode) @@ -67,8 +68,7 @@ static int fifo_open(struct inode *inode, struct file *filp) * seen a writer */ filp->f_version = pipe->w_counter; } else { - wait_for_partner(inode, &pipe->w_counter); - if(signal_pending(current)) + if (wait_for_partner(inode, &pipe->w_counter)) goto err_rd; } } @@ -90,8 +90,7 @@ static int fifo_open(struct inode *inode, struct file *filp) wake_up_partner(inode); if (!pipe->readers) { - wait_for_partner(inode, &pipe->r_counter); - if (signal_pending(current)) + if (wait_for_partner(inode, &pipe->r_counter)) goto err_wr; } break; -- GitLab From a3c021d25debc6278951e0112b1a06d8b7376d22 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 4 Jul 2012 13:10:02 +0200 Subject: [PATCH 0014/1799] rt2x00usb: fix indexes ordering on RX queue kick commit efd821182cec8c92babef6e00a95066d3252fda4 upstream. On rt2x00_dmastart() we increase index specified by Q_INDEX and on rt2x00_dmadone() we increase index specified by Q_INDEX_DONE. So entries between Q_INDEX_DONE and Q_INDEX are those we currently process in the hardware. Entries between Q_INDEX and Q_INDEX_DONE are those we can submit to the hardware. According to that fix rt2x00usb_kick_queue(), as we need to submit RX entries that are not processed by the hardware. It worked before only for empty queue, otherwise was broken. Note that for TX queues indexes ordering are ok. We need to kick entries that have filled skb, but was not submitted to the hardware, i.e. started from Q_INDEX_DONE and have ENTRY_DATA_PENDING bit set. From practical standpoint this fixes RX queue stall, usually reproducible in AP mode, like for example reported here: https://bugzilla.redhat.com/show_bug.cgi?id=828824 Reported-and-tested-by: Franco Miceli Reported-and-tested-by: Tom Horsley Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2x00usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 66094eb21b61..507085facb88 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -436,8 +436,8 @@ void rt2x00usb_kick_queue(struct data_queue *queue) case QID_RX: if (!rt2x00queue_full(queue)) rt2x00queue_for_each_entry(queue, - Q_INDEX_DONE, Q_INDEX, + Q_INDEX_DONE, NULL, rt2x00usb_kick_rx_entry); break; -- GitLab From 3cc4e0e187e4187a6ec13a79dafc1b0f72e31afa Mon Sep 17 00:00:00 2001 From: Tushar Dave Date: Thu, 12 Jul 2012 08:56:56 +0000 Subject: [PATCH 0015/1799] e1000e: Correct link check logic for 82571 serdes commit d0efa8f23a644f7cb7d1f8e78dd9a223efa412a3 upstream. SYNCH bit and IV bit of RXCW register are sticky. Before examining these bits, RXCW should be read twice to filter out one-time false events and have correct values for these bits. Incorrect values of these bits in link check logic can cause weird link stability issues if auto-negotiation fails. Reported-by: Dean Nelson Signed-off-by: Tushar Dave Reviewed-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/intel/e1000e/82571.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index c6d95f2031eb..a9dd6a92cf50 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -1553,6 +1553,9 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) ctrl = er32(CTRL); status = er32(STATUS); rxcw = er32(RXCW); + /* SYNCH bit and IV bit are sticky */ + udelay(10); + rxcw = er32(RXCW); if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) { -- GitLab From 57cff816121720c80b39e3b3fb0ef36128fdc45b Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 4 Jul 2012 13:20:20 +0200 Subject: [PATCH 0016/1799] iwlegacy: always monitor for stuck queues commit c2ca7d92ed4bbd779516beb6eb226e19f7f7ab0f upstream. This is iwlegacy version of: commit 342bbf3fee2fa9a18147e74b2e3c4229a4564912 Author: Johannes Berg Date: Sun Mar 4 08:50:46 2012 -0800 iwlwifi: always monitor for stuck queues If we only monitor while associated, the following can happen: - we're associated, and the queue stuck check runs, setting the queue "touch" time to X - we disassociate, stopping the monitoring, which leaves the time set to X - almost 2s later, we associate, and enqueue a frame - before the frame is transmitted, we monitor for stuck queues, and find the time set to X, although it is now later than X + 2000ms, so we decide that the queue is stuck and erroneously restart the device Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlegacy/common.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index eaf249452e51..4bc27112cbe2 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -4767,14 +4767,12 @@ il_bg_watchdog(unsigned long data) return; /* monitor and check for other stuck queues */ - if (il_is_any_associated(il)) { - for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { - /* skip as we already checked the command queue */ - if (cnt == il->cmd_queue) - continue; - if (il_check_stuck_queue(il, cnt)) - return; - } + for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { + /* skip as we already checked the command queue */ + if (cnt == il->cmd_queue) + continue; + if (il_check_stuck_queue(il, cnt)) + return; } mod_timer(&il->watchdog, -- GitLab From 1214b7852425b78a2b73b0a759ec55210340396d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 4 Jul 2012 13:59:08 +0200 Subject: [PATCH 0017/1799] iwlegacy: don't mess up the SCD when removing a key commit b48d96652626b315229b1b82c6270eead6a77a6d upstream. When we remove a key, we put a key index which was supposed to tell the fw that we are actually removing the key. But instead the fw took that index as a valid index and messed up the SRAM of the device. This memory corruption on the device mangled the data of the SCD. The impact on the user is that SCD queue 2 got stuck after having removed keys. Reported-by: Paul Bolle Signed-off-by: Emmanuel Grumbach Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlegacy/4965-mac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index c46275a92565..9aa48074ee20 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -3405,7 +3405,7 @@ il4965_remove_dynamic_key(struct il_priv *il, return 0; } - if (il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) { + if (il->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_INVALID) { IL_WARN("Removing wrong key %d 0x%x\n", keyconf->keyidx, key_flags); spin_unlock_irqrestore(&il->sta_lock, flags); @@ -3420,7 +3420,7 @@ il4965_remove_dynamic_key(struct il_priv *il, memset(&il->stations[sta_id].sta.key, 0, sizeof(struct il4965_keyinfo)); il->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; - il->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET; + il->stations[sta_id].sta.key.key_offset = keyconf->hw_key_idx; il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; -- GitLab From c8ed7cf355f41b649524029c49f101d878499482 Mon Sep 17 00:00:00 2001 From: Federico Fuga Date: Mon, 16 Jul 2012 10:36:51 +0300 Subject: [PATCH 0018/1799] rpmsg: fix dependency on initialization order commit 9634252617441991b01dacaf4040866feecaf36f upstream. When rpmsg drivers are built into the kernel, they must not initialize before the rpmsg bus does, otherwise they'd trigger a BUG() in drivers/base/driver.c line 169 (driver_register()). To fix that, and to stop depending on arbitrary linkage ordering of those built-in rpmsg drivers, we make the rpmsg bus initialize at subsys_initcall. Signed-off-by: Federico Fuga [ohad: rewrite the commit log] Signed-off-by: Ohad Ben-Cohen Signed-off-by: Greg Kroah-Hartman --- drivers/rpmsg/virtio_rpmsg_bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 39d3aa41adda..f56c8ba3a861 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -1085,7 +1085,7 @@ static int __init rpmsg_init(void) return ret; } -module_init(rpmsg_init); +subsys_initcall(rpmsg_init); static void __exit rpmsg_fini(void) { -- GitLab From 3cf16f7e388934d4458d0d6cebdf752e4424f226 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 2 Jul 2012 14:42:03 +0300 Subject: [PATCH 0019/1799] mac80211: destroy assoc_data correctly if assoc fails commit 10a9109f2705fdc3caa94d768b2559587a9a050c upstream. If association failed due to internal error (e.g. no supported rates IE), we call ieee80211_destroy_assoc_data() with assoc=true, while we actually reject the association. This results in the BSSID not being zeroed out. After passing assoc=false, we no longer have to call sta_info_destroy_addr() explicitly. While on it, move the "associated" message after the assoc_success check. Signed-off-by: Eliad Peller Reviewed-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/mlme.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1197e8dd5b01..d132b98bd1c1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2183,15 +2183,13 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, sdata->name, mgmt->sa, status_code); ieee80211_destroy_assoc_data(sdata, false); } else { - printk(KERN_DEBUG "%s: associated\n", sdata->name); - if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { /* oops -- internal error -- send timeout for now */ - ieee80211_destroy_assoc_data(sdata, true); - sta_info_destroy_addr(sdata, mgmt->bssid); + ieee80211_destroy_assoc_data(sdata, false); cfg80211_put_bss(*bss); return RX_MGMT_CFG80211_ASSOC_TIMEOUT; } + printk(KERN_DEBUG "%s: associated\n", sdata->name); /* * destroy assoc_data afterwards, as otherwise an idle -- GitLab From b98522a7cf0ff60bcf49330d9467089515cf9dad Mon Sep 17 00:00:00 2001 From: Deepak Sikri Date: Sun, 8 Jul 2012 21:14:45 +0000 Subject: [PATCH 0020/1799] stmmac: Fix for nfs hang on multiple reboot commit 8e83989106562326bfd6aaf92174fe138efd026b upstream. It was observed that during multiple reboots nfs hangs. The status of receive descriptors shows that all the descriptors were in control of CPU, and none were assigned to DMA. Also the DMA status register confirmed that the Rx buffer is unavailable. This patch adds the fix for the same by adding the memory barriers to ascertain that the all instructions before enabling the Rx or Tx DMA are completed which involves the proper setting of the ownership bit in DMA descriptors. Signed-off-by: Deepak Sikri Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 48d56da62f08..9bdfaba4e308 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1158,6 +1158,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion); wmb(); priv->hw->desc->set_tx_owner(desc); + wmb(); } /* Interrupt on completition only for the latest segment */ @@ -1173,6 +1174,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) /* To avoid raise condition */ priv->hw->desc->set_tx_owner(first); + wmb(); priv->cur_tx++; @@ -1236,6 +1238,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) } wmb(); priv->hw->desc->set_rx_owner(p + entry); + wmb(); } } -- GitLab From f4e2229ea5d49e338fce36b2c36f22b525fbeff6 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 9 Jul 2012 10:52:43 +0000 Subject: [PATCH 0021/1799] bonding: debugfs and network namespaces are incompatible commit 96ca7ffe748bf91f851e6aa4479aa11c8b1122ba upstream. The bonding debugfs support has been broken in the presence of network namespaces since it has been added. The debugfs support does not handle multiple bonding devices with the same name in different network namespaces. I haven't had any bug reports, and I'm not interested in getting any. Disable the debugfs support when network namespaces are enabled. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/bonding/bond_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c index 3680aa251dea..2cf084eb9d52 100644 --- a/drivers/net/bonding/bond_debugfs.c +++ b/drivers/net/bonding/bond_debugfs.c @@ -6,7 +6,7 @@ #include "bonding.h" #include "bond_alb.h" -#ifdef CONFIG_DEBUG_FS +#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_NET_NS) #include #include -- GitLab From d418f998832c7fd8f783e05cec7da6125720360d Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 9 Jul 2012 10:51:45 +0000 Subject: [PATCH 0022/1799] bonding: Manage /proc/net/bonding/ entries from the netdev events commit a64d49c3dd504b685f9742a2f3dcb11fb8e4345f upstream. It was recently reported that moving a bonding device between network namespaces causes warnings from /proc. It turns out after the move we were trying to add and to remove the /proc/net/bonding entries from the wrong network namespace. Move the bonding /proc registration code into the NETDEV_REGISTER and NETDEV_UNREGISTER events where the proc registration and unregistration will always happen at the right time. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/bonding/bond_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index a579a2f57c55..318a62a4db52 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3218,6 +3218,12 @@ static int bond_master_netdev_event(unsigned long event, switch (event) { case NETDEV_CHANGENAME: return bond_event_changename(event_bond); + case NETDEV_UNREGISTER: + bond_remove_proc_entry(event_bond); + break; + case NETDEV_REGISTER: + bond_create_proc_entry(event_bond); + break; default: break; } @@ -4402,8 +4408,6 @@ static void bond_uninit(struct net_device *bond_dev) bond_work_cancel_all(bond); - bond_remove_proc_entry(bond); - bond_debug_unregister(bond); __hw_addr_flush(&bond->mc_list); @@ -4805,7 +4809,6 @@ static int bond_init(struct net_device *bond_dev) bond_set_lockdep_class(bond_dev); - bond_create_proc_entry(bond); list_add_tail(&bond->bond_list, &bn->dev_list); bond_prepare_sysfs_group(bond); -- GitLab From edb5132a255e3f594b662018acced9037c6989b5 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Tue, 10 Jul 2012 09:43:57 -0700 Subject: [PATCH 0023/1799] Input: bcm5974 - Add support for 2012 MacBook Pro Retina commit 3dde22a98e94eb18527f0ff0068fb2fb945e58d4 upstream. Add support for the 15'' MacBook Pro Retina model (MacBookPro10,1). Patch originally written by clipcarl (forums.opensuse.org). Signed-off-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/bcm5974.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index f9e2758b9f46..e410b98c2271 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -79,6 +79,10 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254 +/* MacbookPro10,1 (unibody, June 2012) */ +#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262 +#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263 +#define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264 #define BCM5974_DEVICE(prod) { \ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ @@ -128,6 +132,10 @@ static const struct usb_device_id bcm5974_table[] = { BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS), + /* MacbookPro10,1 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), /* Terminating entry */ {} }; @@ -354,6 +362,18 @@ static const struct bcm5974_config bcm5974_config_table[] = { { DIM_X, DIM_X / SN_COORD, -4620, 5140 }, { DIM_Y, DIM_Y / SN_COORD, -150, 6600 } }, + { + USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI, + USB_DEVICE_ID_APPLE_WELLSPRING7_ISO, + USB_DEVICE_ID_APPLE_WELLSPRING7_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, -4750, 5280 }, + { DIM_Y, DIM_Y / SN_COORD, -150, 6730 } + }, {} }; -- GitLab From abee143740c3388cc34869b9320aed3fa28f9cdb Mon Sep 17 00:00:00 2001 From: Yuri Khan Date: Wed, 11 Jul 2012 00:49:18 -0700 Subject: [PATCH 0024/1799] Input: xpad - handle all variations of Mad Catz Beat Pad commit 3ffb62cb9ac2430c2504c6ff9727d0f2476ef0bd upstream. The device should be handled by xpad driver instead of generic HID driver. Signed-off-by: Yuri Khan Acked-by: Jiri Kosina Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 +++ drivers/input/joystick/xpad.c | 1 + 3 files changed, 5 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 4da66b4b977c..b54a57a733de 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1914,6 +1914,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MCT) }, { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) }, { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) }, { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index e39aecb1f9f2..b32f67c0b6cf 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -509,6 +509,9 @@ #define USB_DEVICE_ID_CRYSTALTOUCH 0x0006 #define USB_DEVICE_ID_CRYSTALTOUCH_DUAL 0x0007 +#define USB_VENDOR_ID_MADCATZ 0x0738 +#define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540 + #define USB_VENDOR_ID_MCC 0x09db #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index fd7a0d5bc94d..0369364092d2 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -238,6 +238,7 @@ static struct usb_device_id xpad_table [] = { XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ + { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */ XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */ XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ -- GitLab From 07793cd472f688c266eedff79f46f6c512d84ce4 Mon Sep 17 00:00:00 2001 From: Ilia Katsnelson Date: Wed, 11 Jul 2012 00:54:20 -0700 Subject: [PATCH 0025/1799] Input: xpad - add signature for Razer Onza Tournament Edition commit cc71a7e899cc6b2ff41e1be48756782ed004d802 upstream. Signed-off-by: Ilia Katsnelson Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/joystick/xpad.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 0369364092d2..e0665281feee 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -164,6 +164,7 @@ static const struct xpad_device { { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1689, 0xfd00, "Razer Onza Tournament Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } }; @@ -244,7 +245,8 @@ static struct usb_device_id xpad_table [] = { XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */ XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */ - XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ + XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ + XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ { } }; -- GitLab From 256cf2738cb242af70ea6f6117446a98ed949a9c Mon Sep 17 00:00:00 2001 From: Yuri Khan Date: Wed, 11 Jul 2012 22:12:31 -0700 Subject: [PATCH 0026/1799] Input: xpad - add Andamiro Pump It Up pad commit e76b8ee25e034ab601b525abb95cea14aa167ed3 upstream. I couldn't find the vendor ID in any of the online databases, but this mat has a Pump It Up logo on the top side of the controller compartment, and a disclaimer stating that Andamiro will not be liable on the bottom. Signed-off-by: Yuri Khan Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/joystick/xpad.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index e0665281feee..42f7b257feb0 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -142,6 +142,7 @@ static const struct xpad_device { { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX }, { 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX }, + { 0x0d2f, 0x0002, "Andamiro Pump It Up pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX }, { 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX }, { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX }, -- GitLab From c5e42b8d692877676fc3ba9fdf3dbcbd723b4c2b Mon Sep 17 00:00:00 2001 From: Ryan Bourgeois Date: Tue, 10 Jul 2012 09:43:33 -0700 Subject: [PATCH 0027/1799] HID: add support for 2012 MacBook Pro Retina commit b2e6ad7dfe26aac5bf136962d0b11d180b820d44 upstream. Add support for the 15'' MacBook Pro Retina. The keyboard is the same as recent models. The patch needs to be synchronized with the bcm5974 patch for the trackpad - as usual. Patch originally written by clipcarl (forums.opensuse.org). [rydberg@euromail.se: Amended mouse ignore lines] Signed-off-by: Ryan Bourgeois Signed-off-by: Henrik Rydberg Acked-by: Jiri Kosina Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-apple.c | 6 ++++++ drivers/hid/hid-core.c | 6 ++++++ drivers/hid/hid-ids.h | 3 +++ 3 files changed, 15 insertions(+) diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 299d23871122..899c71200bd9 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -514,6 +514,12 @@ 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_WELLSPRING5A_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_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 b54a57a733de..054677b3d168 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1379,6 +1379,9 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_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) }, @@ -2009,6 +2012,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_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 b32f67c0b6cf..dfd40981c86a 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -125,6 +125,9 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI 0x024c #define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO 0x024d #define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS 0x024e +#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262 +#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263 +#define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264 #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 -- GitLab From 871d4f5e1d82cf0ad56ae076c8535004e7837416 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Fri, 8 Jun 2012 14:04:06 +0100 Subject: [PATCH 0028/1799] clk: Check parent for NULL in clk_change_rate commit bf47b4fd8f9f81cd5ce40e1945c6334d088226d1 upstream. clk_change_rate() is accessing parent's rate without checking if the parent exists at all. In case of root clocks this will cause NULL pointer dereference. This patch follows what clk_calc_new_rates() does in such situation. Signed-off-by: Pawel Moll Signed-off-by: Mike Turquette Signed-off-by: Greg Kroah-Hartman --- drivers/clk/clk.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 2da025ee226d..7f1ea568b444 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -834,18 +834,21 @@ static void clk_change_rate(struct clk *clk) { struct clk *child; unsigned long old_rate; + unsigned long best_parent_rate = 0; struct hlist_node *tmp; old_rate = clk->rate; + if (clk->parent) + best_parent_rate = clk->parent->rate; + if (clk->ops->set_rate) clk->ops->set_rate(clk->hw, clk->new_rate); if (clk->ops->recalc_rate) - clk->rate = clk->ops->recalc_rate(clk->hw, - clk->parent->rate); + clk->rate = clk->ops->recalc_rate(clk->hw, best_parent_rate); else - clk->rate = clk->parent->rate; + clk->rate = best_parent_rate; if (clk->notifier_count && old_rate != clk->rate) __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); -- GitLab From 738c88c1b8ebe16c3ecd1694871474b470275d82 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Jun 2012 10:55:44 +0200 Subject: [PATCH 0029/1799] cfg80211: check iface combinations only when iface is running commit f8cdddb8d61d16a156229f0910f7ecfc7a82c003 upstream. Don't validate interface combinations on a stopped interface. Otherwise we might end up being able to create a new interface with a certain type, but won't be able to change an existing interface into that type. This also skips some other functions when interface is stopped and changing interface type. Signed-off-by: Michal Kazior Signed-off-by: Johannes Berg [Fixes regression introduced by cherry pick of 463454b5dbd8] Signed-off-by: Paul Gortmaker --- net/wireless/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/util.c b/net/wireless/util.c index b5b689070bab..0eb6cc0c77d8 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -805,7 +805,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, ntype == NL80211_IFTYPE_P2P_CLIENT)) return -EBUSY; - if (ntype != otype) { + if (ntype != otype && netif_running(dev)) { err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, ntype); if (err) -- GitLab From 5e5006e64cae9603841405af9febb67064869d83 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 17 Jul 2012 02:39:50 -0400 Subject: [PATCH 0030/1799] hrtimer: Provide clock_was_set_delayed() This is a backport of f55a6faa384304c89cfef162768e88374d3312cb clock_was_set() cannot be called from hard interrupt context because it calls on_each_cpu(). For fixing the widely reported leap seconds issue it is necessary to call it from hard interrupt context, i.e. the timer tick code, which does the timekeeping updates. Provide a new function which denotes it in the hrtimer cpu base structure of the cpu on which it is called and raise the hrtimer softirq. We then execute the clock_was_set() notificiation from softirq context in run_hrtimer_softirq(). The hrtimer softirq is rarely used, so polling the flag there is not a performance issue. [ tglx: Made it depend on CONFIG_HIGH_RES_TIMERS. We really should get rid of all this ifdeffery ASAP ] Signed-off-by: John Stultz Reported-by: Jan Engelhardt Reviewed-by: Ingo Molnar Acked-by: Peter Zijlstra Acked-by: Prarit Bhargava Link: http://lkml.kernel.org/r/1341960205-56738-2-git-send-email-johnstul@us.ibm.com Signed-off-by: Thomas Gleixner Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- include/linux/hrtimer.h | 9 ++++++++- kernel/hrtimer.c | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index fd0dc30c9f15..c9ec9400ee5b 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -165,6 +165,7 @@ enum hrtimer_base_type { * @lock: lock protecting the base and associated clock bases * and timers * @active_bases: Bitfield to mark bases with active timers + * @clock_was_set: Indicates that clock was set from irq context. * @expires_next: absolute time of the next event which was scheduled * via clock_set_next_event() * @hres_active: State of high resolution mode @@ -177,7 +178,8 @@ enum hrtimer_base_type { */ struct hrtimer_cpu_base { raw_spinlock_t lock; - unsigned long active_bases; + unsigned int active_bases; + unsigned int clock_was_set; #ifdef CONFIG_HIGH_RES_TIMERS ktime_t expires_next; int hres_active; @@ -286,6 +288,8 @@ extern void hrtimer_peek_ahead_timers(void); # define MONOTONIC_RES_NSEC HIGH_RES_NSEC # define KTIME_MONOTONIC_RES KTIME_HIGH_RES +extern void clock_was_set_delayed(void); + #else # define MONOTONIC_RES_NSEC LOW_RES_NSEC @@ -306,6 +310,9 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer) { return 0; } + +static inline void clock_was_set_delayed(void) { } + #endif extern void clock_was_set(void); diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index ae34bf51682b..3c24fb2c25c8 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -717,6 +717,19 @@ static int hrtimer_switch_to_hres(void) return 1; } +/* + * Called from timekeeping code to reprogramm the hrtimer interrupt + * device. If called from the timer interrupt context we defer it to + * softirq context. + */ +void clock_was_set_delayed(void) +{ + struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); + + cpu_base->clock_was_set = 1; + __raise_softirq_irqoff(HRTIMER_SOFTIRQ); +} + #else static inline int hrtimer_hres_active(void) { return 0; } @@ -1395,6 +1408,13 @@ void hrtimer_peek_ahead_timers(void) static void run_hrtimer_softirq(struct softirq_action *h) { + struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); + + if (cpu_base->clock_was_set) { + cpu_base->clock_was_set = 0; + clock_was_set(); + } + hrtimer_peek_ahead_timers(); } -- GitLab From 2e947d469fba2c2036ff50a2e58a1875ab2ea6b6 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 17 Jul 2012 02:39:51 -0400 Subject: [PATCH 0031/1799] timekeeping: Fix leapsecond triggered load spike issue This is a backport of 4873fa070ae84a4115f0b3c9dfabc224f1bc7c51 The timekeeping code misses an update of the hrtimer subsystem after a leap second happened. Due to that timers based on CLOCK_REALTIME are either expiring a second early or late depending on whether a leap second has been inserted or deleted until an operation is initiated which causes that update. Unless the update happens by some other means this discrepancy between the timekeeping and the hrtimer data stays forever and timers are expired either early or late. The reported immediate workaround - $ data -s "`date`" - is causing a call to clock_was_set() which updates the hrtimer data structures. See: http://www.sheeri.com/content/mysql-and-leap-second-high-cpu-and-fix Add the missing clock_was_set() call to update_wall_time() in case of a leap second event. The actual update is deferred to softirq context as the necessary smp function call cannot be invoked from hard interrupt context. Signed-off-by: John Stultz Reported-by: Jan Engelhardt Reviewed-by: Ingo Molnar Acked-by: Peter Zijlstra Acked-by: Prarit Bhargava Link: http://lkml.kernel.org/r/1341960205-56738-3-git-send-email-johnstul@us.ibm.com Signed-off-by: Thomas Gleixner Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- kernel/time/timekeeping.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index d42574df7c51..9588f0c3c36a 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -965,6 +965,8 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) leap = second_overflow(timekeeper.xtime.tv_sec); timekeeper.xtime.tv_sec += leap; timekeeper.wall_to_monotonic.tv_sec -= leap; + if (leap) + clock_was_set_delayed(); } /* Accumulate raw time */ @@ -1081,6 +1083,8 @@ static void update_wall_time(void) leap = second_overflow(timekeeper.xtime.tv_sec); timekeeper.xtime.tv_sec += leap; timekeeper.wall_to_monotonic.tv_sec -= leap; + if (leap) + clock_was_set_delayed(); } timekeeping_update(false); -- GitLab From 7d1f07113b1b32da1eabce0dc74d9f96bbb7b90a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 17 Jul 2012 02:39:52 -0400 Subject: [PATCH 0032/1799] timekeeping: Maintain ktime_t based offsets for hrtimers This is a backport of 5b9fe759a678e05be4937ddf03d50e950207c1c0 We need to update the hrtimer clock offsets from the hrtimer interrupt context. To avoid conversions from timespec to ktime_t maintain a ktime_t based representation of those offsets in the timekeeper. This puts the conversion overhead into the code which updates the underlying offsets and provides fast accessible values in the hrtimer interrupt. Signed-off-by: Thomas Gleixner Signed-off-by: John Stultz Reviewed-by: Ingo Molnar Acked-by: Peter Zijlstra Acked-by: Prarit Bhargava Link: http://lkml.kernel.org/r/1341960205-56738-4-git-send-email-johnstul@us.ibm.com Signed-off-by: Thomas Gleixner Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- kernel/time/timekeeping.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 9588f0c3c36a..615ec8d14981 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -70,6 +70,12 @@ struct timekeeper { /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ struct timespec raw_time; + /* Offset clock monotonic -> clock realtime */ + ktime_t offs_real; + + /* Offset clock monotonic -> clock boottime */ + ktime_t offs_boot; + /* Seqlock for all timekeeper values */ seqlock_t lock; }; @@ -172,6 +178,14 @@ static inline s64 timekeeping_get_ns_raw(void) return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift); } +static void update_rt_offset(void) +{ + struct timespec tmp, *wtm = &timekeeper.wall_to_monotonic; + + set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec); + timekeeper.offs_real = timespec_to_ktime(tmp); +} + /* must hold write on timekeeper.lock */ static void timekeeping_update(bool clearntp) { @@ -179,6 +193,7 @@ static void timekeeping_update(bool clearntp) timekeeper.ntp_error = 0; ntp_clear(); } + update_rt_offset(); update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, timekeeper.clock, timekeeper.mult); } @@ -606,6 +621,7 @@ void __init timekeeping_init(void) } set_normalized_timespec(&timekeeper.wall_to_monotonic, -boot.tv_sec, -boot.tv_nsec); + update_rt_offset(); timekeeper.total_sleep_time.tv_sec = 0; timekeeper.total_sleep_time.tv_nsec = 0; write_sequnlock_irqrestore(&timekeeper.lock, flags); @@ -614,6 +630,12 @@ void __init timekeeping_init(void) /* time in seconds when suspend began */ static struct timespec timekeeping_suspend_time; +static void update_sleep_time(struct timespec t) +{ + timekeeper.total_sleep_time = t; + timekeeper.offs_boot = timespec_to_ktime(t); +} + /** * __timekeeping_inject_sleeptime - Internal function to add sleep interval * @delta: pointer to a timespec delta value @@ -632,8 +654,7 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta) timekeeper.xtime = timespec_add(timekeeper.xtime, *delta); timekeeper.wall_to_monotonic = timespec_sub(timekeeper.wall_to_monotonic, *delta); - timekeeper.total_sleep_time = timespec_add( - timekeeper.total_sleep_time, *delta); + update_sleep_time(timespec_add(timekeeper.total_sleep_time, *delta)); } -- GitLab From dd3cded0f516201d3b72999e588a6d67e00cb82f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 17 Jul 2012 02:39:53 -0400 Subject: [PATCH 0033/1799] hrtimers: Move lock held region in hrtimer_interrupt() This is a backport of 196951e91262fccda81147d2bcf7fdab08668b40 We need to update the base offsets from this code and we need to do that under base->lock. Move the lock held region around the ktime_get() calls. The ktime_get() calls are going to be replaced with a function which gets the time and the offsets atomically. Signed-off-by: Thomas Gleixner Reviewed-by: Ingo Molnar Acked-by: Peter Zijlstra Acked-by: Prarit Bhargava Signed-off-by: John Stultz Link: http://lkml.kernel.org/r/1341960205-56738-6-git-send-email-johnstul@us.ibm.com Signed-off-by: Thomas Gleixner Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- kernel/hrtimer.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 3c24fb2c25c8..8f320af837b5 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -1263,11 +1263,10 @@ void hrtimer_interrupt(struct clock_event_device *dev) cpu_base->nr_events++; dev->next_event.tv64 = KTIME_MAX; + raw_spin_lock(&cpu_base->lock); entry_time = now = ktime_get(); retry: expires_next.tv64 = KTIME_MAX; - - raw_spin_lock(&cpu_base->lock); /* * We set expires_next to KTIME_MAX here with cpu_base->lock * held to prevent that a timer is enqueued in our queue via @@ -1344,6 +1343,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) * interrupt routine. We give it 3 attempts to avoid * overreacting on some spurious event. */ + raw_spin_lock(&cpu_base->lock); now = ktime_get(); cpu_base->nr_retries++; if (++retries < 3) @@ -1356,6 +1356,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) */ cpu_base->nr_hangs++; cpu_base->hang_detected = 1; + raw_spin_unlock(&cpu_base->lock); delta = ktime_sub(now, entry_time); if (delta.tv64 > cpu_base->max_hang_time.tv64) cpu_base->max_hang_time = delta; -- GitLab From 765bdc4d82fadcddfec19222a545e904633c7816 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 17 Jul 2012 02:39:54 -0400 Subject: [PATCH 0034/1799] timekeeping: Provide hrtimer update function This is a backport of f6c06abfb3972ad4914cef57d8348fcb2932bc3b To finally fix the infamous leap second issue and other race windows caused by functions which change the offsets between the various time bases (CLOCK_MONOTONIC, CLOCK_REALTIME and CLOCK_BOOTTIME) we need a function which atomically gets the current monotonic time and updates the offsets of CLOCK_REALTIME and CLOCK_BOOTTIME with minimalistic overhead. The previous patch which provides ktime_t offsets allows us to make this function almost as cheap as ktime_get() which is going to be replaced in hrtimer_interrupt(). Signed-off-by: Thomas Gleixner Reviewed-by: Ingo Molnar Acked-by: Peter Zijlstra Acked-by: Prarit Bhargava Signed-off-by: John Stultz Link: http://lkml.kernel.org/r/1341960205-56738-7-git-send-email-johnstul@us.ibm.com Signed-off-by: Thomas Gleixner Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- include/linux/hrtimer.h | 1 + kernel/time/timekeeping.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index c9ec9400ee5b..cc07d2777bbe 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -327,6 +327,7 @@ extern ktime_t ktime_get(void); extern ktime_t ktime_get_real(void); extern ktime_t ktime_get_boottime(void); extern ktime_t ktime_get_monotonic_offset(void); +extern ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot); DECLARE_PER_CPU(struct tick_device, tick_cpu_device); diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 615ec8d14981..62e12c354ef9 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1273,6 +1273,40 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, } while (read_seqretry(&timekeeper.lock, seq)); } +#ifdef CONFIG_HIGH_RES_TIMERS +/** + * ktime_get_update_offsets - hrtimer helper + * @offs_real: pointer to storage for monotonic -> realtime offset + * @offs_boot: pointer to storage for monotonic -> boottime offset + * + * Returns current monotonic time and updates the offsets + * Called from hrtimer_interupt() or retrigger_next_event() + */ +ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) +{ + ktime_t now; + unsigned int seq; + u64 secs, nsecs; + + do { + seq = read_seqbegin(&timekeeper.lock); + + secs = timekeeper.xtime.tv_sec; + nsecs = timekeeper.xtime.tv_nsec; + nsecs += timekeeping_get_ns(); + /* If arch requires, add in gettimeoffset() */ + nsecs += arch_gettimeoffset(); + + *offs_real = timekeeper.offs_real; + *offs_boot = timekeeper.offs_boot; + } while (read_seqretry(&timekeeper.lock, seq)); + + now = ktime_add_ns(ktime_set(secs, 0), nsecs); + now = ktime_sub(now, *offs_real); + return now; +} +#endif + /** * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format */ -- GitLab From 6321a0a1a3a9d6c9cbd73d9a4159a97ac3bc0919 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 17 Jul 2012 02:39:55 -0400 Subject: [PATCH 0035/1799] hrtimer: Update hrtimer base offsets each hrtimer_interrupt This is a backport of 5baefd6d84163443215f4a99f6a20f054ef11236 The update of the hrtimer base offsets on all cpus cannot be made atomically from the timekeeper.lock held and interrupt disabled region as smp function calls are not allowed there. clock_was_set(), which enforces the update on all cpus, is called either from preemptible process context in case of do_settimeofday() or from the softirq context when the offset modification happened in the timer interrupt itself due to a leap second. In both cases there is a race window for an hrtimer interrupt between dropping timekeeper lock, enabling interrupts and clock_was_set() issuing the updates. Any interrupt which arrives in that window will see the new time but operate on stale offsets. So we need to make sure that an hrtimer interrupt always sees a consistent state of time and offsets. ktime_get_update_offsets() allows us to get the current monotonic time and update the per cpu hrtimer base offsets from hrtimer_interrupt() to capture a consistent state of monotonic time and the offsets. The function replaces the existing ktime_get() calls in hrtimer_interrupt(). The overhead of the new function vs. ktime_get() is minimal as it just adds two store operations. This ensures that any changes to realtime or boottime offsets are noticed and stored into the per-cpu hrtimer base structures, prior to any hrtimer expiration and guarantees that timers are not expired early. Signed-off-by: John Stultz Reviewed-by: Ingo Molnar Acked-by: Peter Zijlstra Acked-by: Prarit Bhargava Link: http://lkml.kernel.org/r/1341960205-56738-8-git-send-email-johnstul@us.ibm.com Signed-off-by: Thomas Gleixner Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- kernel/hrtimer.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 8f320af837b5..6db7a5ed52b5 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -657,6 +657,14 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, return 0; } +static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) +{ + ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset; + ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset; + + return ktime_get_update_offsets(offs_real, offs_boot); +} + /* * Retrigger next event is called after clock was set * @@ -665,22 +673,12 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, static void retrigger_next_event(void *arg) { struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); - struct timespec realtime_offset, xtim, wtm, sleep; if (!hrtimer_hres_active()) return; - /* Optimized out for !HIGH_RES */ - get_xtime_and_monotonic_and_sleep_offset(&xtim, &wtm, &sleep); - set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec); - - /* Adjust CLOCK_REALTIME offset */ raw_spin_lock(&base->lock); - base->clock_base[HRTIMER_BASE_REALTIME].offset = - timespec_to_ktime(realtime_offset); - base->clock_base[HRTIMER_BASE_BOOTTIME].offset = - timespec_to_ktime(sleep); - + hrtimer_update_base(base); hrtimer_force_reprogram(base, 0); raw_spin_unlock(&base->lock); } @@ -710,7 +708,6 @@ static int hrtimer_switch_to_hres(void) base->clock_base[i].resolution = KTIME_HIGH_RES; tick_setup_sched_timer(); - /* "Retrigger" the interrupt to get things going */ retrigger_next_event(NULL); local_irq_restore(flags); @@ -1264,7 +1261,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) dev->next_event.tv64 = KTIME_MAX; raw_spin_lock(&cpu_base->lock); - entry_time = now = ktime_get(); + entry_time = now = hrtimer_update_base(cpu_base); retry: expires_next.tv64 = KTIME_MAX; /* @@ -1342,9 +1339,12 @@ void hrtimer_interrupt(struct clock_event_device *dev) * We need to prevent that we loop forever in the hrtimer * interrupt routine. We give it 3 attempts to avoid * overreacting on some spurious event. + * + * Acquire base lock for updating the offsets and retrieving + * the current time. */ raw_spin_lock(&cpu_base->lock); - now = ktime_get(); + now = hrtimer_update_base(cpu_base); cpu_base->nr_retries++; if (++retries < 3) goto retry; -- GitLab From 3cdeda1e763ccb2287c6ee76ece14145027653a9 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 17 Jul 2012 02:39:56 -0400 Subject: [PATCH 0036/1799] timekeeping: Add missing update call in timekeeping_resume() This is a backport of 3e997130bd2e8c6f5aaa49d6e3161d4d29b43ab0 The leap second rework unearthed another issue of inconsistent data. On timekeeping_resume() the timekeeper data is updated, but nothing calls timekeeping_update(), so now the update code in the timer interrupt sees stale values. This has been the case before those changes, but then the timer interrupt was using stale data as well so this went unnoticed for quite some time. Add the missing update call, so all the data is consistent everywhere. Reported-by: Andreas Schwab Reported-and-tested-by: "Rafael J. Wysocki" Reported-and-tested-by: Martin Steigerwald Cc: John Stultz Cc: Ingo Molnar Cc: Peter Zijlstra , Cc: Prarit Bhargava Signed-off-by: Thomas Gleixner Signed-off-by: John Stultz Signed-off-by: Linus Torvalds Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- kernel/time/timekeeping.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 62e12c354ef9..7c50de83b6fd 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -719,6 +719,7 @@ static void timekeeping_resume(void) timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); timekeeper.ntp_error = 0; timekeeping_suspended = 0; + timekeeping_update(false); write_sequnlock_irqrestore(&timekeeper.lock, flags); touch_softlockup_watchdog(); -- GitLab From 016e7d822a72c4cbcbf7e4bc6d590cf50879ec26 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Thu, 10 May 2012 19:45:51 +0200 Subject: [PATCH 0037/1799] NFC: Export nfc.h to userland commit dbd4fcaf8d664fab4163b1f8682e41ad8bff3444 upstream. The netlink commands and attributes, along with the socket structure definitions need to be exported. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville 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 50f55c77f8b4..f2f73f9b986f 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -272,6 +272,7 @@ header-y += netfilter_ipv4.h header-y += netfilter_ipv6.h header-y += netlink.h header-y += netrom.h +header-y += nfc.h header-y += nfs.h header-y += nfs2.h header-y += nfs3.h -- GitLab From 1c8f63c2758096c3b6425f4ecb274901151d6f17 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 19 Jul 2012 12:11:49 -0700 Subject: [PATCH 0038/1799] Linux 3.4.6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a2e69a08b7e6..5d0edcbd8786 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 5 +SUBLEVEL = 6 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 2ac8a0f58a8782ff8024404a579eee260e8b2010 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 19 Jul 2012 15:59:18 +1000 Subject: [PATCH 0039/1799] md: avoid crash when stopping md array races with closing other open fds. commit a05b7ea03d72f36edb0cec05e8893803335c61a0 upstream. md will refuse to stop an array if any other fd (or mounted fs) is using it. When any fs is unmounted of when the last open fd is closed all pending IO will be flushed (e.g. sync_blockdev call in __blkdev_put) so there will be no pending IO to worry about when the array is stopped. However in order to send the STOP_ARRAY ioctl to stop the array one must first get and open fd on the block device. If some fd is being used to write to the block device and it is closed after mdadm open the block device, but before mdadm issues the STOP_ARRAY ioctl, then there will be no last-close on the md device so __blkdev_put will not call sync_blockdev. If this happens, then IO can still be in-flight while md tears down the array and bad things can happen (use-after-free and subsequent havoc). So in the case where do_md_stop is being called from an open file descriptor, call sync_block after taking the mutex to ensure there will be no new openers. This is needed when setting a read-write device to read-only too. Reported-by: majianpeng Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 2b30ffdb81b2..9ee8ce3e9650 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3744,8 +3744,8 @@ array_state_show(struct mddev *mddev, char *page) return sprintf(page, "%s\n", array_states[st]); } -static int do_md_stop(struct mddev * mddev, int ro, int is_open); -static int md_set_readonly(struct mddev * mddev, int is_open); +static int do_md_stop(struct mddev * mddev, int ro, struct block_device *bdev); +static int md_set_readonly(struct mddev * mddev, struct block_device *bdev); static int do_md_run(struct mddev * mddev); static int restart_array(struct mddev *mddev); @@ -3761,14 +3761,14 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) /* stopping an active array */ if (atomic_read(&mddev->openers) > 0) return -EBUSY; - err = do_md_stop(mddev, 0, 0); + err = do_md_stop(mddev, 0, NULL); break; case inactive: /* stopping an active array */ if (mddev->pers) { if (atomic_read(&mddev->openers) > 0) return -EBUSY; - err = do_md_stop(mddev, 2, 0); + err = do_md_stop(mddev, 2, NULL); } else err = 0; /* already inactive */ break; @@ -3776,7 +3776,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) break; /* not supported yet */ case readonly: if (mddev->pers) - err = md_set_readonly(mddev, 0); + err = md_set_readonly(mddev, NULL); else { mddev->ro = 1; set_disk_ro(mddev->gendisk, 1); @@ -3786,7 +3786,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) case read_auto: if (mddev->pers) { if (mddev->ro == 0) - err = md_set_readonly(mddev, 0); + err = md_set_readonly(mddev, NULL); else if (mddev->ro == 1) err = restart_array(mddev); if (err == 0) { @@ -5124,15 +5124,17 @@ void md_stop(struct mddev *mddev) } EXPORT_SYMBOL_GPL(md_stop); -static int md_set_readonly(struct mddev *mddev, int is_open) +static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) { int err = 0; mutex_lock(&mddev->open_mutex); - if (atomic_read(&mddev->openers) > is_open) { + if (atomic_read(&mddev->openers) > !!bdev) { printk("md: %s still in use.\n",mdname(mddev)); err = -EBUSY; goto out; } + if (bdev) + sync_blockdev(bdev); if (mddev->pers) { __md_stop_writes(mddev); @@ -5154,18 +5156,26 @@ static int md_set_readonly(struct mddev *mddev, int is_open) * 0 - completely stop and dis-assemble array * 2 - stop but do not disassemble array */ -static int do_md_stop(struct mddev * mddev, int mode, int is_open) +static int do_md_stop(struct mddev * mddev, int mode, + struct block_device *bdev) { struct gendisk *disk = mddev->gendisk; struct md_rdev *rdev; mutex_lock(&mddev->open_mutex); - if (atomic_read(&mddev->openers) > is_open || + if (atomic_read(&mddev->openers) > !!bdev || mddev->sysfs_active) { printk("md: %s still in use.\n",mdname(mddev)); mutex_unlock(&mddev->open_mutex); return -EBUSY; } + if (bdev) + /* It is possible IO was issued on some other + * open file which was closed before we took ->open_mutex. + * As that was not the last close __blkdev_put will not + * have called sync_blockdev, so we must. + */ + sync_blockdev(bdev); if (mddev->pers) { if (mddev->ro) @@ -5239,7 +5249,7 @@ static void autorun_array(struct mddev *mddev) err = do_md_run(mddev); if (err) { printk(KERN_WARNING "md: do_md_run() returned %d\n", err); - do_md_stop(mddev, 0, 0); + do_md_stop(mddev, 0, NULL); } } @@ -6237,11 +6247,11 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, goto done_unlock; case STOP_ARRAY: - err = do_md_stop(mddev, 0, 1); + err = do_md_stop(mddev, 0, bdev); goto done_unlock; case STOP_ARRAY_RO: - err = md_set_readonly(mddev, 1); + err = md_set_readonly(mddev, bdev); goto done_unlock; case BLKROSET: -- GitLab From d8ae4bb4a1c12f9cfb373f215e624a9f1fca0767 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 19 Jul 2012 15:59:18 +1000 Subject: [PATCH 0040/1799] md/raid1: close some possible races on write errors during resync commit 58e94ae18478c08229626daece2fc108a4a23261 upstream. commit 4367af556133723d0f443e14ca8170d9447317cb md/raid1: clear bad-block record when write succeeds. Added a 'reschedule_retry' call possibility at the end of end_sync_write, but didn't add matching code at the end of sync_request_write. So if the writes complete very quickly, or scheduling makes it seem that way, then we can miss rescheduling the request and the resync could hang. Also commit 73d5c38a9536142e062c35997b044e89166e063b md: avoid races when stopping resync. Fix a race condition in this same code in end_sync_write but didn't make the change in sync_request_write. This patch updates sync_request_write to fix both of those. Patch is suitable for 3.1 and later kernels. Reported-by: Alexander Lyakas Original-version-by: Alexander Lyakas Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid1.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d1f74ab13966..d7add9d5bac2 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1821,8 +1821,14 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio) if (atomic_dec_and_test(&r1_bio->remaining)) { /* if we're here, all write(s) have completed, so clean up */ - md_done_sync(mddev, r1_bio->sectors, 1); - put_buf(r1_bio); + int s = r1_bio->sectors; + if (test_bit(R1BIO_MadeGood, &r1_bio->state) || + test_bit(R1BIO_WriteError, &r1_bio->state)) + reschedule_retry(r1_bio); + else { + put_buf(r1_bio); + md_done_sync(mddev, s, 1); + } } } -- GitLab From f952e137849253c0584a60cc2d73a220d9a091f8 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 6 Jul 2012 07:09:42 -0400 Subject: [PATCH 0041/1799] cifs: always update the inode cache with the results from a FIND_* commit cd60042cc1392e79410dc8de9e9c1abb38a29e57 upstream. When we get back a FIND_FIRST/NEXT result, we have some info about the dentry that we use to instantiate a new inode. We were ignoring and discarding that info when we had an existing dentry in the cache. Fix this by updating the inode in place when we find an existing dentry and the uniqueid is the same. Reported-and-Tested-by: Andrew Bartlett Reported-by: Bill Robertson Reported-by: Dion Edwards Signed-off-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/readdir.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 0a8224d1c4c5..a4217f02fab2 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -86,9 +86,12 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name, dentry = d_lookup(parent, name); if (dentry) { - /* FIXME: check for inode number changes? */ - if (dentry->d_inode != NULL) + inode = dentry->d_inode; + /* update inode in place if i_ino didn't change */ + if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) { + cifs_fattr_to_inode(inode, fattr); return dentry; + } d_drop(dentry); dput(dentry); } -- GitLab From c82cd13737cfab6cb9d1b31e624896e627f9c9e4 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 11 Jul 2012 09:09:35 -0400 Subject: [PATCH 0042/1799] cifs: on CONFIG_HIGHMEM machines, limit the rsize/wsize to the kmap space commit 3ae629d98bd5ed77585a878566f04f310adbc591 upstream. We currently rely on being able to kmap all of the pages in an async read or write request. If you're on a machine that has CONFIG_HIGHMEM set then that kmap space is limited, sometimes to as low as 512 slots. With 512 slots, we can only support up to a 2M r/wsize, and that's assuming that we can get our greedy little hands on all of them. There are other users however, so it's possible we'll end up stuck with a size that large. Since we can't handle a rsize or wsize larger than that currently, cap those options at the number of kmap slots we have. We could consider capping it even lower, but we currently default to a max of 1M. Might as well allow those luddites on 32 bit arches enough rope to hang themselves. A more robust fix would be to teach the send and receive routines how to contend with an array of pages so we don't need to marshal up a kvec array at all. That's a fairly significant overhaul though, so we'll need this limit in place until that's ready. Reported-by: Jian Li Signed-off-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/connect.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 402fa0f9bc01..87ce8af1ce40 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3348,6 +3348,18 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, #define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024) #define CIFS_DEFAULT_NON_POSIX_WSIZE (65536) +/* + * On hosts with high memory, we can't currently support wsize/rsize that are + * larger than we can kmap at once. Cap the rsize/wsize at + * LAST_PKMAP * PAGE_SIZE. We'll never be able to fill a read or write request + * larger than that anyway. + */ +#ifdef CONFIG_HIGHMEM +#define CIFS_KMAP_SIZE_LIMIT (LAST_PKMAP * PAGE_CACHE_SIZE) +#else /* CONFIG_HIGHMEM */ +#define CIFS_KMAP_SIZE_LIMIT (1<<24) +#endif /* CONFIG_HIGHMEM */ + static unsigned int cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) { @@ -3378,6 +3390,9 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) wsize = min_t(unsigned int, wsize, server->maxBuf - sizeof(WRITE_REQ) + 4); + /* limit to the amount that we can kmap at once */ + wsize = min_t(unsigned int, wsize, CIFS_KMAP_SIZE_LIMIT); + /* hard limit of CIFS_MAX_WSIZE */ wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE); @@ -3419,6 +3434,9 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) if (!(server->capabilities & CAP_LARGE_READ_X)) rsize = min_t(unsigned int, CIFSMaxBufSize, rsize); + /* limit to the amount that we can kmap at once */ + rsize = min_t(unsigned int, rsize, CIFS_KMAP_SIZE_LIMIT); + /* hard limit of CIFS_MAX_RSIZE */ rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE); -- GitLab From 815faab2c4b7deb2cc6495186307ceb0983214a9 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 16 Jul 2012 15:17:10 -0700 Subject: [PATCH 0043/1799] target: Clean up returning errors in PR handling code commit d35212f3ca3bf4fb49d15e37f530c9931e2d2183 upstream. - instead of (PTR_ERR(file) < 0) just use IS_ERR(file) - return -EINVAL instead of EINVAL - all other error returns in target_scsi3_emulate_pr_out() use "goto out" -- get rid of the one remaining straight "return." Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_pr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index c3148b10b4b3..89d10e6a82ee 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -2038,7 +2038,7 @@ static int __core_scsi3_write_aptpl_to_file( if (IS_ERR(file) || !file || !file->f_dentry) { pr_err("filp_open(%s) for APTPL metadata" " failed\n", path); - return (PTR_ERR(file) < 0 ? PTR_ERR(file) : -ENOENT); + return IS_ERR(file) ? PTR_ERR(file) : -ENOENT; } iov[0].iov_base = &buf[0]; @@ -3826,7 +3826,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task) " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = EINVAL; + ret = -EINVAL; goto out; } @@ -3836,7 +3836,8 @@ int target_scsi3_emulate_pr_out(struct se_task *task) */ if (!cmd->se_sess) { cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + ret = -EINVAL; + goto out; } if (cmd->data_length < 24) { -- GitLab From 5c8c9e57270fc5f54aa02144f7280f91ee2e3334 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 16 Jul 2012 17:10:17 -0700 Subject: [PATCH 0044/1799] target: Fix range calculation in WRITE SAME emulation when num blocks == 0 commit 1765fe5edcb83f53fc67edeb559fcf4bc82c6460 upstream. When NUMBER OF LOGICAL BLOCKS is 0, WRITE SAME is supposed to write all the blocks from the specified LBA through the end of the device. However, dev->transport->get_blocks(dev) (perhaps confusingly) returns the last valid LBA rather than the number of blocks, so the correct number of blocks to write starting with lba is dev->transport->get_blocks(dev) - lba + 1 (nab: Backport roland's for-3.6 patch to for-3.5) Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_cdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 30a67707036f..fa323f8aa171 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -1107,7 +1107,7 @@ int target_emulate_write_same(struct se_task *task) if (num_blocks != 0) range = num_blocks; else - range = (dev->transport->get_blocks(dev) - lba); + range = (dev->transport->get_blocks(dev) - lba) + 1; pr_debug("WRITE_SAME UNMAP: LBA: %llu Range: %llu\n", (unsigned long long)lba, (unsigned long long)range); -- GitLab From fd25080998d00a94a87bf7fc9f843291db7250a6 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 13 Jul 2012 01:21:50 -0400 Subject: [PATCH 0045/1799] ntp: Fix STA_INS/DEL clearing bug commit 6b1859dba01c7d512b72d77e3fd7da8354235189 upstream. In commit 6b43ae8a619d17c4935c3320d2ef9e92bdeed05d, I introduced a bug that kept the STA_INS or STA_DEL bit from being cleared from time_status via adjtimex() without forcing STA_PLL first. Usually once the STA_INS is set, it isn't cleared until the leap second is applied, so its unlikely this affected anyone. However during testing I noticed it took some effort to cancel a leap second once STA_INS was set. Signed-off-by: John Stultz Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Richard Cochran Cc: Prarit Bhargava Link: http://lkml.kernel.org/r/1342156917-25092-2-git-send-email-john.stultz@linaro.org Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/time/ntp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index e8c867173ae5..8b707100286b 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -409,7 +409,9 @@ int second_overflow(unsigned long secs) time_state = TIME_DEL; break; case TIME_INS: - if (secs % 86400 == 0) { + if (!(time_status & STA_INS)) + time_state = TIME_OK; + else if (secs % 86400 == 0) { leap = -1; time_state = TIME_OOP; time_tai++; @@ -418,7 +420,9 @@ int second_overflow(unsigned long secs) } break; case TIME_DEL: - if ((secs + 1) % 86400 == 0) { + if (!(time_status & STA_DEL)) + time_state = TIME_OK; + else if ((secs + 1) % 86400 == 0) { leap = 1; time_tai--; time_state = TIME_WAIT; -- GitLab From 8db5153f9dca89afbeebe0b077e7cc1e5827e07a Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 13 Jul 2012 18:18:04 -0700 Subject: [PATCH 0046/1799] tcm_fc: Fix crash seen with aborts and large reads commit 3cc5d2a6b9a2fd1bf024aa5e52dd22961eecaf13 upstream. This patch fixes a crash seen when large reads have their exchange aborted by either timing out or being reset. Because the exchange abort results in the seq pointer being set to NULL, because the sequence is no longer valid, it must not be dereferenced. This patch changes the function ft_get_task_tag to return ~0 if it is unable to get the tag for this reason. Because the get_task_tag interface provides no means of returning an error, this seems like the best way to fix this issue at the moment. Signed-off-by: Mark Rustad Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/tcm_fc/tfc_cmd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index a375f257aabc..da90f647695e 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -240,6 +240,8 @@ u32 ft_get_task_tag(struct se_cmd *se_cmd) { struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd); + if (cmd->aborted) + return ~0; return fc_seq_exch(cmd->seq)->rxid; } -- GitLab From 2dbbb550c56cbaf9d8353f4546aab9a88786d279 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 18 Jul 2012 09:31:36 +0100 Subject: [PATCH 0047/1799] ext4: fix duplicated mnt_drop_write call in EXT4_IOC_MOVE_EXT commit 331ae4962b975246944ea039697a8f1cadce42bb upstream. Caused, AFAICS, by mismerge in commit ff9cb1c4eead ("Merge branch 'for_linus' into for_linus_merged") Signed-off-by: Al Viro Cc: Theodore Ts'o Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/ext4/ioctl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 1365903a5144..9727522e2716 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -261,7 +261,6 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) err = ext4_move_extents(filp, donor_filp, me.orig_start, me.donor_start, me.len, &me.moved_len); mnt_drop_write_file(filp); - mnt_drop_write(filp->f_path.mnt); if (copy_to_user((struct move_extent __user *)arg, &me, sizeof(me))) -- GitLab From 07aa70120e4be526a468b9c3ea93b45cfbe95013 Mon Sep 17 00:00:00 2001 From: Aaditya Kumar Date: Tue, 17 Jul 2012 15:48:07 -0700 Subject: [PATCH 0048/1799] mm: fix lost kswapd wakeup in kswapd_stop() commit 1c7e7f6c0703d03af6bcd5ccc11fc15d23e5ecbe upstream. Offlining memory may block forever, waiting for kswapd() to wake up because kswapd() does not check the event kthread->should_stop before sleeping. The proper pattern, from Documentation/memory-barriers.txt, is: --- waker --- event_indicated = 1; wake_up_process(event_daemon); --- sleeper --- for (;;) { set_current_state(TASK_UNINTERRUPTIBLE); if (event_indicated) break; schedule(); } set_current_state() may be wrapped by: prepare_to_wait(); In the kswapd() case, event_indicated is kthread->should_stop. === offlining memory (waker) === kswapd_stop() kthread_stop() kthread->should_stop = 1 wake_up_process() wait_for_completion() === kswapd_try_to_sleep (sleeper) === kswapd_try_to_sleep() prepare_to_wait() . . schedule() . . finish_wait() The schedule() needs to be protected by a test of kthread->should_stop, which is wrapped by kthread_should_stop(). Reproducer: Do heavy file I/O in background. Do a memory offline/online in a tight loop Signed-off-by: Aaditya Kumar Acked-by: KOSAKI Motohiro Reviewed-by: Minchan Kim Acked-by: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/vmscan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 4607cc62b1d9..be5bc0af2e76 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -3013,7 +3013,10 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx) * them before going back to sleep. */ set_pgdat_percpu_threshold(pgdat, calculate_normal_threshold); - schedule(); + + if (!kthread_should_stop()) + schedule(); + set_pgdat_percpu_threshold(pgdat, calculate_pressure_threshold); } else { if (remaining) -- GitLab From e58cd46e372812120c547f1b311f7a1a00c22af4 Mon Sep 17 00:00:00 2001 From: Daniel Nicoletti Date: Wed, 4 Jul 2012 10:20:31 -0300 Subject: [PATCH 0049/1799] HID: add battery quirk for Apple Wireless ANSI commit 0c47935c5b5cd4916cf1c1ed4a2894807f7bcc3e upstream. Add USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, to the quirk list since it report wrong feature type and wrong percentage range. Signed-off-by: Daniel Nicoletti Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-input.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 002781c5a616..21e473e7fe27 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -290,6 +290,9 @@ static const struct hid_device_id hid_battery_quirks[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI), HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI), + HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, {} }; -- GitLab From eb6cf92d839f43dbc2009a2440479f46f7adfd46 Mon Sep 17 00:00:00 2001 From: Frank Kunz Date: Thu, 5 Jul 2012 22:32:49 +0200 Subject: [PATCH 0050/1799] HID: add Sennheiser BTD500USB device support commit 0e050923a797c1fc46ccc1e5182fd3090f33a75d upstream. The Sennheiser BTD500USB composit device requires the HID_QUIRK_NOGET flag to be set for working proper. Without the flag the device crashes during hid intialization. Signed-off-by: Frank Kunz Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-ids.h | 3 +++ drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index dfd40981c86a..7dc2ff72d5e4 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -650,6 +650,9 @@ #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600 +#define USB_VENDOR_ID_SENNHEISER 0x1395 +#define USB_DEVICE_ID_SENNHEISER_BTD500USB 0x002c + #define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 782c63955f29..82f61ee632b5 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -76,6 +76,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, -- GitLab From 60d091aeb66c0b201689862bcb803c32db712d05 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Fri, 20 Apr 2012 12:15:44 +0200 Subject: [PATCH 0051/1799] HID: multitouch: Add support for Baanto touchscreen commit 9ed326951806c424b42dcf2e1125e25a98fb13d1 upstream. Reported-by: Tvrtko Ursulin Tested-by: Tvrtko Ursulin Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-multitouch.c | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 054677b3d168..973c238eb9f6 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1391,6 +1391,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, + { HID_USB_DEVICE(USB_VENDOR_ID_BAANTO, USB_DEVICE_ID_BAANTO_MT_190W2), }, { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 7dc2ff72d5e4..bb1abf83798b 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -160,6 +160,9 @@ #define USB_VENDOR_ID_AVERMEDIA 0x07ca #define USB_DEVICE_ID_AVER_FM_MR800 0xb800 +#define USB_VENDOR_ID_BAANTO 0x2453 +#define USB_DEVICE_ID_BAANTO_MT_190W2 0x0100 + #define USB_VENDOR_ID_BELKIN 0x050d #define USB_DEVICE_ID_FLIP_KVM 0x3201 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 543896dfc49c..a6197f572039 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -783,6 +783,10 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_ATMEL, USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) }, + /* Baanto multitouch devices */ + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_BAANTO, + USB_DEVICE_ID_BAANTO_MT_190W2) }, /* Cando panels */ { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, HID_USB_DEVICE(USB_VENDOR_ID_CANDO, -- GitLab From ec8348902ff82ae44f25b3127f8f3ec47e1e6a07 Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 19 Jul 2012 09:11:14 +0200 Subject: [PATCH 0052/1799] MIPS: Properly align the .data..init_task section. commit 7b1c0d26a8e272787f0f9fcc5f3e8531df3b3409 upstream. Improper alignment can lead to unbootable systems and/or random crashes. [ralf@linux-mips.org: This is a lond standing bug since 6eb10bc9e2deab06630261cd05c4cb1e9a60e980 (kernel.org) rsp. c422a10917f75fd19fa7fe070aaaa23e384dae6f (lmo) [MIPS: Clean up linker script using new linker script macros.] so dates back to 2.6.32.] Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3881/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- arch/mips/include/asm/thread_info.h | 4 ++-- arch/mips/kernel/vmlinux.lds.S | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index 0d85d8e440c5..abb13e83dfda 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -60,6 +60,8 @@ struct thread_info { register struct thread_info *__current_thread_info __asm__("$28"); #define current_thread_info() __current_thread_info +#endif /* !__ASSEMBLY__ */ + /* thread information allocation */ #if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_32BIT) #define THREAD_SIZE_ORDER (1) @@ -97,8 +99,6 @@ register struct thread_info *__current_thread_info __asm__("$28"); #define free_thread_info(info) kfree(info) -#endif /* !__ASSEMBLY__ */ - #define PREEMPT_ACTIVE 0x10000000 /* diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 924da5eb7031..df243a64f430 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -1,5 +1,6 @@ #include #include +#include #include #undef mips @@ -72,7 +73,7 @@ SECTIONS .data : { /* Data */ . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */ - INIT_TASK_DATA(PAGE_SIZE) + INIT_TASK_DATA(THREAD_SIZE) NOSAVE_DATA CACHELINE_ALIGNED_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT) READ_MOSTLY_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT) -- GitLab From 863c806617059e412ade0b1bbb6d215106be14c1 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sat, 14 Jul 2012 14:33:09 +0300 Subject: [PATCH 0053/1799] UBIFS: fix a bug in empty space fix-up commit c6727932cfdb13501108b16c38463c09d5ec7a74 upstream. UBIFS has a feature called "empty space fix-up" which is a quirk to work-around limitations of dumb flasher programs. Namely, of those flashers that are unable to skip NAND pages full of 0xFFs while flashing, resulting in empty space at the end of half-filled eraseblocks to be unusable for UBIFS. This feature is relatively new (introduced in v3.0). The fix-up routine (fixup_free_space()) is executed only once at the very first mount if the superblock has the 'space_fixup' flag set (can be done with -F option of mkfs.ubifs). It basically reads all the UBIFS data and metadata and writes it back to the same LEB. The routine assumes the image is pristine and does not have anything in the journal. There was a bug in 'fixup_free_space()' where it fixed up the log incorrectly. All but one LEB of the log of a pristine file-system are empty. And one contains just a commit start node. And 'fixup_free_space()' just unmapped this LEB, which resulted in wiping the commit start node. As a result, some users were unable to mount the file-system next time with the following symptom: UBIFS error (pid 1): replay_log_leb: first log node at LEB 3:0 is not CS node UBIFS error (pid 1): replay_log_leb: log error detected while replaying the log at LEB 3:0 The root-cause of this bug was that 'fixup_free_space()' wrongly assumed that the beginning of empty space in the log head (c->lhead_offs) was known on mount. However, it is not the case - it was always 0. UBIFS does not store in it the master node and finds out by scanning the log on every mount. The fix is simple - just pass commit start node size instead of 0 to 'fixup_leb()'. Signed-off-by: Artem Bityutskiy Reported-by: Iwo Mergler Tested-by: Iwo Mergler Reported-by: James Nute Signed-off-by: Greg Kroah-Hartman --- fs/ubifs/sb.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index 771f7fb6ce92..a7be8e2b4b9d 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c @@ -724,8 +724,12 @@ static int fixup_free_space(struct ubifs_info *c) lnum = ubifs_next_log_lnum(c, lnum); } - /* Fixup the current log head */ - err = fixup_leb(c, c->lhead_lnum, c->lhead_offs); + /* + * Fixup the log head which contains the only a CS node at the + * beginning. + */ + err = fixup_leb(c, c->lhead_lnum, + ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size)); if (err) goto out; -- GitLab From 0234af60fb13cbb7caa6f757e4d8e29cd87aaba6 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Fri, 8 Jun 2012 01:19:07 +0300 Subject: [PATCH 0054/1799] ore: Fix NFS crash by supporting any unaligned RAID IO commit 9ff19309a9623f2963ac5a136782ea4d8b5d67fb upstream. In RAID_5/6 We used to not permit an IO that it's end byte is not stripe_size aligned and spans more than one stripe. .i.e the caller must check if after submission the actual transferred bytes is shorter, and would need to resubmit a new IO with the remainder. Exofs supports this, and NFS was supposed to support this as well with it's short write mechanism. But late testing has exposed a CRASH when this is used with none-RPC layout-drivers. The change at NFS is deep and risky, in it's place the fix at ORE to lift the limitation is actually clean and simple. So here it is below. The principal here is that in the case of unaligned IO on both ends, beginning and end, we will send two read requests one like old code, before the calculation of the first stripe, and also a new site, before the calculation of the last stripe. If any "boundary" is aligned or the complete IO is within a single stripe. we do a single read like before. The code is clean and simple by splitting the old _read_4_write into 3 even parts: 1._read_4_write_first_stripe 2. _read_4_write_last_stripe 3. _read_4_write_execute And calling 1+3 at the same place as before. 2+3 before last stripe, and in the case of all in a single stripe then 1+2+3 is preformed additively. Why did I not think of it before. Well I had a strike of genius because I have stared at this code for 2 years, and did not find this simple solution, til today. Not that I did not try. This solution is much better for NFS than the previous supposedly solution because the short write was dealt with out-of-band after IO_done, which would cause for a seeky IO pattern where as in here we execute in order. At both solutions we do 2 separate reads, only here we do it within a single IO request. (And actually combine two writes into a single submission) NFS/exofs code need not change since the ORE API communicates the new shorter length on return, what will happen is that this case would not occur anymore. hurray!! [Stable this is an NFS bug since 3.2 Kernel should apply cleanly] Signed-off-by: Boaz Harrosh Signed-off-by: Greg Kroah-Hartman --- fs/exofs/ore_raid.c | 67 ++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/fs/exofs/ore_raid.c b/fs/exofs/ore_raid.c index d222c77cfa1b..fff2070c6751 100644 --- a/fs/exofs/ore_raid.c +++ b/fs/exofs/ore_raid.c @@ -461,16 +461,12 @@ static void _mark_read4write_pages_uptodate(struct ore_io_state *ios, int ret) * ios->sp2d[p][*], xor is calculated the same way. These pages are * allocated/freed and don't go through cache */ -static int _read_4_write(struct ore_io_state *ios) +static int _read_4_write_first_stripe(struct ore_io_state *ios) { - struct ore_io_state *ios_read; struct ore_striping_info read_si; struct __stripe_pages_2d *sp2d = ios->sp2d; u64 offset = ios->si.first_stripe_start; - u64 last_stripe_end; - unsigned bytes_in_stripe = ios->si.bytes_in_stripe; - unsigned i, c, p, min_p = sp2d->pages_in_unit, max_p = -1; - int ret; + unsigned c, p, min_p = sp2d->pages_in_unit, max_p = -1; if (offset == ios->offset) /* Go to start collect $200 */ goto read_last_stripe; @@ -478,6 +474,9 @@ static int _read_4_write(struct ore_io_state *ios) min_p = _sp2d_min_pg(sp2d); max_p = _sp2d_max_pg(sp2d); + ORE_DBGMSG("stripe_start=0x%llx ios->offset=0x%llx min_p=%d max_p=%d\n", + offset, ios->offset, min_p, max_p); + for (c = 0; ; c++) { ore_calc_stripe_info(ios->layout, offset, 0, &read_si); read_si.obj_offset += min_p * PAGE_SIZE; @@ -512,6 +511,18 @@ static int _read_4_write(struct ore_io_state *ios) } read_last_stripe: + return 0; +} + +static int _read_4_write_last_stripe(struct ore_io_state *ios) +{ + struct ore_striping_info read_si; + struct __stripe_pages_2d *sp2d = ios->sp2d; + u64 offset; + u64 last_stripe_end; + unsigned bytes_in_stripe = ios->si.bytes_in_stripe; + unsigned c, p, min_p = sp2d->pages_in_unit, max_p = -1; + offset = ios->offset + ios->length; if (offset % PAGE_SIZE) _add_to_r4w_last_page(ios, &offset); @@ -527,15 +538,15 @@ static int _read_4_write(struct ore_io_state *ios) c = _dev_order(ios->layout->group_width * ios->layout->mirrors_p1, ios->layout->mirrors_p1, read_si.par_dev, read_si.dev); - BUG_ON(ios->si.first_stripe_start + bytes_in_stripe != last_stripe_end); - /* unaligned IO must be within a single stripe */ - if (min_p == sp2d->pages_in_unit) { /* Didn't do it yet */ min_p = _sp2d_min_pg(sp2d); max_p = _sp2d_max_pg(sp2d); } + ORE_DBGMSG("offset=0x%llx stripe_end=0x%llx min_p=%d max_p=%d\n", + offset, last_stripe_end, min_p, max_p); + while (offset < last_stripe_end) { struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p]; @@ -568,6 +579,15 @@ static int _read_4_write(struct ore_io_state *ios) } read_it: + return 0; +} + +static int _read_4_write_execute(struct ore_io_state *ios) +{ + struct ore_io_state *ios_read; + unsigned i; + int ret; + ios_read = ios->ios_read_4_write; if (!ios_read) return 0; @@ -591,6 +611,8 @@ static int _read_4_write(struct ore_io_state *ios) } _mark_read4write_pages_uptodate(ios_read, ret); + ore_put_io_state(ios_read); + ios->ios_read_4_write = NULL; /* Might need a reuse at last stripe */ return 0; } @@ -626,8 +648,11 @@ int _ore_add_parity_unit(struct ore_io_state *ios, /* If first stripe, Read in all read4write pages * (if needed) before we calculate the first parity. */ - _read_4_write(ios); + _read_4_write_first_stripe(ios); } + if (!cur_len) /* If last stripe r4w pages of last stripe */ + _read_4_write_last_stripe(ios); + _read_4_write_execute(ios); for (i = 0; i < num_pages; i++) { pages[i] = _raid_page_alloc(); @@ -654,34 +679,14 @@ int _ore_add_parity_unit(struct ore_io_state *ios, int _ore_post_alloc_raid_stuff(struct ore_io_state *ios) { - struct ore_layout *layout = ios->layout; - if (ios->parity_pages) { + struct ore_layout *layout = ios->layout; unsigned pages_in_unit = layout->stripe_unit / PAGE_SIZE; - unsigned stripe_size = ios->si.bytes_in_stripe; - u64 last_stripe, first_stripe; if (_sp2d_alloc(pages_in_unit, layout->group_width, layout->parity, &ios->sp2d)) { return -ENOMEM; } - - /* Round io down to last full strip */ - first_stripe = div_u64(ios->offset, stripe_size); - last_stripe = div_u64(ios->offset + ios->length, stripe_size); - - /* If an IO spans more then a single stripe it must end at - * a stripe boundary. The reminder at the end is pushed into the - * next IO. - */ - if (last_stripe != first_stripe) { - ios->length = last_stripe * stripe_size - ios->offset; - - BUG_ON(!ios->length); - ios->nr_pages = (ios->length + PAGE_SIZE - 1) / - PAGE_SIZE; - ios->si.length = ios->length; /*make it consistent */ - } } return 0; } -- GitLab From f6ecbea43e774dfc0b3678d2cdda9d4b43cfecf8 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Fri, 8 Jun 2012 04:30:40 +0300 Subject: [PATCH 0055/1799] ore: Remove support of partial IO request (NFS crash) commit 62b62ad873f2accad9222a4d7ffbe1e93f6714c1 upstream. Do to OOM situations the ore might fail to allocate all resources needed for IO of the full request. If some progress was possible it would proceed with a partial/short request, for the sake of forward progress. Since this crashes NFS-core and exofs is just fine without it just remove this contraption, and fail. TODO: Support real forward progress with some reserved allocations of resources, such as mem pools and/or bio_sets [Bug since 3.2 Kernel] CC: Benny Halevy Signed-off-by: Boaz Harrosh Signed-off-by: Greg Kroah-Hartman --- fs/exofs/ore.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c index 49cf230554a2..24a49d47e935 100644 --- a/fs/exofs/ore.c +++ b/fs/exofs/ore.c @@ -735,13 +735,7 @@ static int _prepare_for_striping(struct ore_io_state *ios) out: ios->numdevs = devs_in_group; ios->pages_consumed = cur_pg; - if (unlikely(ret)) { - if (length == ios->length) - return ret; - else - ios->length -= length; - } - return 0; + return ret; } int ore_create(struct ore_io_state *ios) -- GitLab From 08603bdd6b0b65248921c8be05febe574dd78905 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Fri, 8 Jun 2012 05:29:40 +0300 Subject: [PATCH 0056/1799] pnfs-obj: don't leak objio_state if ore_write/read fails commit 9909d45a8557455ca5f8ee7af0f253debc851f1a upstream. [Bug since 3.2 Kernel] Signed-off-by: Boaz Harrosh Signed-off-by: Greg Kroah-Hartman --- fs/nfs/objlayout/objio_osd.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index 4bff4a3dab46..42ac1bf6fcc8 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c @@ -453,7 +453,10 @@ int objio_read_pagelist(struct nfs_read_data *rdata) objios->ios->done = _read_done; dprintk("%s: offset=0x%llx length=0x%x\n", __func__, rdata->args.offset, rdata->args.count); - return ore_read(objios->ios); + ret = ore_read(objios->ios); + if (unlikely(ret)) + objio_free_result(&objios->oir); + return ret; } /* @@ -537,8 +540,10 @@ int objio_write_pagelist(struct nfs_write_data *wdata, int how) dprintk("%s: offset=0x%llx length=0x%x\n", __func__, wdata->args.offset, wdata->args.count); ret = ore_write(objios->ios); - if (unlikely(ret)) + if (unlikely(ret)) { + objio_free_result(&objios->oir); return ret; + } if (objios->sync) _write_done(objios->ios, objios); -- GitLab From 5b8bbc39d5678179f2fd4ee2e09005d8f277834c Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Fri, 20 Jul 2012 14:25:05 +0100 Subject: [PATCH 0057/1799] dm thin: do not send discards to shared blocks commit 650d2a06b4fe1cc1d218c20e256650f68bf0ca31 upstream. When process_discard receives a partial discard that doesn't cover a full block, it sends this discard down to that block. Unfortunately, the block can be shared and the discard would corrupt the other snapshots sharing this block. This patch detects block sharing and ends the discard with success when sending it to the shared block. The above change means that if the device supports discard it can't be guaranteed that a discard request zeroes data. Therefore, we set ti->discard_zeroes_data_unsupported. Thin target discard support with this bug arrived in commit 104655fd4dcebd50068ef30253a001da72e3a081 (dm thin: support discards). Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-thin.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index eb3d138ff55a..e0a0ebe64c09 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -1240,7 +1240,10 @@ static void process_discard(struct thin_c *tc, struct bio *bio) cell_release_singleton(cell, bio); cell_release_singleton(cell2, bio); - remap_and_issue(tc, bio, lookup_result.block); + if ((!lookup_result.shared) && pool->pf.discard_passdown) + remap_and_issue(tc, bio, lookup_result.block); + else + bio_endio(bio, 0); } break; @@ -2575,6 +2578,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv) if (tc->pool->pf.discard_enabled) { ti->discards_supported = 1; ti->num_discard_requests = 1; + ti->discard_zeroes_data_unsupported = 1; } dm_put(pool_md); -- GitLab From 91aafba4414743c24c6d06ccca75113e4abd13a8 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Fri, 20 Jul 2012 14:25:03 +0100 Subject: [PATCH 0058/1799] dm raid1: fix crash with mirror recovery and discard commit 751f188dd5ab95b3f2b5f2f467c38aae5a2877eb upstream. This patch fixes a crash when a discard request is sent during mirror recovery. Firstly, some background. Generally, the following sequence happens during mirror synchronization: - function do_recovery is called - do_recovery calls dm_rh_recovery_prepare - dm_rh_recovery_prepare uses a semaphore to limit the number simultaneously recovered regions (by default the semaphore value is 1, so only one region at a time is recovered) - dm_rh_recovery_prepare calls __rh_recovery_prepare, __rh_recovery_prepare asks the log driver for the next region to recover. Then, it sets the region state to DM_RH_RECOVERING. If there are no pending I/Os on this region, the region is added to quiesced_regions list. If there are pending I/Os, the region is not added to any list. It is added to the quiesced_regions list later (by dm_rh_dec function) when all I/Os finish. - when the region is on quiesced_regions list, there are no I/Os in flight on this region. The region is popped from the list in dm_rh_recovery_start function. Then, a kcopyd job is started in the recover function. - when the kcopyd job finishes, recovery_complete is called. It calls dm_rh_recovery_end. dm_rh_recovery_end adds the region to recovered_regions or failed_recovered_regions list (depending on whether the copy operation was successful or not). The above mechanism assumes that if the region is in DM_RH_RECOVERING state, no new I/Os are started on this region. When I/O is started, dm_rh_inc_pending is called, which increases reg->pending count. When I/O is finished, dm_rh_dec is called. It decreases reg->pending count. If the count is zero and the region was in DM_RH_RECOVERING state, dm_rh_dec adds it to the quiesced_regions list. Consequently, if we call dm_rh_inc_pending/dm_rh_dec while the region is in DM_RH_RECOVERING state, it could be added to quiesced_regions list multiple times or it could be added to this list when kcopyd is copying data (it is assumed that the region is not on any list while kcopyd does its jobs). This results in memory corruption and crash. There already exist bypasses for REQ_FLUSH requests: REQ_FLUSH requests do not belong to any region, so they are always added to the sync list in do_writes. dm_rh_inc_pending does not increase count for REQ_FLUSH requests. In mirror_end_io, dm_rh_dec is never called for REQ_FLUSH requests. These bypasses avoid the crash possibility described above. These bypasses were improperly implemented for REQ_DISCARD when the mirror target gained discard support in commit 5fc2ffeabb9ee0fc0e71ff16b49f34f0ed3d05b4 (dm raid1: support discard). In do_writes, REQ_DISCARD requests is always added to the sync queue and immediately dispatched (even if the region is in DM_RH_RECOVERING). However, dm_rh_inc and dm_rh_dec is called for REQ_DISCARD resusts. So it violates the rule that no I/Os are started on DM_RH_RECOVERING regions, and causes the list corruption described above. This patch changes it so that REQ_DISCARD requests follow the same path as REQ_FLUSH. This avoids the crash. Reference: https://bugzilla.redhat.com/837607 Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-raid1.c | 2 +- drivers/md/dm-region-hash.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index d039de8322f0..ea16984c0f08 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -1214,7 +1214,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, * We need to dec pending if this was a write. */ if (rw == WRITE) { - if (!(bio->bi_rw & REQ_FLUSH)) + if (!(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))) dm_rh_dec(ms->rh, map_context->ll); return error; } diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c index 7771ed212182..69732e03eb34 100644 --- a/drivers/md/dm-region-hash.c +++ b/drivers/md/dm-region-hash.c @@ -404,6 +404,9 @@ void dm_rh_mark_nosync(struct dm_region_hash *rh, struct bio *bio) return; } + if (bio->bi_rw & REQ_DISCARD) + return; + /* We must inform the log that the sync count has changed. */ log->type->set_region_sync(log, region, 0); @@ -524,7 +527,7 @@ void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios) struct bio *bio; for (bio = bios->head; bio; bio = bio->bi_next) { - if (bio->bi_rw & REQ_FLUSH) + if (bio->bi_rw & (REQ_FLUSH | REQ_DISCARD)) continue; rh_inc(rh, dm_rh_bio_to_region(rh, bio)); } -- GitLab From 5a4db9ee4f44658077a11c71d78a17573016fc0e Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Fri, 20 Jul 2012 14:25:07 +0100 Subject: [PATCH 0059/1799] dm raid1: set discard_zeroes_data_unsupported commit 7c8d3a42fe1c58a7e8fd3f6a013e7d7b474ff931 upstream. We can't guarantee that REQ_DISCARD on dm-mirror zeroes the data even if the underlying disks support zero on discard. So this patch sets ti->discard_zeroes_data_unsupported. For example, if the mirror is in the process of resynchronizing, it may happen that kcopyd reads a piece of data, then discard is sent on the same area and then kcopyd writes the piece of data to another leg. Consequently, the data is not zeroed. The flag was made available by commit 983c7db347db8ce2d8453fd1d89b7a4bb6920d56 (dm crypt: always disable discard_zeroes_data). Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-raid1.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index ea16984c0f08..b58b7a33914a 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -1084,6 +1084,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) ti->split_io = dm_rh_get_region_size(ms->rh); ti->num_flush_requests = 1; ti->num_discard_requests = 1; + ti->discard_zeroes_data_unsupported = 1; ms->kmirrord_wq = alloc_workqueue("kmirrord", WQ_NON_REENTRANT | WQ_MEM_RECLAIM, 0); -- GitLab From a22ad130fc91983ac717a24e29838bf2969a67d4 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Thu, 12 Jul 2012 18:06:28 +0900 Subject: [PATCH 0060/1799] ARM: SAMSUNG: Update default rate for xusbxti clock commit bdd3cc26ba651e33780ade33f1410320cf2d0cf4 upstream. The rate of xusbxti clock is set in individual machine files. The default value should be defined at the clock definition and individual machine files should modify it if required. Division by zero in kernel. [] (unwind_backtrace+0x1/0x9c) from [] (Ldiv0+0x9/0x12) [] (Ldiv0+0x9/0x12) from [] (s3c_setrate_clksrc+0x33/0x78) [] (s3c_setrate_clksrc+0x33/0x78) from [] (clk_set_rate+0x2f/0x78) Signed-off-by: Tushar Behera Signed-off-by: Kukjin Kim Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-s5p/clock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c index f68a9bb11948..b04279512e2d 100644 --- a/arch/arm/plat-s5p/clock.c +++ b/arch/arm/plat-s5p/clock.c @@ -38,6 +38,7 @@ struct clk clk_ext_xtal_mux = { struct clk clk_xusbxti = { .name = "xusbxti", .id = -1, + .rate = 24000000, }; struct clk s5p_clk_27m = { -- GitLab From 5d0c7b47b27d51c45700b1153ac86752ff743aa6 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 11 Jul 2012 09:09:36 -0400 Subject: [PATCH 0061/1799] cifs: when CONFIG_HIGHMEM is set, serialize the read/write kmaps commit 3cf003c08be785af4bee9ac05891a15bcbff856a upstream. [The async read code was broadened to include uncached reads in 3.5, so the mainline patch did not apply directly. This patch is just a backport to account for that change.] Jian found that when he ran fsx on a 32 bit arch with a large wsize the process and one of the bdi writeback kthreads would sometimes deadlock with a stack trace like this: crash> bt PID: 2789 TASK: f02edaa0 CPU: 3 COMMAND: "fsx" #0 [eed63cbc] schedule at c083c5b3 #1 [eed63d80] kmap_high at c0500ec8 #2 [eed63db0] cifs_async_writev at f7fabcd7 [cifs] #3 [eed63df0] cifs_writepages at f7fb7f5c [cifs] #4 [eed63e50] do_writepages at c04f3e32 #5 [eed63e54] __filemap_fdatawrite_range at c04e152a #6 [eed63ea4] filemap_fdatawrite at c04e1b3e #7 [eed63eb4] cifs_file_aio_write at f7fa111a [cifs] #8 [eed63ecc] do_sync_write at c052d202 #9 [eed63f74] vfs_write at c052d4ee #10 [eed63f94] sys_write at c052df4c #11 [eed63fb0] ia32_sysenter_target at c0409a98 EAX: 00000004 EBX: 00000003 ECX: abd73b73 EDX: 012a65c6 DS: 007b ESI: 012a65c6 ES: 007b EDI: 00000000 SS: 007b ESP: bf8db178 EBP: bf8db1f8 GS: 0033 CS: 0073 EIP: 40000424 ERR: 00000004 EFLAGS: 00000246 Each task would kmap part of its address array before getting stuck, but not enough to actually issue the write. This patch fixes this by serializing the marshal_iov operations for async reads and writes. The idea here is to ensure that cifs aggressively tries to populate a request before attempting to fulfill another one. As soon as all of the pages are kmapped for a request, then we can unlock and allow another one to proceed. There's no need to do this serialization on non-CONFIG_HIGHMEM arches however, so optimize all of this out when CONFIG_HIGHMEM isn't set. Reported-by: Jian Li Signed-off-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifssmb.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 6b79efd7d75f..3a75ee5a6b33 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -89,6 +89,32 @@ static struct { /* Forward declarations */ static void cifs_readv_complete(struct work_struct *work); +#ifdef CONFIG_HIGHMEM +/* + * On arches that have high memory, kmap address space is limited. By + * serializing the kmap operations on those arches, we ensure that we don't + * end up with a bunch of threads in writeback with partially mapped page + * arrays, stuck waiting for kmap to come back. That situation prevents + * progress and can deadlock. + */ +static DEFINE_MUTEX(cifs_kmap_mutex); + +static inline void +cifs_kmap_lock(void) +{ + mutex_lock(&cifs_kmap_mutex); +} + +static inline void +cifs_kmap_unlock(void) +{ + mutex_unlock(&cifs_kmap_mutex); +} +#else /* !CONFIG_HIGHMEM */ +#define cifs_kmap_lock() do { ; } while(0) +#define cifs_kmap_unlock() do { ; } while(0) +#endif /* CONFIG_HIGHMEM */ + /* Mark as invalid, all open files on tree connections since they were closed when session to server was lost */ static void mark_open_files_invalid(struct cifs_tcon *pTcon) @@ -1557,6 +1583,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0; cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index); + cifs_kmap_lock(); list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { if (remaining >= PAGE_CACHE_SIZE) { /* enough data to fill the page */ @@ -1606,6 +1633,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) page_cache_release(page); } } + cifs_kmap_unlock(); /* issue the read if we have any iovecs left to fill */ if (rdata->nr_iov > 1) { @@ -2194,7 +2222,9 @@ cifs_async_writev(struct cifs_writedata *wdata) * and set the iov_len properly for each one. It may also set * wdata->bytes too. */ + cifs_kmap_lock(); wdata->marshal_iov(iov, wdata); + cifs_kmap_unlock(); cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); -- GitLab From 0d0eef55e03a76885b5d665b1f5572e1f4975886 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 29 Jul 2012 08:04:57 -0700 Subject: [PATCH 0062/1799] Linux 3.4.7 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5d0edcbd8786..e17a98c3ea53 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 6 +SUBLEVEL = 7 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 480692b1562b07a4bb8e4d6e49bf7fd2acefbea2 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 16 Jul 2012 15:34:21 -0700 Subject: [PATCH 0063/1799] target: Add generation of LOGICAL BLOCK ADDRESS OUT OF RANGE commit e2397c704429025bc6b331a970f699e52f34283e upstream. Many SCSI commands are defined to return a CHECK CONDITION / ILLEGAL REQUEST with ASC set to LOGICAL BLOCK ADDRESS OUT OF RANGE if the initiator sends a command that accesses a too-big LBA. Add an enum value and case entries so that target code can return this status. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_transport.c | 10 ++++++++++ include/target/target_core_base.h | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 443704f84fd5..0686d61adeae 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1976,6 +1976,7 @@ void transport_generic_request_failure(struct se_cmd *cmd) case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE: case TCM_UNKNOWN_MODE_PAGE: case TCM_WRITE_PROTECTED: + case TCM_ADDRESS_OUT_OF_RANGE: case TCM_CHECK_CONDITION_ABORT_CMD: case TCM_CHECK_CONDITION_UNIT_ATTENTION: case TCM_CHECK_CONDITION_NOT_READY: @@ -4656,6 +4657,15 @@ int transport_send_check_condition_and_sense( /* WRITE PROTECTED */ buffer[offset+SPC_ASC_KEY_OFFSET] = 0x27; break; + case TCM_ADDRESS_OUT_OF_RANGE: + /* CURRENT ERROR */ + buffer[offset] = 0x70; + buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10; + /* ILLEGAL REQUEST */ + buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; + /* LOGICAL BLOCK ADDRESS OUT OF RANGE */ + buffer[offset+SPC_ASC_KEY_OFFSET] = 0x21; + break; case TCM_CHECK_CONDITION_UNIT_ATTENTION: /* CURRENT ERROR */ buffer[offset] = 0x70; diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index aaccc5f5fc9f..3ad5b33ee328 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -229,6 +229,7 @@ enum tcm_sense_reason_table { TCM_CHECK_CONDITION_UNIT_ATTENTION = 0x0e, TCM_CHECK_CONDITION_NOT_READY = 0x0f, TCM_RESERVATION_CONFLICT = 0x10, + TCM_ADDRESS_OUT_OF_RANGE = 0x11, }; enum target_sc_flags_table { -- GitLab From f1377fddb346729aa2fe9cdbfc54aaf2ca463bd5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 21 Jul 2012 08:55:18 +0100 Subject: [PATCH 0064/1799] iscsi-target: Drop bogus struct file usage for iSCSI/SCTP commit bf6932f44a7b3fa7e2246a8b18a44670e5eab6c2 upstream. From Al Viro: BTW, speaking of struct file treatment related to sockets - there's this piece of code in iscsi: /* * The SCTP stack needs struct socket->file. */ if ((np->np_network_transport == ISCSI_SCTP_TCP) || (np->np_network_transport == ISCSI_SCTP_UDP)) { if (!new_sock->file) { new_sock->file = kzalloc( sizeof(struct file), GFP_KERNEL); For one thing, as far as I can see it'not true - sctp does *not* depend on socket->file being non-NULL; it does, in one place, check socket->file->f_flags for O_NONBLOCK, but there it treats NULL socket->file as "flag not set". Which is the case here anyway - the fake struct file created in __iscsi_target_login_thread() (and in iscsi_target_setup_login_socket(), with the same excuse) do *not* get that flag set. Moreover, it's a bloody serious violation of a bunch of asserts in VFS; all struct file instances should come from filp_cachep, via get_empty_filp() (or alloc_file(), which is a wrapper for it). FWIW, I'm very tempted to do this and be done with the entire mess: Signed-off-by: Al Viro Cc: Andy Grover Cc: Hannes Reinecke Cc: Christoph Hellwig Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target.c | 22 ++------- drivers/target/iscsi/iscsi_target_core.h | 2 - drivers/target/iscsi/iscsi_target_login.c | 60 ++--------------------- 3 files changed, 6 insertions(+), 78 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 8b1d5e62ed40..e326d17e05a8 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -427,19 +427,8 @@ int iscsit_reset_np_thread( int iscsit_del_np_comm(struct iscsi_np *np) { - if (!np->np_socket) - return 0; - - /* - * Some network transports allocate their own struct sock->file, - * see if we need to free any additional allocated resources. - */ - if (np->np_flags & NPF_SCTP_STRUCT_FILE) { - kfree(np->np_socket->file); - np->np_socket->file = NULL; - } - - sock_release(np->np_socket); + if (np->np_socket) + sock_release(np->np_socket); return 0; } @@ -4094,13 +4083,8 @@ int iscsit_close_connection( kfree(conn->conn_ops); conn->conn_ops = NULL; - if (conn->sock) { - if (conn->conn_flags & CONNFLAG_SCTP_STRUCT_FILE) { - kfree(conn->sock->file); - conn->sock->file = NULL; - } + if (conn->sock) sock_release(conn->sock); - } conn->thread_set = NULL; pr_debug("Moving to TARG_CONN_STATE_FREE.\n"); diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 2aaee7efa683..d1c4bc22cca4 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -224,7 +224,6 @@ enum iscsi_timer_flags_table { /* Used for struct iscsi_np->np_flags */ enum np_flags_table { NPF_IP_NETWORK = 0x00, - NPF_SCTP_STRUCT_FILE = 0x01 /* Bugfix */ }; /* Used for struct iscsi_np->np_thread_state */ @@ -511,7 +510,6 @@ struct iscsi_conn { u16 local_port; int net_size; u32 auth_id; -#define CONNFLAG_SCTP_STRUCT_FILE 0x01 u32 conn_flags; /* Used for iscsi_tx_login_rsp() */ u32 login_itt; diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index a3656c9903a1..ae304248c8c2 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -794,22 +794,6 @@ int iscsi_target_setup_login_socket( return ret; } np->np_socket = sock; - /* - * The SCTP stack needs struct socket->file. - */ - if ((np->np_network_transport == ISCSI_SCTP_TCP) || - (np->np_network_transport == ISCSI_SCTP_UDP)) { - if (!sock->file) { - sock->file = kzalloc(sizeof(struct file), GFP_KERNEL); - if (!sock->file) { - pr_err("Unable to allocate struct" - " file for SCTP\n"); - ret = -ENOMEM; - goto fail; - } - np->np_flags |= NPF_SCTP_STRUCT_FILE; - } - } /* * Setup the np->np_sockaddr from the passed sockaddr setup * in iscsi_target_configfs.c code.. @@ -869,21 +853,15 @@ int iscsi_target_setup_login_socket( fail: np->np_socket = NULL; - if (sock) { - if (np->np_flags & NPF_SCTP_STRUCT_FILE) { - kfree(sock->file); - sock->file = NULL; - } - + if (sock) sock_release(sock); - } return ret; } static int __iscsi_target_login_thread(struct iscsi_np *np) { u8 buffer[ISCSI_HDR_LEN], iscsi_opcode, zero_tsih = 0; - int err, ret = 0, set_sctp_conn_flag, stop; + int err, ret = 0, stop; struct iscsi_conn *conn = NULL; struct iscsi_login *login; struct iscsi_portal_group *tpg = NULL; @@ -894,7 +872,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) struct sockaddr_in6 sock_in6; flush_signals(current); - set_sctp_conn_flag = 0; sock = np->np_socket; spin_lock_bh(&np->np_thread_lock); @@ -917,35 +894,12 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) spin_unlock_bh(&np->np_thread_lock); goto out; } - /* - * The SCTP stack needs struct socket->file. - */ - if ((np->np_network_transport == ISCSI_SCTP_TCP) || - (np->np_network_transport == ISCSI_SCTP_UDP)) { - if (!new_sock->file) { - new_sock->file = kzalloc( - sizeof(struct file), GFP_KERNEL); - if (!new_sock->file) { - pr_err("Unable to allocate struct" - " file for SCTP\n"); - sock_release(new_sock); - /* Get another socket */ - return 1; - } - set_sctp_conn_flag = 1; - } - } - iscsi_start_login_thread_timer(np); conn = kzalloc(sizeof(struct iscsi_conn), GFP_KERNEL); if (!conn) { pr_err("Could not allocate memory for" " new connection\n"); - if (set_sctp_conn_flag) { - kfree(new_sock->file); - new_sock->file = NULL; - } sock_release(new_sock); /* Get another socket */ return 1; @@ -955,9 +909,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) conn->conn_state = TARG_CONN_STATE_FREE; conn->sock = new_sock; - if (set_sctp_conn_flag) - conn->conn_flags |= CONNFLAG_SCTP_STRUCT_FILE; - pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n"); conn->conn_state = TARG_CONN_STATE_XPT_UP; @@ -1205,13 +1156,8 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) iscsi_release_param_list(conn->param_list); conn->param_list = NULL; } - if (conn->sock) { - if (conn->conn_flags & CONNFLAG_SCTP_STRUCT_FILE) { - kfree(conn->sock->file); - conn->sock->file = NULL; - } + if (conn->sock) sock_release(conn->sock); - } kfree(conn); if (tpg) { -- GitLab From c5b5af98489f4db8025baee2fc0cae7dd0d19ac3 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 3 Jul 2012 23:13:39 +0100 Subject: [PATCH 0065/1799] mmc: sdhci-pci: CaFe has broken card detection commit 55fc05b7414274f17795cd0e8a3b1546f3649d5e upstream. At http://dev.laptop.org/ticket/11980 we have determined that the Marvell CaFe SDHCI controller reports bad card presence during resume. It reports that no card is present even when it is. This is a regression -- resume worked back around 2.6.37. Around 400ms after resuming, a "card inserted" interrupt is generated, at which point it starts reporting presence. Work around this hardware oddity by setting the SDHCI_QUIRK_BROKEN_CARD_DETECTION flag. Thanks to Chris Ball for helping with diagnosis. Signed-off-by: Daniel Drake Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- 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 69ef0beae104..504da715a41a 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -157,6 +157,7 @@ static const struct sdhci_pci_fixes sdhci_ene_714 = { static const struct sdhci_pci_fixes sdhci_cafe = { .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | SDHCI_QUIRK_NO_BUSY_IRQ | + SDHCI_QUIRK_BROKEN_CARD_DETECTION | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, }; -- GitLab From 94c73bbcec6a77eb8a526a1230631a2cc18bf18b Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Tue, 3 Jul 2012 17:27:49 +0800 Subject: [PATCH 0066/1799] mmc: sdhci: fix incorrect command used in tuning commit 473b095a72a95ba719905b1f2e82cd18d099a427 upstream. For SD hosts using retuning mode 1, when retuning timer expired, it will need to do retuning in sdhci_request before processing the actual request. But the retuning command is fixed: cmd19 for SD card and cmd21 for eMMC card, so we can't use the original request's command to do the tuning. And since the tuning command depends on the card type attached to the host, we will need to know the card type to use the correct tuning command. Signed-off-by: Aaron Lu Reviewed-by: Philip Rakity Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sdhci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index ccefdebeff14..3c403aa8495f 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -27,6 +27,7 @@ #include #include +#include #include "sdhci.h" @@ -1245,6 +1246,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) struct sdhci_host *host; bool present; unsigned long flags; + u32 tuning_opcode; host = mmc_priv(mmc); @@ -1292,8 +1294,12 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) */ if ((host->flags & SDHCI_NEEDS_RETUNING) && !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { + /* eMMC uses cmd21 while sd and sdio use cmd19 */ + tuning_opcode = mmc->card->type == MMC_TYPE_MMC ? + MMC_SEND_TUNING_BLOCK_HS200 : + MMC_SEND_TUNING_BLOCK; spin_unlock_irqrestore(&host->lock, flags); - sdhci_execute_tuning(mmc, mrq->cmd->opcode); + sdhci_execute_tuning(mmc, tuning_opcode); spin_lock_irqsave(&host->lock, flags); /* Restore original mmc_request structure */ -- GitLab From 2cdb31f3c09f2bdd10d520a24def87d90c0030ba Mon Sep 17 00:00:00 2001 From: roger blofeld Date: Thu, 21 Jun 2012 05:27:14 +0000 Subject: [PATCH 0067/1799] powerpc/ftrace: Fix assembly trampoline register usage commit fd5a42980e1cf327b7240adf5e7b51ea41c23437 upstream. Just like the module loader, ftrace needs to be updated to use r12 instead of r11 with newer gcc's. Signed-off-by: Roger Blofeld Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/ftrace.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index bf99cfa6bbfe..63240081133e 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c @@ -245,9 +245,9 @@ __ftrace_make_nop(struct module *mod, /* * On PPC32 the trampoline looks like: - * 0x3d, 0x60, 0x00, 0x00 lis r11,sym@ha - * 0x39, 0x6b, 0x00, 0x00 addi r11,r11,sym@l - * 0x7d, 0x69, 0x03, 0xa6 mtctr r11 + * 0x3d, 0x80, 0x00, 0x00 lis r12,sym@ha + * 0x39, 0x8c, 0x00, 0x00 addi r12,r12,sym@l + * 0x7d, 0x89, 0x03, 0xa6 mtctr r12 * 0x4e, 0x80, 0x04, 0x20 bctr */ @@ -262,9 +262,9 @@ __ftrace_make_nop(struct module *mod, pr_devel(" %08x %08x ", jmp[0], jmp[1]); /* verify that this is what we expect it to be */ - if (((jmp[0] & 0xffff0000) != 0x3d600000) || - ((jmp[1] & 0xffff0000) != 0x396b0000) || - (jmp[2] != 0x7d6903a6) || + if (((jmp[0] & 0xffff0000) != 0x3d800000) || + ((jmp[1] & 0xffff0000) != 0x398c0000) || + (jmp[2] != 0x7d8903a6) || (jmp[3] != 0x4e800420)) { printk(KERN_ERR "Not a trampoline\n"); return -EINVAL; -- GitLab From a461394c31c5aa3c8cfe98dd0dc35f6b56047770 Mon Sep 17 00:00:00 2001 From: Tiejun Chen Date: Wed, 11 Jul 2012 14:22:46 +1000 Subject: [PATCH 0068/1799] powerpc: Add "memory" attribute for mfmsr() commit b416c9a10baae6a177b4f9ee858b8d309542fbef upstream. Add "memory" attribute in inline assembly language as a compiler barrier to make sure 4.6.x GCC don't reorder mfmsr(). Signed-off-by: Tiejun Chen Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/include/asm/reg.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 9d7f0fb69028..cae0ed7878ed 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1022,7 +1022,8 @@ /* Macros for setting and retrieving special purpose registers */ #ifndef __ASSEMBLY__ #define mfmsr() ({unsigned long rval; \ - asm volatile("mfmsr %0" : "=r" (rval)); rval;}) + asm volatile("mfmsr %0" : "=r" (rval) : \ + : "memory"); rval;}) #ifdef CONFIG_PPC_BOOK3S_64 #define __mtmsrd(v, l) asm volatile("mtmsrd %0," __stringify(l) \ : : "r" (v) : "memory") -- GitLab From f18e28667a2a26d0ead02cc730524fa6203ec818 Mon Sep 17 00:00:00 2001 From: Kleber Sacilotto de Souza Date: Thu, 12 Jul 2012 17:14:36 +0000 Subject: [PATCH 0069/1799] powerpc/eeh: Check handle_eeh_events() return value commit 10db8d212864cb6741df7d7fafda5ab6661f6f88 upstream. Function eeh_event_handler() dereferences the pointer returned by handle_eeh_events() without checking, causing a crash if NULL was returned, which is expected in some situations. This patch fixes this bug by checking for the value returned by handle_eeh_events() before dereferencing it. Signed-off-by: Kleber Sacilotto de Souza Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/pseries/eeh_event.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 4cb375c0f8d1..fb506317ebb0 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -85,8 +85,10 @@ static int eeh_event_handler(void * dummy) set_current_state(TASK_INTERRUPTIBLE); /* Don't add to load average */ edev = handle_eeh_events(event); - eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING); - pci_dev_put(edev->pdev); + if (edev) { + eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING); + pci_dev_put(edev->pdev); + } kfree(event); mutex_unlock(&eeh_event_mutex); -- GitLab From 753e14ef13311122aa5a819657d17940969a6f80 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 5 Jul 2012 10:08:28 -0500 Subject: [PATCH 0070/1799] powerpc/85xx: use the BRx registers to enable indirect mode on the P1022DS commit 6bd825f02966be8ba544047cab313d6032c23819 upstream. In order to enable the DIU video controller on the P1022DS, the FPGA needs to be switched to "indirect mode", where the localbus is disabled and the FPGA is accessed via writes to localbus chip select signals CS0 and CS1. To obtain the address of CS0 and CS1, the platform driver uses an "indirect pixis mode" device tree node. This node assumes that the localbus 'ranges' property is sorted in chip-select order. That is, reg value 0 maps to CS0, reg value 1 maps to CS1, etc. This is how the 'ranges' property is supposed to be arranged. Unfortunately, the 'ranges' property is often mis-arranged, and not just on the P1022DS. Linux normally does not care, since it does not program the localbus. But the indirect-mode code on the P1022DS does care. The "proper" fix is to have U-Boot fix the 'ranges' property, but this would be too cumbersome. The names and 'reg' properties of all the localbus devices would also need to be updated, and determining which localbus device maps to which chip select is board-specific. Instead, we determine the CS0/CS1 base addresses the same way that U-boot does -- by reading the BRx registers directly and mapping them to physical addresses. This code is simpler and more reliable, and it does not require a U-boot or device tree change. Since the indirect pixis device tree node is no longer needed, the node is deleted from the DTS. Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/boot/dts/p1022ds.dtsi | 16 ---- arch/powerpc/platforms/85xx/p1022_ds.c | 106 ++++++++++++++++++++++--- 2 files changed, 93 insertions(+), 29 deletions(-) diff --git a/arch/powerpc/boot/dts/p1022ds.dtsi b/arch/powerpc/boot/dts/p1022ds.dtsi index 7cdb505036bb..1b0673e36313 100644 --- a/arch/powerpc/boot/dts/p1022ds.dtsi +++ b/arch/powerpc/boot/dts/p1022ds.dtsi @@ -33,22 +33,6 @@ */ &board_lbc { - /* - * This node is used to access the pixis via "indirect" mode, - * which is done by writing the pixis register index to chip - * select 0 and the value to/from chip select 1. Indirect - * mode is the only way to access the pixis when DIU video - * is enabled. Note that this assumes that the first column - * of the 'ranges' property above is the chip select number. - */ - board-control@0,0 { - compatible = "fsl,p1022ds-indirect-pixis"; - reg = <0x0 0x0 1 /* CS0 */ - 0x1 0x0 1>; /* CS1 */ - interrupt-parent = <&mpic>; - interrupts = <8 0 0 0>; - }; - nor@0,0 { #address-cells = <1>; #size-cells = <1>; diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index f700c81a1321..978330ccdde6 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "smp.h" #include "mpc85xx.h" @@ -142,17 +143,73 @@ static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port, { } +struct fsl_law { + u32 lawbar; + u32 reserved1; + u32 lawar; + u32 reserved[5]; +}; + +#define LAWBAR_MASK 0x00F00000 +#define LAWBAR_SHIFT 12 + +#define LAWAR_EN 0x80000000 +#define LAWAR_TGT_MASK 0x01F00000 +#define LAW_TRGT_IF_LBC (0x04 << 20) + +#define LAWAR_MASK (LAWAR_EN | LAWAR_TGT_MASK) +#define LAWAR_MATCH (LAWAR_EN | LAW_TRGT_IF_LBC) + +#define BR_BA 0xFFFF8000 + +/* + * Map a BRx value to a physical address + * + * The localbus BRx registers only store the lower 32 bits of the address. To + * obtain the upper four bits, we need to scan the LAW table. The entry which + * maps to the localbus will contain the upper four bits. + */ +static phys_addr_t lbc_br_to_phys(const void *ecm, unsigned int count, u32 br) +{ +#ifndef CONFIG_PHYS_64BIT + /* + * If we only have 32-bit addressing, then the BRx address *is* the + * physical address. + */ + return br & BR_BA; +#else + const struct fsl_law *law = ecm + 0xc08; + unsigned int i; + + for (i = 0; i < count; i++) { + u64 lawbar = in_be32(&law[i].lawbar); + u32 lawar = in_be32(&law[i].lawar); + + if ((lawar & LAWAR_MASK) == LAWAR_MATCH) + /* Extract the upper four bits */ + return (br & BR_BA) | ((lawbar & LAWBAR_MASK) << 12); + } + + return 0; +#endif +} + /** * p1022ds_set_monitor_port: switch the output to a different monitor port - * */ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) { struct device_node *guts_node; - struct device_node *indirect_node = NULL; + struct device_node *lbc_node = NULL; + struct device_node *law_node = NULL; struct ccsr_guts __iomem *guts; + struct fsl_lbc_regs *lbc = NULL; + void *ecm = NULL; u8 __iomem *lbc_lcs0_ba = NULL; u8 __iomem *lbc_lcs1_ba = NULL; + phys_addr_t cs0_addr, cs1_addr; + const __be32 *iprop; + unsigned int num_laws; u8 b; /* Map the global utilities registers. */ @@ -168,25 +225,43 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) goto exit; } - indirect_node = of_find_compatible_node(NULL, NULL, - "fsl,p1022ds-indirect-pixis"); - if (!indirect_node) { - pr_err("p1022ds: missing pixis indirect mode node\n"); + lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc"); + if (!lbc_node) { + pr_err("p1022ds: missing localbus node\n"); goto exit; } - lbc_lcs0_ba = of_iomap(indirect_node, 0); - if (!lbc_lcs0_ba) { - pr_err("p1022ds: could not map localbus chip select 0\n"); + lbc = of_iomap(lbc_node, 0); + if (!lbc) { + pr_err("p1022ds: could not map localbus node\n"); goto exit; } - lbc_lcs1_ba = of_iomap(indirect_node, 1); - if (!lbc_lcs1_ba) { - pr_err("p1022ds: could not map localbus chip select 1\n"); + law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law"); + if (!law_node) { + pr_err("p1022ds: missing local access window node\n"); goto exit; } + ecm = of_iomap(law_node, 0); + if (!ecm) { + pr_err("p1022ds: could not map local access window node\n"); + goto exit; + } + + iprop = of_get_property(law_node, "fsl,num-laws", 0); + if (!iprop) { + pr_err("p1022ds: LAW node is missing fsl,num-laws property\n"); + goto exit; + } + num_laws = be32_to_cpup(iprop); + + cs0_addr = lbc_br_to_phys(ecm, num_laws, in_be32(&lbc->bank[0].br)); + cs1_addr = lbc_br_to_phys(ecm, num_laws, in_be32(&lbc->bank[1].br)); + + lbc_lcs0_ba = ioremap(cs0_addr, 1); + lbc_lcs1_ba = ioremap(cs1_addr, 1); + /* Make sure we're in indirect mode first. */ if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) != PMUXCR_ELBCDIU_DIU) { @@ -254,10 +329,15 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) iounmap(lbc_lcs1_ba); if (lbc_lcs0_ba) iounmap(lbc_lcs0_ba); + if (lbc) + iounmap(lbc); + if (ecm) + iounmap(ecm); if (guts) iounmap(guts); - of_node_put(indirect_node); + of_node_put(law_node); + of_node_put(lbc_node); of_node_put(guts_node); } -- GitLab From de0449fd59c6c6a9a523c625a014c8d8cd73810f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 21 Jun 2012 23:36:15 -0700 Subject: [PATCH 0071/1799] SCSI: libsas: continue revalidation commit 26f2f199ff150d8876b2641c41e60d1c92d2fb81 upstream. Continue running revalidation until no more broadcast devices are discovered. Fixes cases where re-discovery completes too early in a domain with multiple expanders with pending re-discovery events. Servicing BCNs can get backed up behind error recovery. Signed-off-by: Dan Williams Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libsas/sas_expander.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index caa0525d2523..79f9d559992c 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -2109,9 +2109,7 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev) struct domain_device *dev = NULL; res = sas_find_bcast_dev(port_dev, &dev); - if (res) - goto out; - if (dev) { + while (res == 0 && dev) { struct expander_device *ex = &dev->ex_dev; int i = 0, phy_id; @@ -2123,8 +2121,10 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev) res = sas_rediscover(dev, phy_id); i = phy_id + 1; } while (i < ex->num_phys); + + dev = NULL; + res = sas_find_bcast_dev(port_dev, &dev); } -out: return res; } -- GitLab From 1c06102701a00d42f2c690d97cc2203d561ea6a4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 21 Jun 2012 23:36:20 -0700 Subject: [PATCH 0072/1799] SCSI: libsas: fix sas_discover_devices return code handling commit b17caa174a7e1fd2e17b26e210d4ee91c4c28b37 upstream. commit 198439e4 [SCSI] libsas: do not set res = 0 in sas_ex_discover_dev() commit 19252de6 [SCSI] libsas: fix wide port hotplug issues The above commits seem to have confused the return value of sas_ex_discover_dev which is non-zero on failure and sas_ex_join_wide_port which just indicates short circuiting discovery on already established ports. The result is random discovery failures depending on configuration. Calls to sas_ex_join_wide_port are the source of the trouble as its return value is errantly assigned to 'res'. Convert it to bool and stop returning its result up the stack. Tested-by: Dan Melnic Reported-by: Dan Melnic Signed-off-by: Dan Williams Reviewed-by: Jack Wang Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libsas/sas_expander.c | 39 +++++++++--------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 79f9d559992c..101b28e61c6f 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -868,7 +868,7 @@ static struct domain_device *sas_ex_discover_end_dev( } /* See if this phy is part of a wide port */ -static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id) +static bool sas_ex_join_wide_port(struct domain_device *parent, int phy_id) { struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id]; int i; @@ -884,11 +884,11 @@ static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id) sas_port_add_phy(ephy->port, phy->phy); phy->port = ephy->port; phy->phy_state = PHY_DEVICE_DISCOVERED; - return 0; + return true; } } - return -ENODEV; + return false; } static struct domain_device *sas_ex_discover_expander( @@ -1030,8 +1030,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) return res; } - res = sas_ex_join_wide_port(dev, phy_id); - if (!res) { + if (sas_ex_join_wide_port(dev, phy_id)) { SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", phy_id, SAS_ADDR(ex_phy->attached_sas_addr)); return res; @@ -1077,8 +1076,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) == SAS_ADDR(child->sas_addr)) { ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED; - res = sas_ex_join_wide_port(dev, i); - if (!res) + if (sas_ex_join_wide_port(dev, i)) SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr)); @@ -1943,32 +1941,20 @@ static int sas_discover_new(struct domain_device *dev, int phy_id) { struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id]; struct domain_device *child; - bool found = false; - int res, i; + int res; SAS_DPRINTK("ex %016llx phy%d new device attached\n", SAS_ADDR(dev->sas_addr), phy_id); res = sas_ex_phy_discover(dev, phy_id); if (res) - goto out; - /* to support the wide port inserted */ - for (i = 0; i < dev->ex_dev.num_phys; i++) { - struct ex_phy *ex_phy_temp = &dev->ex_dev.ex_phy[i]; - if (i == phy_id) - continue; - if (SAS_ADDR(ex_phy_temp->attached_sas_addr) == - SAS_ADDR(ex_phy->attached_sas_addr)) { - found = true; - break; - } - } - if (found) { - sas_ex_join_wide_port(dev, phy_id); + return res; + + if (sas_ex_join_wide_port(dev, phy_id)) return 0; - } + res = sas_ex_discover_devices(dev, phy_id); - if (!res) - goto out; + if (res) + return res; list_for_each_entry(child, &dev->ex_dev.children, siblings) { if (SAS_ADDR(child->sas_addr) == SAS_ADDR(ex_phy->attached_sas_addr)) { @@ -1978,7 +1964,6 @@ static int sas_discover_new(struct domain_device *dev, int phy_id) break; } } -out: return res; } -- GitLab From bb12049078a3a69f750779a19287cd4ac5f2bc3e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 21 Jun 2012 23:25:32 -0700 Subject: [PATCH 0073/1799] SCSI: fix eh wakeup (scsi_schedule_eh vs scsi_restart_operations) commit 57fc2e335fd3c2f898ee73570dc81426c28dc7b4 upstream. Rapid ata hotplug on a libsas controller results in cases where libsas is waiting indefinitely on eh to perform an ata probe. A race exists between scsi_schedule_eh() and scsi_restart_operations() in the case when scsi_restart_operations() issues i/o to other devices in the sas domain. When this happens the host state transitions from SHOST_RECOVERY (set by scsi_schedule_eh) back to SHOST_RUNNING and ->host_busy is non-zero so we put the eh thread to sleep even though ->host_eh_scheduled is active. Before putting the error handler to sleep we need to check if the host_state needs to return to SHOST_RECOVERY for another trip through eh. Since i/o that is released by scsi_restart_operations has been blocked for at least one eh cycle, this implementation allows those i/o's to run before another eh cycle starts to discourage hung task timeouts. Reported-by: Tom Jackson Tested-by: Tom Jackson Signed-off-by: Dan Williams Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_error.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 386f0c53bea7..cc8dc8cc6d6f 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1687,6 +1687,20 @@ static void scsi_restart_operations(struct Scsi_Host *shost) * requests are started. */ scsi_run_host_queues(shost); + + /* + * if eh is active and host_eh_scheduled is pending we need to re-run + * recovery. we do this check after scsi_run_host_queues() to allow + * everything pent up since the last eh run a chance to make forward + * progress before we sync again. Either we'll immediately re-run + * recovery or scsi_device_unbusy() will wake us again when these + * pending commands complete. + */ + spin_lock_irqsave(shost->host_lock, flags); + if (shost->host_eh_scheduled) + if (scsi_host_set_state(shost, SHOST_RECOVERY)) + WARN_ON(scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)); + spin_unlock_irqrestore(shost->host_lock, flags); } /** -- GitLab From f07d3f59e35eb0fc8847587f601f84b8cfa8dd38 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 21 Jun 2012 23:47:28 -0700 Subject: [PATCH 0074/1799] SCSI: fix hot unplug vs async scan race commit 3b661a92e869ebe2358de8f4b3230ad84f7fce51 upstream. The following crash results from cases where the end_device has been removed before scsi_sysfs_add_sdev has had a chance to run. BUG: unable to handle kernel NULL pointer dereference at 0000000000000098 IP: [] sysfs_create_dir+0x32/0xb6 ... Call Trace: [] kobject_add_internal+0x120/0x1e3 [] ? trace_hardirqs_on+0xd/0xf [] kobject_add_varg+0x41/0x50 [] kobject_add+0x64/0x66 [] device_add+0x12d/0x63a [] ? _raw_spin_unlock_irqrestore+0x47/0x56 [] ? module_refcount+0x89/0xa0 [] scsi_sysfs_add_sdev+0x4e/0x28a [] do_scan_async+0x9c/0x145 ...teach scsi_sysfs_add_devices() to check for deleted devices() before trying to add them, and teach scsi_remove_target() how to remove targets that have not been added via device_add(). Reported-by: Dariusz Majchrzak Signed-off-by: Dan Williams Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_scan.c | 3 +++ drivers/scsi/scsi_sysfs.c | 41 +++++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 01b03744f1f9..8906557d2a24 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1714,6 +1714,9 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost) { struct scsi_device *sdev; shost_for_each_device(sdev, shost) { + /* target removed before the device could be added */ + if (sdev->sdev_state == SDEV_DEL) + continue; if (!scsi_host_scan_allowed(shost) || scsi_sysfs_add_sdev(sdev) != 0) __scsi_remove_device(sdev); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 04c2a278076e..f888aadc8c25 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1000,7 +1000,6 @@ static void __scsi_remove_target(struct scsi_target *starget) struct scsi_device *sdev; spin_lock_irqsave(shost->host_lock, flags); - starget->reap_ref++; restart: list_for_each_entry(sdev, &shost->__devices, siblings) { if (sdev->channel != starget->channel || @@ -1014,14 +1013,6 @@ static void __scsi_remove_target(struct scsi_target *starget) goto restart; } spin_unlock_irqrestore(shost->host_lock, flags); - scsi_target_reap(starget); -} - -static int __remove_child (struct device * dev, void * data) -{ - if (scsi_is_target_device(dev)) - __scsi_remove_target(to_scsi_target(dev)); - return 0; } /** @@ -1034,14 +1025,34 @@ static int __remove_child (struct device * dev, void * data) */ void scsi_remove_target(struct device *dev) { - if (scsi_is_target_device(dev)) { - __scsi_remove_target(to_scsi_target(dev)); - return; + struct Scsi_Host *shost = dev_to_shost(dev->parent); + struct scsi_target *starget, *found; + unsigned long flags; + + restart: + found = NULL; + spin_lock_irqsave(shost->host_lock, flags); + list_for_each_entry(starget, &shost->__targets, siblings) { + if (starget->state == STARGET_DEL) + continue; + if (starget->dev.parent == dev || &starget->dev == dev) { + found = starget; + found->reap_ref++; + break; + } } + spin_unlock_irqrestore(shost->host_lock, flags); - get_device(dev); - device_for_each_child(dev, NULL, __remove_child); - put_device(dev); + if (found) { + __scsi_remove_target(found); + scsi_target_reap(found); + /* in the case where @dev has multiple starget children, + * continue removing. + * + * FIXME: does such a case exist? + */ + goto restart; + } } EXPORT_SYMBOL(scsi_remove_target); -- GitLab From bb0f467989fd14bd4bf41b9a30b49900f9223e47 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 29 Jun 2012 15:33:22 +0000 Subject: [PATCH 0075/1799] SCSI: Fix device removal NULL pointer dereference commit 67bd94130015c507011af37858989b199c52e1de upstream. Use blk_queue_dead() to test whether the queue is dead instead of !sdev. Since scsi_prep_fn() may be invoked concurrently with __scsi_remove_device(), keep the queuedata (sdev) pointer in __scsi_remove_device(). This patch fixes a kernel oops that can be triggered by USB device removal. See also http://www.spinics.net/lists/linux-scsi/msg56254.html. Other changes included in this patch: - Swap the blk_cleanup_queue() and kfree() calls in scsi_host_dev_release() to make that code easier to grasp. - Remove the queue dead check from scsi_run_queue() since the queue state can change anyway at any point in that function where the queue lock is not held. - Remove the queue dead check from the start of scsi_request_fn() since it is redundant with the scsi_device_online() check. Reported-by: Jun'ichi Nomura Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Reviewed-by: Tejun Heo Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/hosts.c | 7 ++++--- drivers/scsi/scsi_lib.c | 32 ++++---------------------------- drivers/scsi/scsi_priv.h | 1 - drivers/scsi/scsi_sysfs.c | 5 +---- 4 files changed, 9 insertions(+), 36 deletions(-) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index a3a056a9db67..b48c24f7d21a 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -290,6 +290,7 @@ static void scsi_host_dev_release(struct device *dev) struct Scsi_Host *shost = dev_to_shost(dev); struct device *parent = dev->parent; struct request_queue *q; + void *queuedata; scsi_proc_hostdir_rm(shost->hostt); @@ -299,9 +300,9 @@ static void scsi_host_dev_release(struct device *dev) destroy_workqueue(shost->work_q); q = shost->uspace_req_q; if (q) { - kfree(q->queuedata); - q->queuedata = NULL; - scsi_free_queue(q); + queuedata = q->queuedata; + blk_cleanup_queue(q); + kfree(queuedata); } scsi_destroy_command_freelist(shost); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 4037fd5b1e00..f97edb75e568 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -406,10 +406,6 @@ static void scsi_run_queue(struct request_queue *q) 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); @@ -1370,16 +1366,16 @@ static inline int scsi_host_queue_ready(struct request_queue *q, * may be changed after request stacking drivers call the function, * regardless of taking lock or not. * - * When scsi can't dispatch I/Os anymore and needs to kill I/Os - * (e.g. !sdev), scsi needs to return 'not busy'. - * Otherwise, request stacking drivers may hold requests forever. + * When scsi can't dispatch I/Os anymore and needs to kill I/Os scsi + * needs to return 'not busy'. Otherwise, request stacking drivers + * may hold requests forever. */ static int scsi_lld_busy(struct request_queue *q) { struct scsi_device *sdev = q->queuedata; struct Scsi_Host *shost; - if (!sdev) + if (blk_queue_dead(q)) return 0; shost = sdev->host; @@ -1490,12 +1486,6 @@ static void scsi_request_fn(struct request_queue *q) struct scsi_cmnd *cmd; struct request *req; - if (!sdev) { - while ((req = blk_peek_request(q)) != NULL) - scsi_kill_request(req, q); - return; - } - if(!get_device(&sdev->sdev_gendev)) /* We must be tearing the block queue down already */ return; @@ -1697,20 +1687,6 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) return q; } -void scsi_free_queue(struct request_queue *q) -{ - unsigned long flags; - - WARN_ON(q->queuedata); - - /* cause scsi_request_fn() to kill all non-finished requests */ - spin_lock_irqsave(q->queue_lock, flags); - q->request_fn(q); - spin_unlock_irqrestore(q->queue_lock, flags); - - blk_cleanup_queue(q); -} - /* * Function: scsi_block_requests() * diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index be4fa6d179b1..fd9f57fd2102 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -84,7 +84,6 @@ extern void scsi_next_command(struct scsi_cmnd *cmd); extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); extern void scsi_run_host_queues(struct Scsi_Host *shost); extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev); -extern void scsi_free_queue(struct request_queue *q); extern int scsi_init_queue(void); extern void scsi_exit_queue(void); struct request_queue; diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index f888aadc8c25..bb7c4828acc0 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -971,11 +971,8 @@ void __scsi_remove_device(struct scsi_device *sdev) 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); + blk_cleanup_queue(sdev->request_queue); put_device(dev); } -- GitLab From 84ecccfc25f7dda4f1d2aeb6db0658368d3ef185 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 29 Jun 2012 15:34:26 +0000 Subject: [PATCH 0076/1799] SCSI: Avoid dangling pointer in scsi_requeue_command() commit 940f5d47e2f2e1fa00443921a0abf4822335b54d upstream. When we call scsi_unprep_request() the command associated with the request gets destroyed and therefore drops its reference on the device. If this was the only reference, the device may get released and we end up with a NULL pointer deref when we call blk_requeue_request. Reported-by: Mike Christie Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Reviewed-by: Tejun Heo [jejb: enhance commend and add commit log for stable] Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_lib.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index f97edb75e568..19291463c554 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -479,15 +479,26 @@ void scsi_requeue_run_queue(struct work_struct *work) */ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) { + struct scsi_device *sdev = cmd->device; struct request *req = cmd->request; unsigned long flags; + /* + * We need to hold a reference on the device to avoid the queue being + * killed after the unlock and before scsi_run_queue is invoked which + * may happen because scsi_unprep_request() puts the command which + * releases its reference on the device. + */ + get_device(&sdev->sdev_gendev); + spin_lock_irqsave(q->queue_lock, flags); scsi_unprep_request(req); blk_requeue_request(q, req); spin_unlock_irqrestore(q->queue_lock, flags); scsi_run_queue(q); + + put_device(&sdev->sdev_gendev); } void scsi_next_command(struct scsi_cmnd *cmd) -- GitLab From c4c3d44ab775fa457c49d7fce906df0a310bb347 Mon Sep 17 00:00:00 2001 From: Albert Pool Date: Mon, 14 May 2012 18:08:32 +0200 Subject: [PATCH 0077/1799] rt2800usb: 2001:3c17 is an RT3370 device commit 8fd9d059af12786341dec5a688e607bcdb372238 upstream. D-Link DWA-123 rev A1 Signed-off-by: Albert Pool Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2800usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 5601302d09ad..f388b65fbe90 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1137,6 +1137,8 @@ static struct usb_device_id rt2800usb_device_table[] = { #ifdef CONFIG_RT2800USB_RT33XX /* Belkin */ { USB_DEVICE(0x050d, 0x945b) }, + /* D-Link */ + { USB_DEVICE(0x2001, 0x3c17) }, /* Panasonic */ { USB_DEVICE(0x083a, 0xb511) }, /* Philips */ @@ -1237,7 +1239,6 @@ static struct usb_device_id rt2800usb_device_table[] = { /* D-Link */ { USB_DEVICE(0x07d1, 0x3c0b) }, { USB_DEVICE(0x07d1, 0x3c17) }, - { USB_DEVICE(0x2001, 0x3c17) }, /* Encore */ { USB_DEVICE(0x203d, 0x14a1) }, /* Gemtek */ -- GitLab From 0706b27d2ff206bdbeb457a56944ca372e6a9d8e Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Fri, 18 May 2012 12:26:19 -0500 Subject: [PATCH 0078/1799] ARM: OMAP2+: OPP: Fix to ensure check of right oppdef after bad one commit b110547e586eb5825bc1d04aa9147bff83b57672 upstream. Commit 9fa2df6b90786301b175e264f5fa9846aba81a65 (ARM: OMAP2+: OPP: allow OPP enumeration to continue if device is not present) makes the logic: for (i = 0; i < opp_def_size; i++) { if (!oh || !oh->od) { continue; } opp_def++; } In short, the moment we hit a "Bad OPP", we end up looping the list comparing against the bad opp definition pointer for the rest of the iteration count. Instead, increment opp_def in the for loop itself and allow continue to be used in code without much thought so that we check the next set of OPP definition pointers :) Cc: Steve Sakoman Cc: Tony Lindgren Signed-off-by: Nishanth Menon Signed-off-by: Kevin Hilman Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap2/opp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c index de6d46451746..d8f6dbf45d16 100644 --- a/arch/arm/mach-omap2/opp.c +++ b/arch/arm/mach-omap2/opp.c @@ -53,7 +53,7 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def, omap_table_init = 1; /* Lets now register with OPP library */ - for (i = 0; i < opp_def_size; i++) { + for (i = 0; i < opp_def_size; i++, opp_def++) { struct omap_hwmod *oh; struct device *dev; @@ -86,7 +86,6 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def, __func__, opp_def->freq, opp_def->hwmod_name, i, r); } - opp_def++; } return 0; -- GitLab From a73185355e3d19694b655528811e54cc086a5bcf Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 20 Jul 2012 17:29:34 +0100 Subject: [PATCH 0079/1799] ASoC: dapm: Fix _PRE and _POST events for DAPM performance improvements commit 0ff97ebf0804d2e519d578fcb4db03f104d2ca8c upstream. Ever since the DAPM performance improvements we've been marking all widgets as not dirty after each DAPM run. Since _PRE and _POST events aren't part of the DAPM graph this has rendered them non-functional, they will never be marked dirty again and thus will never be run again. Fix this by skipping them when marking widgets as not dirty. Signed-off-by: Mark Brown Acked-by: Liam Girdwood Signed-off-by: Greg Kroah-Hartman --- sound/soc/soc-dapm.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 1bb6d4a63cd8..c41efe01a819 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1442,7 +1442,15 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) } list_for_each_entry(w, &card->widgets, list) { - list_del_init(&w->dirty); + switch (w->id) { + case snd_soc_dapm_pre: + case snd_soc_dapm_post: + /* These widgets always need to be powered */ + break; + default: + list_del_init(&w->dirty); + break; + } if (w->power) { d = w->dapm; -- GitLab From 8f1b438887c47d3b65fc64ca23821d69ba69ddd7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 11 Jul 2012 19:03:48 +0100 Subject: [PATCH 0080/1799] ASoC: wm8962: Redo early init of the part on resume commit e4dd76788c7e5b27165890d712c8c4f6f0abd645 upstream. Ensure robust startup of the part by going through the reset procedure prior to resyncing the full register cache, avoiding potential intermittent faults in some designs. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8962.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 15d467ff91b4..08850f8fdb58 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3710,6 +3710,9 @@ static int wm8962_runtime_resume(struct device *dev) } regcache_cache_only(wm8962->regmap, false); + + wm8962_reset(wm8962); + regcache_sync(wm8962->regmap); regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, -- GitLab From 4e613aa6c586c99341a3ca40fd7f872b7dee1749 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 18 Jul 2012 07:38:46 +0200 Subject: [PATCH 0081/1799] ALSA: hda - Add support for Realtek ALC282 commit 4e01ec636e64707d202a1ca21a47bbc6d53085b7 upstream. This codec has a separate dmic path (separate dmic only ADC), and thus it looks mostly like ALC275. BugLink: https://bugs.launchpad.net/bugs/1025377 Tested-by: Ray Chen 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 c43264f5981c..10c1bc79ad10 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6977,6 +6977,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 }, { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 }, { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, + { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", .patch = patch_alc861 }, { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, -- GitLab From 761f186a0f94f7bd1c9c844f96cf0b8bbb6e2abb Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Thu, 19 Jul 2012 17:52:58 -0700 Subject: [PATCH 0082/1799] ALSA: hda - Turn on PIN_OUT from hdmi playback prepare. commit 9e76e6d031482194a5b24d8e9ab88063fbd6b4b5 upstream. Turn on the pin widget's PIN_OUT bit from playback prepare. The pin is enabled in open, but is disabled in hdmi_init_pin which is called during system resume. This causes a system suspend/resume during playback to mute HDMI/DP. Enabling the pin in prepare instead of open allows calling snd_pcm_prepare after a system resume to restore audio. Signed-off-by: Dylan Reid Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_hdmi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 83f345f3c961..d1b805aefa57 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -876,7 +876,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, struct hdmi_spec_per_pin *per_pin; struct hdmi_eld *eld; struct hdmi_spec_per_cvt *per_cvt = NULL; - int pinctl; /* Validate hinfo */ pin_idx = hinfo_to_pin_index(spec, hinfo); @@ -912,11 +911,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, snd_hda_codec_write(codec, per_pin->pin_nid, 0, AC_VERB_SET_CONNECT_SEL, mux_idx); - pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - snd_hda_codec_write(codec, per_pin->pin_nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - pinctl | PIN_OUT); snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); /* Initially set the converter's capabilities */ @@ -1153,11 +1147,17 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct hdmi_spec *spec = codec->spec; int pin_idx = hinfo_to_pin_index(spec, hinfo); hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid; + int pinctl; hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); hdmi_setup_audio_infoframe(codec, pin_idx, substream); + pinctl = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl | PIN_OUT); + return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); } -- GitLab From 2af3ad34568307d037dc7ab8f923b51e068b33c4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 4 Jul 2012 09:18:01 +0200 Subject: [PATCH 0083/1799] usbdevfs: Correct amount of data copied to user in processcompl_compat commit 2102e06a5f2e414694921f23591f072a5ba7db9f upstream. iso data buffers may have holes in them if some packets were short, so for iso urbs we should always copy the entire buffer, just like the regular processcompl does. Signed-off-by: Hans de Goede Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 4e577728ead6..404413b0b938 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1615,10 +1615,14 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) void __user *addr = as->userurb; unsigned int i; - if (as->userbuffer && urb->actual_length) - if (copy_to_user(as->userbuffer, urb->transfer_buffer, - urb->actual_length)) + if (as->userbuffer && urb->actual_length) { + if (urb->number_of_packets > 0) /* Isochronous */ + i = urb->transfer_buffer_length; + else /* Non-Isoc */ + i = urb->actual_length; + if (copy_to_user(as->userbuffer, urb->transfer_buffer, i)) return -EFAULT; + } if (put_user(as->status, &userurb->status)) return -EFAULT; if (put_user(urb->actual_length, &userurb->actual_length)) -- GitLab From 2cfe89c15298554d5cf9160bf6d8eef290d34041 Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Sun, 24 Jun 2012 21:11:22 -0700 Subject: [PATCH 0084/1799] usb: gadget: Fix g_ether interface link status commit 31bde1ceaa873bcaecd49e829bfabceacc4c512d upstream. A "usb0" interface that has never been connected to a host has an unknown operstate, and therefore the IFF_RUNNING flag is (incorrectly) asserted when queried by ifconfig, ifplugd, etc. This is a result of calling netif_carrier_off() too early in the probe function; it should be called after register_netdev(). Similar problems have been fixed in many other drivers, e.g.: e826eafa6 (bonding: Call netif_carrier_off after register_netdevice) 0d672e9f8 (drivers/net: Call netif_carrier_off at the end of the probe) 6a3c869a6 (cxgb4: fix reported state of interfaces without link) Fix is to move netif_carrier_off() to the end of the function. Signed-off-by: Kevin Cernekee Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/u_ether.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 29c854bbca44..4e1f0aaafcfe 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -796,12 +796,6 @@ int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]) SET_ETHTOOL_OPS(net, &ops); - /* two kinds of host-initiated state changes: - * - iff DATA transfer is active, carrier is "on" - * - tx queueing enabled if open *and* carrier is "on" - */ - netif_carrier_off(net); - dev->gadget = g; SET_NETDEV_DEV(net, &g->dev); SET_NETDEV_DEVTYPE(net, &gadget_type); @@ -815,6 +809,12 @@ int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]) INFO(dev, "HOST MAC %pM\n", dev->host_mac); the_dev = dev; + + /* two kinds of host-initiated state changes: + * - iff DATA transfer is active, carrier is "on" + * - tx queueing enabled if open *and* carrier is "on" + */ + netif_carrier_off(net); } return status; -- GitLab From 11ca5d15e7a84181788c01adc4049a36e387dd84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 12 Jul 2012 12:37:32 +0200 Subject: [PATCH 0085/1799] USB: option: add ZTE MF821D MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 09110529780890804b22e997ae6b4fe3f0b3b158 upstream. Sold by O2 (telefonica germany) under the name "LTE4G" Tested-by: Thomas Schäfer Signed-off-by: Bjørn Mork 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 49484b39cc09..ae1a4b8c6893 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -936,6 +936,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), -- GitLab From 22dacbd152e98dfd627664f5ee3c21d2bd32430b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 19 Jun 2012 09:54:48 +0200 Subject: [PATCH 0086/1799] Revert "usb/uas: make sure data urb is gone if we receive status before that" commit c621a81edecdee85da32c566c21836332c764fda upstream. This reverts commit e4d8318a85779b25b880187b1b1c44e797bd7d4b. This patch makes uas.c call usb_unlink_urb on data urbs. The data urbs get freed in the completion callback. This is illegal according to the usb_unlink_urb documentation. This patch also makes the code expect the data completion callback being called before the status completion callback. This isn't guaranteed to be the case, even though the actual data transfer should be finished by the time the status is received. Background: The ehci irq handler for example only know that there are finished transfers, it then has go check the QHs & TDs to see which transfers did actually finish. It has no way to figure in which order the transfers did complete. The xhci driver can call the callbacks in completion order thanks to the event queue. This does nicely explain why the driver is solid on a (usb2) xhci port whereas it goes crazy on ehci in my testing. Signed-off-by: Gerd Hoffmann Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/uas.c | 90 +++++++-------------------------------- 1 file changed, 15 insertions(+), 75 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 8ec8a6e66f50..f98ba40352c1 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -58,9 +58,6 @@ enum { SUBMIT_DATA_OUT_URB = (1 << 5), ALLOC_CMD_URB = (1 << 6), SUBMIT_CMD_URB = (1 << 7), - COMPLETED_DATA_IN = (1 << 8), - COMPLETED_DATA_OUT = (1 << 9), - DATA_COMPLETES_CMD = (1 << 10), }; /* Overrides scsi_pointer */ @@ -114,7 +111,6 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) { struct sense_iu *sense_iu = urb->transfer_buffer; struct scsi_device *sdev = cmnd->device; - struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; if (urb->actual_length > 16) { unsigned len = be16_to_cpup(&sense_iu->len); @@ -132,15 +128,13 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) } cmnd->result = sense_iu->status; - if (!(cmdinfo->state & DATA_COMPLETES_CMD)) - cmnd->scsi_done(cmnd); + cmnd->scsi_done(cmnd); } static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) { struct sense_iu_old *sense_iu = urb->transfer_buffer; struct scsi_device *sdev = cmnd->device; - struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; if (urb->actual_length > 8) { unsigned len = be16_to_cpup(&sense_iu->len) - 2; @@ -158,8 +152,7 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) } cmnd->result = sense_iu->status; - if (!(cmdinfo->state & DATA_COMPLETES_CMD)) - cmnd->scsi_done(cmnd); + cmnd->scsi_done(cmnd); } static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, @@ -184,7 +177,6 @@ static void uas_stat_cmplt(struct urb *urb) struct Scsi_Host *shost = urb->context; struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; struct scsi_cmnd *cmnd; - struct uas_cmd_info *cmdinfo; u16 tag; int ret; @@ -210,32 +202,12 @@ static void uas_stat_cmplt(struct urb *urb) dev_err(&urb->dev->dev, "failed submit status urb\n"); return; } - cmdinfo = (void *)&cmnd->SCp; switch (iu->iu_id) { case IU_ID_STATUS: if (devinfo->cmnd == cmnd) devinfo->cmnd = NULL; - if (!(cmdinfo->state & COMPLETED_DATA_IN) && - cmdinfo->data_in_urb) { - if (devinfo->use_streams) { - cmdinfo->state |= DATA_COMPLETES_CMD; - usb_unlink_urb(cmdinfo->data_in_urb); - } else { - usb_free_urb(cmdinfo->data_in_urb); - } - } - if (!(cmdinfo->state & COMPLETED_DATA_OUT) && - cmdinfo->data_out_urb) { - if (devinfo->use_streams) { - cmdinfo->state |= DATA_COMPLETES_CMD; - usb_unlink_urb(cmdinfo->data_in_urb); - } else { - usb_free_urb(cmdinfo->data_out_urb); - } - } - if (urb->actual_length < 16) devinfo->uas_sense_old = 1; if (devinfo->uas_sense_old) @@ -264,59 +236,27 @@ static void uas_stat_cmplt(struct urb *urb) dev_err(&urb->dev->dev, "failed submit status urb\n"); } -static void uas_data_out_cmplt(struct urb *urb) -{ - struct scsi_cmnd *cmnd = urb->context; - struct scsi_data_buffer *sdb = scsi_out(cmnd); - struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; - - cmdinfo->state |= COMPLETED_DATA_OUT; - - sdb->resid = sdb->length - urb->actual_length; - usb_free_urb(urb); - - if (cmdinfo->state & DATA_COMPLETES_CMD) - cmnd->scsi_done(cmnd); -} - -static void uas_data_in_cmplt(struct urb *urb) +static void uas_data_cmplt(struct urb *urb) { - struct scsi_cmnd *cmnd = urb->context; - struct scsi_data_buffer *sdb = scsi_in(cmnd); - struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; - - cmdinfo->state |= COMPLETED_DATA_IN; - + struct scsi_data_buffer *sdb = urb->context; sdb->resid = sdb->length - urb->actual_length; usb_free_urb(urb); - - if (cmdinfo->state & DATA_COMPLETES_CMD) - cmnd->scsi_done(cmnd); } static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, - unsigned int pipe, struct scsi_cmnd *cmnd, - enum dma_data_direction dir) + unsigned int pipe, u16 stream_id, + struct scsi_data_buffer *sdb, + enum dma_data_direction dir) { - struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; struct usb_device *udev = devinfo->udev; struct urb *urb = usb_alloc_urb(0, gfp); - struct scsi_data_buffer *sdb; - usb_complete_t complete_fn; - u16 stream_id = cmdinfo->stream; if (!urb) goto out; - if (dir == DMA_FROM_DEVICE) { - sdb = scsi_in(cmnd); - complete_fn = uas_data_in_cmplt; - } else { - sdb = scsi_out(cmnd); - complete_fn = uas_data_out_cmplt; - } - usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, - complete_fn, cmnd); - urb->stream_id = stream_id; + usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, uas_data_cmplt, + sdb); + if (devinfo->use_streams) + urb->stream_id = stream_id; urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0; urb->sg = sdb->table.sgl; out: @@ -418,8 +358,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (cmdinfo->state & ALLOC_DATA_IN_URB) { cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp, - devinfo->data_in_pipe, cmnd, - DMA_FROM_DEVICE); + devinfo->data_in_pipe, cmdinfo->stream, + scsi_in(cmnd), DMA_FROM_DEVICE); if (!cmdinfo->data_in_urb) return SCSI_MLQUEUE_DEVICE_BUSY; cmdinfo->state &= ~ALLOC_DATA_IN_URB; @@ -436,8 +376,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (cmdinfo->state & ALLOC_DATA_OUT_URB) { cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp, - devinfo->data_out_pipe, cmnd, - DMA_TO_DEVICE); + devinfo->data_out_pipe, cmdinfo->stream, + scsi_out(cmnd), DMA_TO_DEVICE); if (!cmdinfo->data_out_urb) return SCSI_MLQUEUE_DEVICE_BUSY; cmdinfo->state &= ~ALLOC_DATA_OUT_URB; -- GitLab From 2830f9a08c084bcf40819942f04d0ca500faf4b8 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Fri, 20 Jul 2012 10:37:25 +0200 Subject: [PATCH 0087/1799] ALSA: hda - add dock support for Thinkpad X230 Tablet commit 108cc108a3bb42fe4705df1317ff98e1e29428a6 upstream. Also add a model/fixup string "lenovo-dock", so that other Thinkpad users will be able to test this fixup easily, to see if it enables dock I/O for them as well. BugLink: https://bugs.launchpad.net/bugs/1026953 Tested-by: John McCarron Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- Documentation/sound/alsa/HD-Audio-Models.txt | 3 ++- sound/pci/hda/patch_realtek.c | 27 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 03f7897c6414..286ec04d1383 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -21,10 +21,11 @@ ALC267/268 ========== N/A -ALC269 +ALC269/270/275/276/280/282 ====== laptop-amic Laptops with analog-mic input laptop-dmic Laptops with digital-mic input + lenovo-dock Enables docking station I/O for some Lenovos ALC662/663/272 ============== diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 10c1bc79ad10..88ccc0f62b1c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5858,6 +5858,15 @@ static int alc269_resume(struct hda_codec *codec) } #endif /* CONFIG_PM */ +static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + if (action == ALC_FIXUP_ACT_PRE_PROBE) + spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP; +} + static void alc269_fixup_hweq(struct hda_codec *codec, const struct alc_fixup *fix, int action) { @@ -5984,6 +5993,8 @@ enum { ALC269VB_FIXUP_AMIC, ALC269VB_FIXUP_DMIC, ALC269_FIXUP_MIC2_MUTE_LED, + ALC269_FIXUP_LENOVO_DOCK, + ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT, }; static const struct alc_fixup alc269_fixups[] = { @@ -6108,6 +6119,20 @@ static const struct alc_fixup alc269_fixups[] = { .type = ALC_FIXUP_FUNC, .v.func = alc269_fixup_mic2_mute, }, + [ALC269_FIXUP_LENOVO_DOCK] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x19, 0x23a11040 }, /* dock mic */ + { 0x1b, 0x2121103f }, /* dock headphone */ + { } + }, + .chained = true, + .chain_id = ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT + }, + [ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc269_fixup_pincfg_no_hp_to_lineout, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -6131,6 +6156,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), @@ -6189,6 +6215,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { static const struct alc_model_fixup alc269_fixup_models[] = { {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"}, {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"}, + {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"}, {} }; -- GitLab From 7b689c5d930f281e417597af9f817ba03dc9d898 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Wed, 11 Jul 2012 10:20:47 -0700 Subject: [PATCH 0088/1799] x86/mce: Fix siginfo_t->si_addr value for non-recoverable memory faults commit 6751ed65dc6642af64f7b8a440a75563c8aab7ae upstream. In commit dad1743e5993f1 ("x86/mce: Only restart instruction after machine check recovery if it is safe") we fixed mce_notify_process() to force a signal to the current process if it was not restartable (RIPV bit not set in MCG_STATUS). But doing it here means that the process doesn't get told the virtual address of the fault via siginfo_t->si_addr. This would prevent application level recovery from the fault. Make a new MF_MUST_KILL flag bit for memory_failure() et al. to use so that we will provide the right information with the signal. Signed-off-by: Tony Luck Acked-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/mce.c | 6 ++++-- include/linux/mm.h | 1 + mm/memory-failure.c | 14 ++++++++------ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 61604aefc40c..0d2db0e7caf4 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1180,6 +1180,7 @@ void mce_notify_process(void) { unsigned long pfn; struct mce_info *mi = mce_find_info(); + int flags = MF_ACTION_REQUIRED; if (!mi) mce_panic("Lost physical address for unconsumed uncorrectable error", NULL, NULL); @@ -1194,8 +1195,9 @@ void mce_notify_process(void) * doomed. We still need to mark the page as poisoned and alert any * other users of the page. */ - if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0 || - mi->restartable == 0) { + if (!mi->restartable) + flags |= MF_MUST_KILL; + if (memory_failure(pfn, MCE_VECTOR, flags) < 0) { pr_err("Memory error not recovered"); force_sig(SIGBUS, current); } diff --git a/include/linux/mm.h b/include/linux/mm.h index 74aa71bea1e4..441a5641036b 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1595,6 +1595,7 @@ void vmemmap_populate_print_last(void); enum mf_flags { MF_COUNT_INCREASED = 1 << 0, MF_ACTION_REQUIRED = 1 << 1, + MF_MUST_KILL = 1 << 2, }; extern int memory_failure(unsigned long pfn, int trapno, int flags); extern void memory_failure_queue(unsigned long pfn, int trapno, int flags); diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 97cc2733551a..0de20d7168f7 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -345,14 +345,14 @@ static void add_to_kill(struct task_struct *tsk, struct page *p, * Also when FAIL is set do a force kill because something went * wrong earlier. */ -static void kill_procs(struct list_head *to_kill, int doit, int trapno, +static void kill_procs(struct list_head *to_kill, int forcekill, int trapno, int fail, struct page *page, unsigned long pfn, int flags) { struct to_kill *tk, *next; list_for_each_entry_safe (tk, next, to_kill, nd) { - if (doit) { + if (forcekill) { /* * In case something went wrong with munmapping * make sure the process doesn't catch the @@ -858,7 +858,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, struct address_space *mapping; LIST_HEAD(tokill); int ret; - int kill = 1; + int kill = 1, forcekill; struct page *hpage = compound_head(p); struct page *ppage; @@ -888,7 +888,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, * be called inside page lock (it's recommended but not enforced). */ mapping = page_mapping(hpage); - if (!PageDirty(hpage) && mapping && + if (!(flags & MF_MUST_KILL) && !PageDirty(hpage) && mapping && mapping_cap_writeback_dirty(mapping)) { if (page_mkclean(hpage)) { SetPageDirty(hpage); @@ -965,12 +965,14 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, * Now that the dirty bit has been propagated to the * struct page and all unmaps done we can decide if * killing is needed or not. Only kill when the page - * was dirty, otherwise the tokill list is merely + * was dirty or the process is not restartable, + * otherwise the tokill list is merely * freed. When there was a problem unmapping earlier * use a more force-full uncatchable kill to prevent * any accesses to the poisoned memory. */ - kill_procs(&tokill, !!PageDirty(ppage), trapno, + forcekill = PageDirty(ppage) || (flags & MF_MUST_KILL); + kill_procs(&tokill, forcekill, trapno, ret != SWAP_SUCCESS, p, pfn, flags); return ret; -- GitLab From fd3cca0a4e6ac0512e9122f59dfe0214b74049fb Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 23 Jul 2012 15:17:17 -0400 Subject: [PATCH 0089/1799] locks: fix checking of fcntl_setlease argument commit 0ec4f431eb56d633da3a55da67d5c4b88886ccc7 upstream. The only checks of the long argument passed to fcntl(fd,F_SETLEASE,.) are done after converting the long to an int. Thus some illegal values may be let through and cause problems in later code. [ They actually *don't* cause problems in mainline, as of Dave Jones's commit 8d657eb3b438 "Remove easily user-triggerable BUG from generic_setlease", but we should fix this anyway. And this patch will be necessary to fix real bugs on earlier kernels. ] Signed-off-by: J. Bruce Fields Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/locks.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/locks.c b/fs/locks.c index 6a64f154db04..fcc50ab71cc6 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -308,7 +308,7 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock, return 0; } -static int assign_type(struct file_lock *fl, int type) +static int assign_type(struct file_lock *fl, long type) { switch (type) { case F_RDLCK: @@ -445,7 +445,7 @@ static const struct lock_manager_operations lease_manager_ops = { /* * Initialize a lease, use the default lock manager operations */ -static int lease_init(struct file *filp, int type, struct file_lock *fl) +static int lease_init(struct file *filp, long type, struct file_lock *fl) { if (assign_type(fl, type) != 0) return -EINVAL; @@ -463,7 +463,7 @@ static int lease_init(struct file *filp, int type, struct file_lock *fl) } /* Allocate a file_lock initialised to this type of lease */ -static struct file_lock *lease_alloc(struct file *filp, int type) +static struct file_lock *lease_alloc(struct file *filp, long type) { struct file_lock *fl = locks_alloc_lock(); int error = -ENOMEM; -- GitLab From d3dd392851e014c90ce9e26d03a93188840a5a0b Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Sat, 16 Jun 2012 15:30:45 +0200 Subject: [PATCH 0090/1799] ftrace: Disable function tracing during suspend/resume and hibernation, again commit 443772d408a25af62498793f6f805ce3c559309a upstream. If function tracing is enabled for some of the low-level suspend/resume functions, it leads to triple fault during resume from suspend, ultimately ending up in a reboot instead of a resume (or a total refusal to come out of suspended state, on some machines). This issue was explained in more detail in commit f42ac38c59e0a03d (ftrace: disable tracing for suspend to ram). However, the changes made by that commit got reverted by commit cbe2f5a6e84eebb (tracing: allow tracing of suspend/resume & hibernation code again). So, unfortunately since things are not yet robust enough to allow tracing of low-level suspend/resume functions, suspend/resume is still broken when ftrace is enabled. So fix this by disabling function tracing during suspend/resume & hibernation. Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- kernel/power/hibernate.c | 6 ++++++ kernel/power/suspend.c | 3 +++ 2 files changed, 9 insertions(+) diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index e09dfbfeecee..52a18173c845 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -352,6 +352,7 @@ int hibernation_snapshot(int platform_mode) } suspend_console(); + ftrace_stop(); pm_restrict_gfp_mask(); error = dpm_suspend(PMSG_FREEZE); @@ -377,6 +378,7 @@ int hibernation_snapshot(int platform_mode) if (error || !in_suspend) pm_restore_gfp_mask(); + ftrace_start(); resume_console(); dpm_complete(msg); @@ -479,6 +481,7 @@ int hibernation_restore(int platform_mode) pm_prepare_console(); suspend_console(); + ftrace_stop(); pm_restrict_gfp_mask(); error = dpm_suspend_start(PMSG_QUIESCE); if (!error) { @@ -486,6 +489,7 @@ int hibernation_restore(int platform_mode) dpm_resume_end(PMSG_RECOVER); } pm_restore_gfp_mask(); + ftrace_start(); resume_console(); pm_restore_console(); return error; @@ -512,6 +516,7 @@ int hibernation_platform_enter(void) entering_platform_hibernation = true; suspend_console(); + ftrace_stop(); error = dpm_suspend_start(PMSG_HIBERNATE); if (error) { if (hibernation_ops->recover) @@ -555,6 +560,7 @@ int hibernation_platform_enter(void) Resume_devices: entering_platform_hibernation = false; dpm_resume_end(PMSG_RESTORE); + ftrace_start(); resume_console(); Close: diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 396d262b8fd0..c8b7446b27df 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "power.h" @@ -212,6 +213,7 @@ int suspend_devices_and_enter(suspend_state_t state) goto Close; } suspend_console(); + ftrace_stop(); suspend_test_start(); error = dpm_suspend_start(PMSG_SUSPEND); if (error) { @@ -231,6 +233,7 @@ int suspend_devices_and_enter(suspend_state_t state) suspend_test_start(); dpm_resume_end(PMSG_RESUME); suspend_test_finish("resume devices"); + ftrace_start(); resume_console(); Close: if (suspend_ops->end) -- GitLab From 46dbb0f5903b71e3c7b37e4ad707a9aa70fe3eed Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 19 Jul 2012 10:38:06 +0200 Subject: [PATCH 0091/1799] PM / Sleep: call early resume handlers when suspend_noirq fails commit 064b021fbe470ecc9ca10f9f87af48c0fc0865fb upstream. Commit cf579dfb82550e34de7ccf3ef090d8b834ccd3a9 (PM / Sleep: Introduce "late suspend" and "early resume" of devices) introduced a bug where suspend_late handlers would be called, but if dpm_suspend_noirq returned an error the early_resume handlers would never be called. All devices would end up on the dpm_late_early_list, and would never be resumed again. Fix it by calling dpm_resume_early when dpm_suspend_noirq returns an error. Signed-off-by: Colin Cross Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 3085f9bcdd85..f7eff25ffe49 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -979,8 +979,16 @@ static int dpm_suspend_late(pm_message_t state) int dpm_suspend_end(pm_message_t state) { int error = dpm_suspend_late(state); + if (error) + return error; - return error ? : dpm_suspend_noirq(state); + error = dpm_suspend_noirq(state); + if (error) { + dpm_resume_early(state); + return error; + } + + return 0; } EXPORT_SYMBOL_GPL(dpm_suspend_end); -- GitLab From ecbd55f98e07e25d4017077d0a611ce6c766257b Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Tue, 24 Apr 2012 17:38:17 -0300 Subject: [PATCH 0092/1799] TPM: chip disabled state erronously being reported as error commit 24ebe6670de3d1f0dca11c9eb372134c7ab05503 upstream. tpm_do_selftest() attempts to read a PCR in order to decide if one can rely on the TPM being used or not. The function that's used by __tpm_pcr_read() does not expect the TPM to be disabled or deactivated, and if so, reports an error. It's fine if the TPM returns this error when trying to use it for the first time after a power cycle, but it's definitely not if it already returned success for a previous attempt to read one of its PCRs. The tpm_do_selftest() was modified so that the driver only reports this return code as an error when it really is. Reported-and-tested-by: Paul Bolle Signed-off-by: Rajiv Andrade Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index ad7c7320dd1b..08427abf5fa5 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -827,10 +827,10 @@ EXPORT_SYMBOL_GPL(tpm_pcr_extend); int tpm_do_selftest(struct tpm_chip *chip) { int rc; - u8 digest[TPM_DIGEST_SIZE]; unsigned int loops; unsigned int delay_msec = 1000; unsigned long duration; + struct tpm_cmd_t cmd; duration = tpm_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST); @@ -845,7 +845,15 @@ int tpm_do_selftest(struct tpm_chip *chip) return rc; do { - rc = __tpm_pcr_read(chip, 0, digest); + /* Attempt to read a PCR value */ + cmd.header.in = pcrread_header; + cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0); + rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE); + + if (rc < TPM_HEADER_SIZE) + return -EFAULT; + + rc = be32_to_cpu(cmd.header.out.return_code); if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { dev_info(chip->dev, "TPM is disabled/deactivated (0x%X)\n", rc); -- GitLab From 20855fe2097ccfde927c6997101ae35340f1d278 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 19 Jul 2012 06:13:36 +0000 Subject: [PATCH 0093/1799] tun: fix a crash bug and a memory leak commit b09e786bd1dd66418b69348cb110f3a64764626a upstream. This patch fixes a crash tun_chr_close -> netdev_run_todo -> tun_free_netdev -> sk_release_kernel -> sock_release -> iput(SOCK_INODE(sock)) introduced by commit 1ab5ecb90cb6a3df1476e052f76a6e8f6511cb3d The problem is that this socket is embedded in struct tun_struct, it has no inode, iput is called on invalid inode, which modifies invalid memory and optionally causes a crash. sock_release also decrements sockets_in_use, this causes a bug that "sockets: used" field in /proc/*/net/sockstat keeps on decreasing when creating and closing tun devices. This patch introduces a flag SOCK_EXTERNALLY_ALLOCATED that instructs sock_release to not free the inode and not decrement sockets_in_use, fixing both memory corruption and sockets_in_use underflow. It should be backported to 3.3 an 3.4 stabke. Signed-off-by: Mikulas Patocka Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/tun.c | 3 +++ include/linux/net.h | 1 + net/socket.c | 3 +++ 3 files changed, 7 insertions(+) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index bb8c72c79c6f..a06ad55d949c 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -358,6 +358,8 @@ static void tun_free_netdev(struct net_device *dev) { struct tun_struct *tun = netdev_priv(dev); + BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED, &tun->socket.flags)); + sk_release_kernel(tun->socket.sk); } @@ -1115,6 +1117,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) tun->flags = flags; tun->txflt.count = 0; tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr); + set_bit(SOCK_EXTERNALLY_ALLOCATED, &tun->socket.flags); err = -ENOMEM; sk = sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL, &tun_proto); diff --git a/include/linux/net.h b/include/linux/net.h index be60c7f5e145..95fea1432dd3 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -72,6 +72,7 @@ struct net; #define SOCK_NOSPACE 2 #define SOCK_PASSCRED 3 #define SOCK_PASSSEC 4 +#define SOCK_EXTERNALLY_ALLOCATED 5 #ifndef ARCH_HAS_SOCKET_TYPES /** diff --git a/net/socket.c b/net/socket.c index 851edcd6b098..573b26152a30 100644 --- a/net/socket.c +++ b/net/socket.c @@ -522,6 +522,9 @@ void sock_release(struct socket *sock) if (rcu_dereference_protected(sock->wq, 1)->fasync_list) printk(KERN_ERR "sock_release: fasync list not empty!\n"); + if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags)) + return; + percpu_sub(sockets_in_use, 1); if (!sock->file) { iput(SOCK_INODE(sock)); -- GitLab From 79746484cab1dede1480580efe9edde68de06770 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 13 May 2012 18:07:04 +0300 Subject: [PATCH 0094/1799] mac80211: fail authentication when AP denied authentication commit dac211ec10d268b9d09000093a9fa2ac1773894f upstream. ieee80211_rx_mgmt_auth() doesn't handle denied authentication properly - it authenticates the station and waits for association (for 5 seconds) instead of failing the authentication. Fix it by destroying auth_data and bailing out instead. Signed-off-by: Eliad Peller Acked-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/mlme.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d132b98bd1c1..25be6831ff09 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1813,7 +1813,8 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, if (status_code != WLAN_STATUS_SUCCESS) { printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n", sdata->name, mgmt->sa, status_code); - goto out; + ieee80211_destroy_auth_data(sdata, false); + return RX_MGMT_CFG80211_RX_AUTH; } switch (ifmgd->auth_data->algorithm) { @@ -1835,7 +1836,6 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, } printk(KERN_DEBUG "%s: authenticated\n", sdata->name); - out: ifmgd->auth_data->done = true; ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; run_again(ifmgd, ifmgd->auth_data->timeout); -- GitLab From a75b6122aacd06507cae1010e0fb6b06fe53336a Mon Sep 17 00:00:00 2001 From: Meenakshi Venkataraman Date: Wed, 16 May 2012 22:40:50 +0200 Subject: [PATCH 0095/1799] iwlwifi: fix debug print in iwl_sta_calc_ht_flags commit a35e270881a5db1ec9ac8bc6d61ebc3e85c14f33 upstream. We missed passing an argument to the debug print. Fix it. Signed-off-by: Meenakshi Venkataraman Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index bef3f242434f..8be535f8f6d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -191,6 +191,7 @@ static void iwl_sta_calc_ht_flags(struct iwl_priv *priv, mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; IWL_DEBUG_INFO(priv, "STA %pM SM PS mode: %s\n", + sta->addr, (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ? "static" : (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ? -- GitLab From 74ec52aa07788b9bce2edd6ce9763c0d79bad38a Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 11 Jul 2012 14:37:28 -0500 Subject: [PATCH 0096/1799] rtlwifi: rtl8192cu: Change buffer allocation for synchronous reads commit 3ce4d85b76010525adedcc2555fa164bf706a2f3 upstream. In commit a7959c1, the USB part of rtlwifi was switched to convert _usb_read_sync() to using a preallocated buffer rather than one that has been acquired using kmalloc. Although this routine is named as though it were synchronous, there seem to be simultaneous users, and the selection of the index to the data buffer is not multi-user safe. This situation is addressed by adding a new spinlock. The routine cannot sleep, thus a mutex is not allowed. Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/usb.c | 14 +++++++++++--- drivers/net/wireless/rtlwifi/wifi.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index a6049d7d51b3..aa970fc18a21 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -131,15 +131,19 @@ static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len) u8 request; u16 wvalue; u16 index; - __le32 *data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; + __le32 *data; + unsigned long flags; + spin_lock_irqsave(&rtlpriv->locks.usb_lock, flags); + if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) + rtlpriv->usb_data_index = 0; + data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; + spin_unlock_irqrestore(&rtlpriv->locks.usb_lock, flags); request = REALTEK_USB_VENQT_CMD_REQ; index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ wvalue = (u16)addr; _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len); - if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) - rtlpriv->usb_data_index = 0; return le32_to_cpu(*data); } @@ -951,6 +955,10 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, GFP_KERNEL); if (!rtlpriv->usb_data) return -ENOMEM; + + /* this spin lock must be initialized early */ + spin_lock_init(&rtlpriv->locks.usb_lock); + rtlpriv->usb_data_index = 0; init_completion(&rtlpriv->firmware_loading_complete); SET_IEEE80211_DEV(hw, &intf->dev); diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 28ebc69218a3..717d3bad17d6 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -1555,6 +1555,7 @@ struct rtl_locks { spinlock_t rf_ps_lock; spinlock_t rf_lock; spinlock_t waitq_lock; + spinlock_t usb_lock; /*Dual mac*/ spinlock_t cck_and_rw_pagea_lock; -- GitLab From ae9bc43cfc53968dd628052d1c225ace8560da64 Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Fri, 13 Jul 2012 12:26:06 -0400 Subject: [PATCH 0097/1799] rtlwifi: rtl8192de: Fix phy-based version calculation commit f1b00f4dab29b57bdf1bc03ef12020b280fd2a72 upstream. Commit d83579e2a50ac68389e6b4c58b845c702cf37516 incorporated some changes from the vendor driver that made it newly important that the calculated hardware version correctly include the CHIP_92D bit, as all of the IS_92D_* macros were changed to depend on it. However, this bit was being unset for dual-mac, dual-phy devices. The vendor driver behavior was modified to not do this, but unfortunately this change was not picked up along with the others. This caused scanning in the 2.4GHz band to be broken, and possibly other bugs as well. This patch brings the version calculation logic in parity with the vendor driver in this regard, and in doing so fixes the regression. However, the version calculation code in general continues to be largely incoherent and messy, and needs to be cleaned up. Signed-off-by: Forest Bond Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/rtl8192de/phy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c index 28fc5fb8057b..46f7917fed5c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c @@ -3344,21 +3344,21 @@ void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw) switch (rtlhal->macphymode) { case DUALMAC_SINGLEPHY: rtlphy->rf_type = RF_2T2R; - rtlhal->version |= CHIP_92D_SINGLEPHY; + rtlhal->version |= RF_TYPE_2T2R; rtlhal->bandset = BAND_ON_BOTH; rtlhal->current_bandtype = BAND_ON_2_4G; break; case SINGLEMAC_SINGLEPHY: rtlphy->rf_type = RF_2T2R; - rtlhal->version |= CHIP_92D_SINGLEPHY; + rtlhal->version |= RF_TYPE_2T2R; rtlhal->bandset = BAND_ON_BOTH; rtlhal->current_bandtype = BAND_ON_2_4G; break; case DUALMAC_DUALPHY: rtlphy->rf_type = RF_1T1R; - rtlhal->version &= (~CHIP_92D_SINGLEPHY); + rtlhal->version &= RF_TYPE_1T1R; /* Now we let MAC0 run on 5G band. */ if (rtlhal->interfaceindex == 0) { rtlhal->bandset = BAND_ON_5G; -- GitLab From 2c3fea5b8591cd8c539bff95108efc2a1f9c5f20 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 11 Jul 2012 18:12:57 -0700 Subject: [PATCH 0098/1799] mwifiex: correction in mcs index check commit fe020120cb863ba918c6d603345342a880272c4d upstream. mwifiex driver supports 2x2 chips as well. Hence valid mcs values are 0 to 15. The check for mcs index is corrected in this patch. For example: if 40MHz is enabled and mcs index is 11, "iw link" command would show "tx bitrate: 108.0 MBit/s" without this patch. Now it shows "tx bitrate: 108.0 MBit/s MCS 11 40Mhz" with the patch. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mwifiex/cfg80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index baf691949c39..03560a8a8588 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -544,9 +544,9 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, /* * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid - * MCS index values for us are 0 to 7. + * MCS index values for us are 0 to 15. */ - if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 8)) { + if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) { sinfo->txrate.mcs = priv->tx_rate; sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; /* 40MHz rate */ -- GitLab From 554c9a0c6f72a8a5c44962b82f495d95e547b4b3 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 13 Jul 2012 15:45:33 +0200 Subject: [PATCH 0099/1799] s390/idle: fix sequence handling vs cpu hotplug commit 0008204ffe85d23382d6fd0f971f3f0fbe70bae2 upstream. The s390 idle accounting code uses a sequence counter which gets used when the per cpu idle statistics get updated and read. One assumption on read access is that only when the sequence counter is even and did not change while reading all values the result is valid. On cpu hotplug however the per cpu data structure gets initialized via a cpu hotplug notifier on CPU_ONLINE. CPU_ONLINE however is too late, since the onlined cpu is already running and might access the per cpu data. Worst case is that the data structure gets initialized while an idle thread is updating its idle statistics. This will result in an uneven sequence counter after an update. As a result user space tools like top, which access /proc/stat in order to get idle stats, will busy loop waiting for the sequence counter to become even again, which will never happen until the queried cpu will update its idle statistics again. And even then the sequence counter will only have an even value for a couple of cpu cycles. Fix this by moving the initialization of the per cpu idle statistics to cpu_init(). I prefer that solution in favor of changing the notifier to CPU_UP_PREPARE, which would be a different solution to the problem. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/kernel/processor.c | 2 ++ arch/s390/kernel/smp.c | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 6e0073e43f54..07c7bf47d618 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -26,12 +26,14 @@ static DEFINE_PER_CPU(struct cpuid, cpu_id); void __cpuinit cpu_init(void) { struct cpuid *id = &per_cpu(cpu_id, smp_processor_id()); + struct s390_idle_data *idle = &__get_cpu_var(s390_idle); get_cpu_id(id); atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; BUG_ON(current->mm); enter_lazy_tlb(&init_mm, current); + memset(idle, 0, sizeof(*idle)); } /* diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 1f77227669e8..c7b8822c561b 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -1034,14 +1034,11 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, unsigned int cpu = (unsigned int)(long)hcpu; struct cpu *c = &pcpu_devices[cpu].cpu; struct device *s = &c->dev; - struct s390_idle_data *idle; int err = 0; switch (action) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: - idle = &per_cpu(s390_idle, cpu); - memset(idle, 0, sizeof(struct s390_idle_data)); err = sysfs_create_group(&s->kobj, &cpu_online_attr_group); break; case CPU_DEAD: -- GitLab From cd1af8b7d386e6b3991252650c16b3e9d5a03b65 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 26 Jul 2012 08:53:06 +0200 Subject: [PATCH 0100/1799] s390/mm: downgrade page table after fork of a 31 bit process commit 0f6f281b731d20bfe75c13f85d33f3f05b440222 upstream. The downgrade of the 4 level page table created by init_new_context is currently done only in start_thread31. If a 31 bit process forks the new mm uses a 4 level page table, including the task size of 2<<42 that goes along with it. This is incorrect as now a 31 bit process can map memory beyond 2GB. Define arch_dup_mmap to do the downgrade after fork. Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/include/asm/mmu_context.h | 14 +++++++++++++- arch/s390/include/asm/processor.h | 2 ++ arch/s390/mm/mmap.c | 12 ++++++++++-- arch/s390/mm/pgtable.c | 5 ----- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index 5d09e405c54d..5d211f70d83d 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h @@ -13,7 +13,6 @@ #include #include #include -#include static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm) @@ -93,4 +92,17 @@ static inline void activate_mm(struct mm_struct *prev, switch_mm(prev, next, current); } +static inline void arch_dup_mmap(struct mm_struct *oldmm, + struct mm_struct *mm) +{ +#ifdef CONFIG_64BIT + if (oldmm->context.asce_limit < mm->context.asce_limit) + crst_table_downgrade(mm, oldmm->context.asce_limit); +#endif +} + +static inline void arch_exit_mmap(struct mm_struct *mm) +{ +} + #endif /* __S390_MMU_CONTEXT_H */ diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index d499b30ea487..8b6f62e1c36b 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -129,7 +129,9 @@ struct stack_frame { regs->psw.mask = psw_user_bits | PSW_MASK_BA; \ regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ regs->gprs[15] = new_stackp; \ + __tlb_flush_mm(current->mm); \ crst_table_downgrade(current->mm, 1UL << 31); \ + update_mm(current->mm, current); \ } while (0) /* Forward declaration, a strange C thing */ diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 2857c48486ea..a64fe53c7202 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -105,9 +105,15 @@ void arch_pick_mmap_layout(struct mm_struct *mm) int s390_mmap_check(unsigned long addr, unsigned long len) { + int rc; + if (!is_compat_task() && - len >= TASK_SIZE && TASK_SIZE < (1UL << 53)) - return crst_table_upgrade(current->mm, 1UL << 53); + len >= TASK_SIZE && TASK_SIZE < (1UL << 53)) { + rc = crst_table_upgrade(current->mm, 1UL << 53); + if (rc) + return rc; + update_mm(current->mm, current); + } return 0; } @@ -127,6 +133,7 @@ s390_get_unmapped_area(struct file *filp, unsigned long addr, rc = crst_table_upgrade(mm, 1UL << 53); if (rc) return (unsigned long) rc; + update_mm(mm, current); area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); } return area; @@ -149,6 +156,7 @@ s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr, rc = crst_table_upgrade(mm, 1UL << 53); if (rc) return (unsigned long) rc; + update_mm(mm, current); area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags); } diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 6e765bf00670..87f0efd0e77c 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -85,7 +85,6 @@ int crst_table_upgrade(struct mm_struct *mm, unsigned long limit) crst_table_free(mm, table); if (mm->context.asce_limit < limit) goto repeat; - update_mm(mm, current); return 0; } @@ -93,9 +92,6 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit) { pgd_t *pgd; - if (mm->context.asce_limit <= limit) - return; - __tlb_flush_mm(mm); while (mm->context.asce_limit > limit) { pgd = mm->pgd; switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) { @@ -118,7 +114,6 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit) mm->task_size = mm->context.asce_limit; crst_table_free(mm, (unsigned long *) pgd); } - update_mm(mm, current); } #endif -- GitLab From 351bb0ecc5b0b9dc60d07a44078fa16971c7f3e7 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 27 Jul 2012 09:45:39 +0200 Subject: [PATCH 0101/1799] s390/mm: fix fault handling for page table walk case commit 008c2e8f247f0a8db1e8e26139da12f3a3abcda0 upstream. Make sure the kernel does not incorrectly create a SIGBUS signal during user space accesses: For user space accesses in the switched addressing mode case the kernel may walk page tables and access user address space via the kernel mapping. If a page table entry is invalid the function __handle_fault() gets called in order to emulate a page fault and trigger all the usual actions like paging in a missing page etc. by calling handle_mm_fault(). If handle_mm_fault() returns with an error fixup handling is necessary. For the switched addressing mode case all errors need to be mapped to -EFAULT, so that the calling uaccess function can return -EFAULT to user space. Unfortunately the __handle_fault() incorrectly calls do_sigbus() if VM_FAULT_SIGBUS is set. This however should only happen if a page fault was triggered by a user space instruction. For kernel mode uaccesses the correct action is to only return -EFAULT. So user space may incorrectly see SIGBUS signals because of this bug. For current machines this would only be possible for the switched addressing mode case in conjunction with futex operations. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/mm/fault.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 4e66860029f3..f2b11ee3fb3a 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -443,6 +443,7 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write) struct pt_regs regs; int access, fault; + /* Emulate a uaccess fault from kernel mode. */ regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK; if (!irqs_disabled()) regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT; @@ -452,12 +453,12 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write) regs.int_parm_long = (uaddr & PAGE_MASK) | 2; access = write ? VM_WRITE : VM_READ; fault = do_exception(®s, access); - if (unlikely(fault)) { - if (fault & VM_FAULT_OOM) - return -EFAULT; - else if (fault & VM_FAULT_SIGBUS) - do_sigbus(®s); - } + /* + * Since the fault happened in kernel mode while performing a uaccess + * all we need to do now is emulating a fixup in case "fault" is not + * zero. + * For the calling uaccess functions this results always in -EFAULT. + */ return fault ? -EFAULT : 0; } -- GitLab From e6c1b59aaa759ae5374dedf8508ee14aff2f967f Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 19 Jul 2012 10:56:10 +0200 Subject: [PATCH 0102/1799] iommu/amd: Add missing spin_lock initialization commit 2c13d47a1a7ee8808796016c617aef25fd1d1925 upstream. Add missing spin_lock initialization in amd_iommu_bind_pasid() function and make lockdep happy again. Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/amd_iommu_v2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index 036fe9bf157e..a1f1bc876043 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c @@ -681,6 +681,8 @@ int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid, atomic_set(&pasid_state->count, 1); init_waitqueue_head(&pasid_state->wq); + spin_lock_init(&pasid_state->lock); + pasid_state->task = task; pasid_state->mm = get_task_mm(task); pasid_state->device_state = dev_state; -- GitLab From 06e619c5073d1830f58039cd97e95ae184cf7bbb Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 19 Jul 2012 13:42:54 +0200 Subject: [PATCH 0103/1799] iommu/amd: Fix hotplug with iommu=pt commit 2c9195e990297068d0f1f1bd8e2f1d09538009da upstream. This did not work because devices are not put into the pt_domain. Fix this. Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/amd_iommu.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index dfe7d37c82c5..57ed244cf990 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -2254,6 +2254,18 @@ static int device_change_notifier(struct notifier_block *nb, iommu_init_device(dev); + /* + * dev_data is still NULL and + * got initialized in iommu_init_device + */ + dev_data = get_dev_data(dev); + + if (iommu_pass_through || dev_data->iommu_v2) { + dev_data->passthrough = true; + attach_device(dev, pt_domain); + break; + } + domain = domain_for_device(dev); /* allocate a protection domain if a device is added */ @@ -2271,10 +2283,7 @@ static int device_change_notifier(struct notifier_block *nb, dev_data = get_dev_data(dev); - if (!dev_data->passthrough) - dev->archdata.dma_ops = &amd_iommu_dma_ops; - else - dev->archdata.dma_ops = &nommu_dma_ops; + dev->archdata.dma_ops = &amd_iommu_dma_ops; break; case BUS_NOTIFY_DEL_DEVICE: -- GitLab From 664634f8a03e721a7fffb5f1e21cbdd806598cda Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 10 Jul 2012 17:58:04 +0200 Subject: [PATCH 0104/1799] udf: Improve table length check to avoid possible overflow commit 57b9655d01ef057a523e810d29c37ac09b80eead upstream. When a partition table length is corrupted to be close to 1 << 32, the check for its length may overflow on 32-bit systems and we will think the length is valid. Later on the kernel can crash trying to read beyond end of buffer. Fix the check to avoid possible overflow. Reported-by: Ben Hutchings Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/udf/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/udf/super.c b/fs/udf/super.c index 8d86a8706c0e..e660ffdd91b6 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1283,7 +1283,7 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, BUG_ON(ident != TAG_IDENT_LVD); lvd = (struct logicalVolDesc *)bh->b_data; table_len = le32_to_cpu(lvd->mapTableLength); - if (sizeof(*lvd) + table_len > sb->s_blocksize) { + if (table_len > sb->s_blocksize - sizeof(*lvd)) { udf_err(sb, "error loading logical volume descriptor: " "Partition table too long (%u > %lu)\n", table_len, sb->s_blocksize - sizeof(*lvd)); -- GitLab From 02f5c5d768faf0417b6801a1bfebc866a6db7878 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 5 Jun 2012 11:15:50 -0400 Subject: [PATCH 0105/1799] stable: update references to older 2.6 versions for 3.x commit 2584f5212d97b664be250ad5700a2d0fee31a10d upstream. Also add information on where the respective trees are. Signed-off-by: Paul Gortmaker Acked-by: Rob Landley Signed-off-by: Greg Kroah-Hartman --- Documentation/stable_kernel_rules.txt | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt index 4a7b54bd37e8..b0714d8f678a 100644 --- a/Documentation/stable_kernel_rules.txt +++ b/Documentation/stable_kernel_rules.txt @@ -1,4 +1,4 @@ -Everything you ever wanted to know about Linux 2.6 -stable releases. +Everything you ever wanted to know about Linux -stable releases. Rules on what kind of patches are accepted, and which ones are not, into the "-stable" tree: @@ -42,10 +42,10 @@ Procedure for submitting patches to the -stable tree: cherry-picked than this can be specified in the following format in the sign-off area: - Cc: # .32.x: a1f84a3: sched: Check for idle - Cc: # .32.x: 1b9508f: sched: Rate-limit newidle - Cc: # .32.x: fd21073: sched: Fix affinity logic - Cc: # .32.x + Cc: # 3.3.x: a1f84a3: sched: Check for idle + Cc: # 3.3.x: 1b9508f: sched: Rate-limit newidle + Cc: # 3.3.x: fd21073: sched: Fix affinity logic + Cc: # 3.3.x Signed-off-by: Ingo Molnar The tag sequence has the meaning of: @@ -79,6 +79,15 @@ Review cycle: security kernel team, and not go through the normal review cycle. Contact the kernel security team for more details on this procedure. +Trees: + + - The queues of patches, for both completed versions and in progress + versions can be found at: + http://git.kernel.org/?p=linux/kernel/git/stable/stable-queue.git + - The finalized and tagged releases of all stable kernels can be found + in separate branches per version at: + http://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git + Review committee: -- GitLab From c7815406caf7efdd805e893caef4a63e61b7645e Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 20 Jun 2012 02:31:11 +0100 Subject: [PATCH 0106/1799] staging: zsmalloc: Finish conversion to a separate module commit 069f101fa463351f528773d73b74e9b606b3f66a upstream. ZSMALLOC is tristate, but the code has no MODULE_LICENSE and since it depends on GPL-only symbols it cannot be loaded as a module. This in turn breaks zram which now depends on it. I assume it's meant to be Dual BSD/GPL like the other z-stuff. There is also no module_exit, which will make it impossible to unload. Add the appropriate module_init and module_exit declarations suggested by comments. Reported-by: Christian Ohm References: http://bugs.debian.org/677273 Signed-off-by: Ben Hutchings Reviewed-by: Jonathan Nieder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zsmalloc/zsmalloc-main.c | 33 +++++------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index 917461c66014..175b3c94d5a7 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -426,12 +426,6 @@ static struct page *find_get_zspage(struct size_class *class) } -/* - * If this becomes a separate module, register zs_init() with - * module_init(), zs_exit with module_exit(), and remove zs_initialized -*/ -static int zs_initialized; - static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action, void *pcpu) { @@ -490,7 +484,7 @@ static int zs_init(void) struct zs_pool *zs_create_pool(const char *name, gfp_t flags) { - int i, error, ovhd_size; + int i, ovhd_size; struct zs_pool *pool; if (!name) @@ -517,28 +511,9 @@ struct zs_pool *zs_create_pool(const char *name, gfp_t flags) } - /* - * If this becomes a separate module, register zs_init with - * module_init, and remove this block - */ - if (!zs_initialized) { - error = zs_init(); - if (error) - goto cleanup; - zs_initialized = 1; - } - pool->flags = flags; pool->name = name; - error = 0; /* Success */ - -cleanup: - if (error) { - zs_destroy_pool(pool); - pool = NULL; - } - return pool; } EXPORT_SYMBOL_GPL(zs_create_pool); @@ -749,3 +724,9 @@ u64 zs_get_total_size_bytes(struct zs_pool *pool) return npages << PAGE_SHIFT; } EXPORT_SYMBOL_GPL(zs_get_total_size_bytes); + +module_init(zs_init); +module_exit(zs_exit); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Nitin Gupta "); -- GitLab From d3b42543cf269243ccf2add49008db879ff7f146 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 17 Jul 2012 12:39:26 -0700 Subject: [PATCH 0107/1799] workqueue: perform cpu down operations from low priority cpu_notifier() commit 6575820221f7a4dd6eadecf7bf83cdd154335eda upstream. Currently, all workqueue cpu hotplug operations run off CPU_PRI_WORKQUEUE which is higher than normal notifiers. This is to ensure that workqueue is up and running while bringing up a CPU before other notifiers try to use workqueue on the CPU. Per-cpu workqueues are supposed to remain working and bound to the CPU for normal CPU_DOWN_PREPARE notifiers. This holds mostly true even with workqueue offlining running with higher priority because workqueue CPU_DOWN_PREPARE only creates a bound trustee thread which runs the per-cpu workqueue without concurrency management without explicitly detaching the existing workers. However, if the trustee needs to create new workers, it creates unbound workers which may wander off to other CPUs while CPU_DOWN_PREPARE notifiers are in progress. Furthermore, if the CPU down is cancelled, the per-CPU workqueue may end up with workers which aren't bound to the CPU. While reliably reproducible with a convoluted artificial test-case involving scheduling and flushing CPU burning work items from CPU down notifiers, this isn't very likely to happen in the wild, and, even when it happens, the effects are likely to be hidden by the following successful CPU down. Fix it by using different priorities for up and down notifiers - high priority for up operations and low priority for down operations. Workqueue cpu hotplug operations will soon go through further cleanup. Signed-off-by: Tejun Heo Acked-by: "Rafael J. Wysocki" Signed-off-by: Greg Kroah-Hartman --- include/linux/cpu.h | 5 +++-- kernel/workqueue.c | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/include/linux/cpu.h b/include/linux/cpu.h index ee28844ae68e..78ed62f3dde4 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -75,8 +75,9 @@ enum { /* migration should happen before other stuff but after perf */ CPU_PRI_PERF = 20, CPU_PRI_MIGRATION = 10, - /* prepare workqueues for other notifiers */ - CPU_PRI_WORKQUEUE = 5, + /* bring up workqueues before normal notifiers and down after */ + CPU_PRI_WORKQUEUE_UP = 5, + CPU_PRI_WORKQUEUE_DOWN = -5, }; #define CPU_ONLINE 0x0002 /* CPU (unsigned)v is up */ diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 7da267c8d0d5..bfe3f8a1fc33 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3582,6 +3582,41 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, return notifier_from_errno(0); } +/* + * Workqueues should be brought up before normal priority CPU notifiers. + * This will be registered high priority CPU notifier. + */ +static int __devinit workqueue_cpu_up_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_UP_PREPARE: + case CPU_UP_CANCELED: + case CPU_DOWN_FAILED: + case CPU_ONLINE: + return workqueue_cpu_callback(nfb, action, hcpu); + } + return NOTIFY_OK; +} + +/* + * Workqueues should be brought down after normal priority CPU notifiers. + * This will be registered as low priority CPU notifier. + */ +static int __devinit workqueue_cpu_down_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_DOWN_PREPARE: + case CPU_DYING: + case CPU_POST_DEAD: + return workqueue_cpu_callback(nfb, action, hcpu); + } + return NOTIFY_OK; +} + #ifdef CONFIG_SMP struct work_for_cpu { @@ -3775,7 +3810,8 @@ static int __init init_workqueues(void) unsigned int cpu; int i; - cpu_notifier(workqueue_cpu_callback, CPU_PRI_WORKQUEUE); + cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP); + cpu_notifier(workqueue_cpu_down_callback, CPU_PRI_WORKQUEUE_DOWN); /* initialize gcwqs */ for_each_gcwq_cpu(cpu) { -- GitLab From 8ebdf76ba264031c60e8dc720775833e0ab6512d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 12 Jun 2012 10:43:28 +0200 Subject: [PATCH 0108/1799] ACPI, APEI: Fixup common access width firmware bug commit f712c71f7b2b43b894d1e92e1b77385fcad8815f upstream. Many firmwares have a common register definition bug where 8-bit access width is specified for a 32-bit register. Ideally this should be fixed in the BIOS, but earlier versions of the kernel did not complain, so fix that up silently. This closes kernel bug #43282: https://bugzilla.kernel.org/show_bug.cgi?id=43282 Signed-off-by: Jean Delvare Acked-by: Huang Ying Acked-by: Gary Hade Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/apei/apei-base.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 6686b1eaf13e..00a783661d0b 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -586,6 +586,11 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr, } *access_bit_width = 1UL << (access_size_code + 2); + /* Fixup common BIOS bug */ + if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 && + *access_bit_width < 32) + *access_bit_width = 32; + if ((bit_width + bit_offset) > *access_bit_width) { pr_warning(FW_BUG APEI_PFX "Invalid bit width + offset in GAR [0x%llx/%u/%u/%u/%u]\n", -- GitLab From c1542109ac67110d3072fabb23e4604be0ff7554 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 20 Jul 2012 13:29:16 +0800 Subject: [PATCH 0109/1799] ACPI/AC: prevent OOPS on some boxes due to missing check power_supply_register() return value check commit f197ac13f6eeb351b31250b9ab7d0da17434ea36 upstream. In the ac.c, power_supply_register()'s return value is not checked. As a result, the driver's add() ops may return success even though the device failed to initialize. For example, some BIOS may describe two ACADs in the same DSDT. The second ACAD device will fail to register, but ACPI driver's add() ops returns sucessfully. The ACPI device will receive ACPI notification and cause OOPS. https://bugzilla.redhat.com/show_bug.cgi?id=772730 Signed-off-by: Lan Tianyu Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/ac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 6512b20aeccd..d1fcbc0f6cbc 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -292,7 +292,9 @@ static int acpi_ac_add(struct acpi_device *device) ac->charger.properties = ac_props; ac->charger.num_properties = ARRAY_SIZE(ac_props); ac->charger.get_property = get_ac_property; - power_supply_register(&ac->device->dev, &ac->charger); + result = power_supply_register(&ac->device->dev, &ac->charger); + if (result) + goto end; printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), acpi_device_bid(device), -- GitLab From d458a00f17bd1c883eaf0192e1cc33a2ae530750 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Wed, 25 Jul 2012 15:57:13 -0400 Subject: [PATCH 0110/1799] Btrfs: call the ordered free operation without any locks held commit e9fbcb42201c862fd6ab45c48ead4f47bb2dea9d upstream. Each ordered operation has a free callback, and this was called with the worker spinlock held. Josef made the free callback also call iput, which we can't do with the spinlock. This drops the spinlock for the free operation and grabs it again before moving through the rest of the list. We'll circle back around to this and find a cleaner way that doesn't bounce the lock around so much. Signed-off-by: Chris Mason Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/async-thread.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index 42704149b723..58b7d14b08ee 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c @@ -206,10 +206,17 @@ static noinline void run_ordered_completions(struct btrfs_workers *workers, work->ordered_func(work); - /* now take the lock again and call the freeing code */ + /* now take the lock again and drop our item from the list */ spin_lock(&workers->order_lock); list_del(&work->order_list); + spin_unlock(&workers->order_lock); + + /* + * we don't want to call the ordered free functions + * with the lock held though + */ work->ordered_free(work); + spin_lock(&workers->order_lock); } spin_unlock(&workers->order_lock); -- GitLab From da49dbd95a28bd166f8935f53ed76d406cd891ca Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 23 Jul 2012 20:34:17 -0400 Subject: [PATCH 0111/1799] cifs: reinstate sec=ntlmv2 mount option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7659624ffb550d69c87f9af9ae63e717daa874bd upstream. sec=ntlmv2 as a mount option got dropped in the mount option overhaul. Cc: Sachin Prabhu Reported-by: Günter Kukkukk Signed-off-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/connect.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 87ce8af1ce40..65a78e9a5d40 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -238,8 +238,8 @@ static const match_table_t cifs_mount_option_tokens = { enum { Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p, Opt_sec_ntlmsspi, Opt_sec_ntlmssp, - Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2i, - Opt_sec_nontlm, Opt_sec_lanman, + Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2, + Opt_sec_ntlmv2i, Opt_sec_lanman, Opt_sec_none, Opt_sec_err @@ -253,8 +253,9 @@ static const match_table_t cifs_secflavor_tokens = { { Opt_sec_ntlmssp, "ntlmssp" }, { Opt_ntlm, "ntlm" }, { Opt_sec_ntlmi, "ntlmi" }, + { Opt_sec_ntlmv2, "nontlm" }, + { Opt_sec_ntlmv2, "ntlmv2" }, { Opt_sec_ntlmv2i, "ntlmv2i" }, - { Opt_sec_nontlm, "nontlm" }, { Opt_sec_lanman, "lanman" }, { Opt_sec_none, "none" }, @@ -1163,7 +1164,7 @@ static int cifs_parse_security_flavors(char *value, case Opt_sec_ntlmi: vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN; break; - case Opt_sec_nontlm: + case Opt_sec_ntlmv2: vol->secFlg |= CIFSSEC_MAY_NTLMV2; break; case Opt_sec_ntlmv2i: -- GitLab From 7e7a57b3ea066e3caf149feb37c6487d8423c772 Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Tue, 12 Jun 2012 15:10:58 +0200 Subject: [PATCH 0112/1799] spi/pl022: disable port when unused commit fd316941cfee1fbd12746afea83720fb7823888a upstream. Commit ffbbdd21329f3e15eeca6df2d4bc11c04d9d91c0 "spi: create a message queueing infrastructure" Accidentally deleted the logic to disable the port when unused leading to higher power consumption. Fix this up. Cc: Vinit Shenoy Signed-off-by: Virupax Sadashivpetimath Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/spi/spi-pl022.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 400ae2121a2a..469eb28e8328 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -489,6 +489,11 @@ static void giveback(struct pl022 *pl022) pl022->cur_transfer = NULL; pl022->cur_chip = NULL; spi_finalize_current_message(pl022->master); + + /* disable the SPI/SSP operation */ + writew((readw(SSP_CR1(pl022->virtbase)) & + (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); + } /** -- GitLab From bfc41a820b085dff6048aab510a4dcb48b570d3b Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Tue, 24 Jul 2012 22:34:29 +0000 Subject: [PATCH 0113/1799] qeth: repair crash in qeth_l3_vlan_rx_kill_vid() commit eabfbe6230ee7363681e7a561948d362b87169f0 upstream. Commit efc73f4b "net: Fix memory leak - vlan_info struct" adds deletion of VLAN 0 for devices with feature NETIF_F_HW_VLAN_FILTER. For driver qeth these are the layer 3 devices. Usually there exists no separate vlan net_device for VLAN 0. Thus the qeth functions qeth_l3_free_vlan_addresses4() and qeth_l3_free_vlan_addresses6() require an extra checking if function __vlan_find_dev_deep() returns with a net_device. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/s390/net/qeth_l3_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index f85921607686..951b6cf086af 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1818,6 +1818,8 @@ static void qeth_l3_free_vlan_addresses4(struct qeth_card *card, QETH_CARD_TEXT(card, 4, "frvaddr4"); netdev = __vlan_find_dev_deep(card->dev, vid); + if (!netdev) + return; in_dev = in_dev_get(netdev); if (!in_dev) return; @@ -1846,6 +1848,8 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card, QETH_CARD_TEXT(card, 4, "frvaddr6"); netdev = __vlan_find_dev_deep(card->dev, vid); + if (!netdev) + return; in6_dev = in6_dev_get(netdev); if (!in6_dev) return; -- GitLab From e49e6d039117405be1c4de6ac9cce196f9aea22e Mon Sep 17 00:00:00 2001 From: Greg KH Date: Thu, 12 Jul 2012 15:39:44 +0000 Subject: [PATCH 0114/1799] tg3: add device id of Apple Thunderbolt Ethernet device commit 02eca3f5f5e458c3a5d7b772bc8042ee2a4ebedf upstream. The Apple Thunderbolt ethernet device is already listed in the driver, but not hooked up in the MODULE_DEVICE_TABLE(). This fixes that and allows it to work properly. Signed-off-by: Greg Kroah-Hartman Acked-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 1a1b29ff8143..00d52acb73e6 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -298,6 +298,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)}, -- GitLab From 4593e510277fec9fbe8708b1276301ead59470f0 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 29 Jul 2012 19:15:42 +0000 Subject: [PATCH 0115/1799] tg3: Fix Read DMA workaround for 5719 A0. commit 10ce95d6ef36c65df7dcd3b8fcf86913f8b298bd upstream. The workaround was mis-applied to all 5719 and 5720 chips. Signed-off-by: Michael Chan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/broadcom/tg3.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 00d52acb73e6..8506c54ee163 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -8949,8 +8949,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || tg3_flag(tp, 57765_PLUS)) { val = tr32(TG3_RDMA_RSRVCTRL_REG); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { + if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0) { val &= ~(TG3_RDMA_RSRVCTRL_TXMRGN_MASK | TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK | TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK); -- GitLab From cbb9e89c375e167d012058c82fa69dd17ec17d4c Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 29 Jul 2012 19:15:44 +0000 Subject: [PATCH 0116/1799] tg3: Fix race condition in tg3_get_stats64() commit 0f566b208b41918053b2e67399673aaec02dde5d upstream. Spinlock should be taken before checking for tp->hw_stats. Signed-off-by: Michael Chan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/broadcom/tg3.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 8506c54ee163..689d2a1935bd 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -12255,10 +12255,12 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, { struct tg3 *tp = netdev_priv(dev); - if (!tp->hw_stats) + spin_lock_bh(&tp->lock); + if (!tp->hw_stats) { + spin_unlock_bh(&tp->lock); return &tp->net_stats_prev; + } - spin_lock_bh(&tp->lock); tg3_get_nstats(tp, stats); spin_unlock_bh(&tp->lock); -- GitLab From 5d11fb27d2f819d61df7e6dc36eb27374a92abe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 3 Jul 2012 14:05:41 +0200 Subject: [PATCH 0117/1799] drm/radeon: fix fence related segfault in CS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 93bf888c5c730605e3470f5d2381f296eda88d79 upstream. Don't return success if scheduling the IB fails, otherwise we end up with an oops in ttm_eu_fence_buffer_objects. Signed-off-by: Christian König Reviewed-by: Jerome Glisse Reviewed-by: Michel Dänzer Reviewed-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 2418cf6da1c1..cf723c4297a9 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -377,7 +377,7 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev, if (r) { DRM_ERROR("Failed to schedule IB !\n"); } - return 0; + return r; } static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser, -- GitLab From 47be757968b4344dd3e46f4e62c842cc201e830d Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 12 Jul 2012 18:23:05 -0400 Subject: [PATCH 0118/1799] drm/radeon: fix bo creation retry path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d1c7871ddb1f588b8eb35affd9ee1a3d5e11cd0c upstream. Retry label was at wrong place in function leading to memory leak. Signed-off-by: Jerome Glisse Reviewed-by: Michel Dänzer Reviewed-by: Christian König Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_object.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index df6a4dbd93f8..80c6e8bad656 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -136,7 +136,6 @@ int radeon_bo_create(struct radeon_device *rdev, acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, sizeof(struct radeon_bo)); -retry: bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; @@ -150,6 +149,8 @@ int radeon_bo_create(struct radeon_device *rdev, bo->surface_reg = -1; INIT_LIST_HEAD(&bo->list); INIT_LIST_HEAD(&bo->va); + +retry: radeon_ttm_placement_from_domain(bo, domain); /* Kernel allocation are uninterruptible */ mutex_lock(&rdev->vram_mutex); -- GitLab From bec6d04dc715ad9fbc0d86abb3eea125109cf98f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 17 Jul 2012 19:02:09 +0200 Subject: [PATCH 0119/1799] drm/radeon: Try harder to avoid HW cursor ending on a multiple of 128 columns. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f60ec4c7df043df81e62891ac45383d012afe0da upstream. This could previously fail if either of the enabled displays was using a horizontal resolution that is a multiple of 128, and only the leftmost column of the cursor was (supposed to be) visible at the right edge of that display. The solution is to move the cursor one pixel to the left in that case. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=33183 Signed-off-by: Michel Dänzer Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_cursor.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 42acc6449dd6..711e95ad39bf 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -262,8 +262,14 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, if (!(cursor_end & 0x7f)) w--; } - if (w <= 0) + if (w <= 0) { w = 1; + cursor_end = x - xorigin + w; + if (!(cursor_end & 0x7f)) { + x--; + WARN_ON_ONCE(x < 0); + } + } } } -- GitLab From 108c49a5cd65e2edc904212e6bd365db8d2f29e8 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Tue, 17 Jul 2012 17:17:16 -0400 Subject: [PATCH 0120/1799] drm/radeon: fix non revealent error message commit 8d1c702aa0b2c4b22b0742b72a1149d91690674b upstream. We want to print link status query failed only if it's an unexepected fail. If we query to see if we need link training it might be because there is nothing connected and thus link status query have the right to fail in that case. To avoid printing failure when it's expected, move the failure message to proper place. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_dp.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index c57d85664e77..886b41f44a55 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -22,6 +22,7 @@ * * Authors: Dave Airlie * Alex Deucher + * Jerome Glisse */ #include "drmP.h" #include "radeon_drm.h" @@ -637,7 +638,6 @@ static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector, ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, link_status, DP_LINK_STATUS_SIZE, 100); if (ret <= 0) { - DRM_ERROR("displayport link status failed\n"); return false; } @@ -816,8 +816,10 @@ static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info) else mdelay(dp_info->rd_interval * 4); - if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) + if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { + DRM_ERROR("displayport link status failed\n"); break; + } if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { clock_recovery = true; @@ -879,8 +881,10 @@ static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info) else mdelay(dp_info->rd_interval * 4); - if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) + if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { + DRM_ERROR("displayport link status failed\n"); break; + } if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { channel_eq = true; -- GitLab From b7ea4b8363e16630219674b9b8178dc07e7e6022 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 19 Jul 2012 17:15:56 -0400 Subject: [PATCH 0121/1799] drm/radeon: fix hotplug of DP to DVI|HDMI passive adapters (v2) commit 266dcba541a1ef7e5d82d9e67c67fde2910636e8 upstream. No need to retrain the link for passive adapters. v2: agd5f - no passive DP to VGA adapters, update comments - assign radeon_connector_atom_dig after we are sure we have a digital connector as analog connectors have different private data. - get new sink type before checking for retrain. No need to check if it's no longer a DP connection. Signed-off-by: Jerome Glisse Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_connectors.c | 29 ++++++++++++++++------ 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 3c2e7a000a2a..e4e3e4c9b4b2 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -64,14 +64,27 @@ void radeon_connector_hotplug(struct drm_connector *connector) /* just deal with DP (not eDP) here. */ if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { - int saved_dpms = connector->dpms; - - /* Only turn off the display it it's physically disconnected */ - if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); - else if (radeon_dp_needs_link_train(radeon_connector)) - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); - connector->dpms = saved_dpms; + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; + + /* if existing sink type was not DP no need to retrain */ + if (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT) + return; + + /* first get sink type as it may be reset after (un)plug */ + dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); + /* don't do anything if sink is not display port, i.e., + * passive dp->(dvi|hdmi) adaptor + */ + if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { + int saved_dpms = connector->dpms; + /* Only turn off the display if it's physically disconnected */ + if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + else if (radeon_dp_needs_link_train(radeon_connector)) + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + connector->dpms = saved_dpms; + } } } -- GitLab From de5b1c0849465404f94ffc0574e9ec9e8dc97570 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 19 Jul 2012 17:25:55 -0400 Subject: [PATCH 0122/1799] drm/radeon: on hotplug force link training to happen (v2) commit ca2ccde5e2f24a792caa4cca919fc5c6f65d1887 upstream. To have DP behave like VGA/DVI we need to retrain the link on hotplug. For this to happen we need to force link training to happen by setting connector dpms to off before asking it turning it on again. v2: agd5f - drop the dp_get_link_status() change in atombios_dp.c for now. We still need the dpms OFF change. Signed-off-by: Jerome Glisse Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_connectors.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index e4e3e4c9b4b2..3fb7ca922069 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -79,10 +79,16 @@ void radeon_connector_hotplug(struct drm_connector *connector) if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { int saved_dpms = connector->dpms; /* Only turn off the display if it's physically disconnected */ - if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) + if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); - else if (radeon_dp_needs_link_train(radeon_connector)) + } else if (radeon_dp_needs_link_train(radeon_connector)) { + /* set it to OFF so that drm_helper_connector_dpms() + * won't return immediately since the current state + * is ON at this point. + */ + connector->dpms = DRM_MODE_DPMS_OFF; drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + } connector->dpms = saved_dpms; } } -- GitLab From b6e9ffcdb09fbf28665e025aa31fda702689786c Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Tue, 24 Jul 2012 17:06:11 -0400 Subject: [PATCH 0123/1799] drm/radeon: fix dpms on/off on trinity/aruba v2 commit fcedac670c3da0d17aaa5db1708694971e8024a9 upstream. The external encoder need to be setup again before enabling the transmiter. This seems to be only needed on some trinity/aruba to fix dpms on. v2: Add comment, only setup again on dce6 ie aruba or newer. Signed-off-by: Jerome Glisse Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_encoders.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 2d39f9977e00..a3ae788a2af2 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1392,10 +1392,18 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_ON: /* some early dce3.2 boards have a bug in their transmitter control table */ if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) || - ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) + ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + if (ASIC_IS_DCE6(rdev)) { + /* It seems we need to call ATOM_ENCODER_CMD_SETUP again + * before reenabling encoder on DPMS ON, otherwise we never + * get picture + */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + } atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - else + } else { atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); + } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { atombios_set_edp_panel_power(connector, -- GitLab From 27cd8f51344dcf4799c7a092c1797402b833126a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 25 Jul 2012 10:40:34 -0400 Subject: [PATCH 0124/1799] posix_types.h: Cleanup stale __NFDBITS and related definitions commit 8ded2bbc1845e19c771eb55209aab166ef011243 upstream. Recently, glibc made a change to suppress sign-conversion warnings in FD_SET (glibc commit ceb9e56b3d1). This uncovered an issue with the kernel's definition of __NFDBITS if applications #include after including . A build failure would be seen when passing the -Werror=sign-compare and -D_FORTIFY_SOURCE=2 flags to gcc. It was suggested that the kernel should either match the glibc definition of __NFDBITS or remove that entirely. The current in-kernel uses of __NFDBITS can be replaced with BITS_PER_LONG, and there are no uses of the related __FDELT and __FDMASK defines. Given that, we'll continue the cleanup that was started with commit 8b3d1cda4f5f ("posix_types: Remove fd_set macros") and drop the remaining unused macros. Additionally, linux/time.h has similar macros defined that expand to nothing so we'll remove those at the same time. Reported-by: Jeff Law Suggested-by: Linus Torvalds Signed-off-by: Josh Boyer [ .. and fix up whitespace as per akpm ] Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/mips/kernel/kspd.c | 2 +- fs/exec.c | 2 +- fs/select.c | 10 +++++----- include/linux/posix_types.h | 18 +++--------------- include/linux/time.h | 8 -------- kernel/exit.c | 2 +- security/selinux/hooks.c | 2 +- 7 files changed, 12 insertions(+), 32 deletions(-) diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c index 84d0639e4580..b77f56bbb477 100644 --- a/arch/mips/kernel/kspd.c +++ b/arch/mips/kernel/kspd.c @@ -323,7 +323,7 @@ static void sp_cleanup(void) fdt = files_fdtable(files); for (;;) { unsigned long set; - i = j * __NFDBITS; + i = j * BITS_PER_LONG; if (i >= fdt->max_fds) break; set = fdt->open_fds[j++]; diff --git a/fs/exec.c b/fs/exec.c index 29e5f840544f..126e01cb2434 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1024,7 +1024,7 @@ static void flush_old_files(struct files_struct * files) unsigned long set, i; j++; - i = j * __NFDBITS; + i = j * BITS_PER_LONG; fdt = files_fdtable(files); if (i >= fdt->max_fds) break; diff --git a/fs/select.c b/fs/select.c index 17d33d09fc16..0baa0a351a1c 100644 --- a/fs/select.c +++ b/fs/select.c @@ -345,8 +345,8 @@ static int max_select_fd(unsigned long n, fd_set_bits *fds) struct fdtable *fdt; /* handle last in-complete long-word first */ - set = ~(~0UL << (n & (__NFDBITS-1))); - n /= __NFDBITS; + set = ~(~0UL << (n & (BITS_PER_LONG-1))); + n /= BITS_PER_LONG; fdt = files_fdtable(current->files); open_fds = fdt->open_fds + n; max = 0; @@ -373,7 +373,7 @@ static int max_select_fd(unsigned long n, fd_set_bits *fds) max++; set >>= 1; } while (set); - max += n * __NFDBITS; + max += n * BITS_PER_LONG; } return max; @@ -435,11 +435,11 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) in = *inp++; out = *outp++; ex = *exp++; all_bits = in | out | ex; if (all_bits == 0) { - i += __NFDBITS; + i += BITS_PER_LONG; continue; } - for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) { + for (j = 0; j < BITS_PER_LONG; ++j, ++i, bit <<= 1) { int fput_needed; if (i >= n) break; diff --git a/include/linux/posix_types.h b/include/linux/posix_types.h index f04c98cf44f3..988f76e636e3 100644 --- a/include/linux/posix_types.h +++ b/include/linux/posix_types.h @@ -15,26 +15,14 @@ */ /* - * Those macros may have been defined in . But we always - * use the ones here. + * This macro may have been defined in . But we always + * use the one here. */ -#undef __NFDBITS -#define __NFDBITS (8 * sizeof(unsigned long)) - #undef __FD_SETSIZE #define __FD_SETSIZE 1024 -#undef __FDSET_LONGS -#define __FDSET_LONGS (__FD_SETSIZE/__NFDBITS) - -#undef __FDELT -#define __FDELT(d) ((d) / __NFDBITS) - -#undef __FDMASK -#define __FDMASK(d) (1UL << ((d) % __NFDBITS)) - typedef struct { - unsigned long fds_bits [__FDSET_LONGS]; + unsigned long fds_bits[__FD_SETSIZE / (8 * sizeof(long))]; } __kernel_fd_set; /* Type of a signal handler. */ diff --git a/include/linux/time.h b/include/linux/time.h index 33a92ead4d88..8da51299a7d5 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -258,14 +258,6 @@ static __always_inline void timespec_add_ns(struct timespec *a, u64 ns) #endif /* __KERNEL__ */ -#define NFDBITS __NFDBITS - -#define FD_SETSIZE __FD_SETSIZE -#define FD_SET(fd,fdsetp) __FD_SET(fd,fdsetp) -#define FD_CLR(fd,fdsetp) __FD_CLR(fd,fdsetp) -#define FD_ISSET(fd,fdsetp) __FD_ISSET(fd,fdsetp) -#define FD_ZERO(fdsetp) __FD_ZERO(fdsetp) - /* * Names of the interval timers, and structure * defining a timer setting: diff --git a/kernel/exit.c b/kernel/exit.c index 9d81012290e3..bfbd85669694 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -471,7 +471,7 @@ static void close_files(struct files_struct * files) rcu_read_unlock(); for (;;) { unsigned long set; - i = j * __NFDBITS; + i = j * BITS_PER_LONG; if (i >= fdt->max_fds) break; set = fdt->open_fds[j++]; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d85b793c9321..56262223190d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2162,7 +2162,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, int fd; j++; - i = j * __NFDBITS; + i = j * BITS_PER_LONG; fdt = files_fdtable(files); if (i >= fdt->max_fds) break; -- GitLab From b4ce163953a4baab2341ba42386904a7199d11af Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Fri, 27 Jul 2012 15:07:57 +0100 Subject: [PATCH 0125/1799] dm thin: reduce endio_hook pool size commit 7768ed33ccdc02801c4483fc5682dc66ace14aea upstream. Reduce the slab size used for the dm_thin_endio_hook mempool. Allocation has been seen to fail on machines with smaller amounts of memory due to fragmentation. lvm: page allocation failure. order:5, mode:0xd0 device-mapper: table: 253:38: thin-pool: Error creating pool's endio_hook mempool Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-thin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index e0a0ebe64c09..bbb29ccc24c7 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -19,7 +19,7 @@ /* * Tunable constants */ -#define ENDIO_HOOK_POOL_SIZE 10240 +#define ENDIO_HOOK_POOL_SIZE 1024 #define DEFERRED_SET_SIZE 64 #define MAPPING_POOL_SIZE 1024 #define PRISON_CELLS 1024 -- GitLab From e73b09d8f258df200adb6383c77c38c31f6f4baa Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Fri, 27 Jul 2012 15:08:05 +0100 Subject: [PATCH 0126/1799] dm thin: fix memory leak in process_prepared_mapping error paths commit 905386f82d08f66726912f303f3e6605248c60a3 upstream. Fix memory leak in process_prepared_mapping by always freeing the dm_thin_new_mapping structs from the mapping_pool mempool on the error paths. Signed-off-by: Joe Thornber Signed-off-by: Mike Snitzer Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-thin.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index bbb29ccc24c7..1555f0b2a2be 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -855,7 +855,7 @@ static void process_prepared_mapping(struct new_mapping *m) if (m->err) { cell_error(m->cell); - return; + goto out; } /* @@ -867,7 +867,7 @@ static void process_prepared_mapping(struct new_mapping *m) if (r) { DMERR("dm_thin_insert_block() failed"); cell_error(m->cell); - return; + goto out; } /* @@ -882,6 +882,7 @@ static void process_prepared_mapping(struct new_mapping *m) } else cell_defer(tc, m->cell, m->data_block); +out: list_del(&m->list); mempool_free(m, tc->pool->mapping_pool); } -- GitLab From a647f0df62cc4eaa0f42b85c71843ed90e150536 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Fri, 8 Jun 2012 02:02:30 +0300 Subject: [PATCH 0127/1799] pnfs-obj: Fix __r4w_get_page when offset is beyond i_size commit c999ff68029ebd0f56ccae75444f640f6d5a27d2 upstream. It is very common for the end of the file to be unaligned on stripe size. But since we know it's beyond file's end then the XOR should be preformed with all zeros. Old code used to just read zeros out of the OSD devices, which is a great waist. But what scares me more about this situation is that, we now have pages attached to the file's mapping that are beyond i_size. I don't like the kind of bugs this calls for. Fix both birds, by returning a global zero_page, if offset is beyond i_size. TODO: Change the API to ->__r4w_get_page() so a NULL can be returned without being considered as error, since XOR API treats NULL entries as zero_pages. [Bug since 3.2. Should apply the same way to all Kernels since] Signed-off-by: Boaz Harrosh [bwh: Backported to 3.2: adjust for lack of wdata->header] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- fs/nfs/objlayout/objio_osd.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index 42ac1bf6fcc8..1afe74c42c8a 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c @@ -487,8 +487,16 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) struct objio_state *objios = priv; struct nfs_write_data *wdata = objios->oir.rpcdata; pgoff_t index = offset / PAGE_SIZE; - struct page *page = find_get_page(wdata->inode->i_mapping, index); + struct page *page; + loff_t i_size = i_size_read(wdata->inode); + if (offset >= i_size) { + *uptodate = true; + dprintk("%s: g_zero_page index=0x%lx\n", __func__, index); + return ZERO_PAGE(0); + } + + page = find_get_page(wdata->inode->i_mapping, index); if (!page) { page = find_or_create_page(wdata->inode->i_mapping, index, GFP_NOFS); @@ -509,8 +517,10 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) static void __r4w_put_page(void *priv, struct page *page) { - dprintk("%s: index=0x%lx\n", __func__, page->index); - page_cache_release(page); + dprintk("%s: index=0x%lx\n", __func__, + (page == ZERO_PAGE(0)) ? -1UL : page->index); + if (ZERO_PAGE(0) != page) + page_cache_release(page); return; } -- GitLab From f0f5dcc0020b78983061a2a674491f4eaa03e386 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 5 Jun 2012 16:52:06 -0400 Subject: [PATCH 0128/1799] nfsd4: our filesystems are normally case sensitive commit 2930d381d22b9c56f40dd4c63a8fa59719ca2c3c upstream. Actually, xfs and jfs can optionally be case insensitive; we'll handle that case in later patches. Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4xdr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 74c00bc92b9a..283d15e9f46d 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2233,7 +2233,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) { if ((buflen -= 4) < 0) goto out_resource; - WRITE32(1); + WRITE32(0); } if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) { if ((buflen -= 4) < 0) -- GitLab From 032da6abbc34272959c790941ce8705337061dbf Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 23 Jul 2012 13:58:51 -0400 Subject: [PATCH 0129/1799] nfs: skip commit in releasepage if we're freeing memory for fs-related reasons commit 5cf02d09b50b1ee1c2d536c9cf64af5a7d433f56 upstream. We've had some reports of a deadlock where rpciod ends up with a stack trace like this: PID: 2507 TASK: ffff88103691ab40 CPU: 14 COMMAND: "rpciod/14" #0 [ffff8810343bf2f0] schedule at ffffffff814dabd9 #1 [ffff8810343bf3b8] nfs_wait_bit_killable at ffffffffa038fc04 [nfs] #2 [ffff8810343bf3c8] __wait_on_bit at ffffffff814dbc2f #3 [ffff8810343bf418] out_of_line_wait_on_bit at ffffffff814dbcd8 #4 [ffff8810343bf488] nfs_commit_inode at ffffffffa039e0c1 [nfs] #5 [ffff8810343bf4f8] nfs_release_page at ffffffffa038bef6 [nfs] #6 [ffff8810343bf528] try_to_release_page at ffffffff8110c670 #7 [ffff8810343bf538] shrink_page_list.clone.0 at ffffffff81126271 #8 [ffff8810343bf668] shrink_inactive_list at ffffffff81126638 #9 [ffff8810343bf818] shrink_zone at ffffffff8112788f #10 [ffff8810343bf8c8] do_try_to_free_pages at ffffffff81127b1e #11 [ffff8810343bf958] try_to_free_pages at ffffffff8112812f #12 [ffff8810343bfa08] __alloc_pages_nodemask at ffffffff8111fdad #13 [ffff8810343bfb28] kmem_getpages at ffffffff81159942 #14 [ffff8810343bfb58] fallback_alloc at ffffffff8115a55a #15 [ffff8810343bfbd8] ____cache_alloc_node at ffffffff8115a2d9 #16 [ffff8810343bfc38] kmem_cache_alloc at ffffffff8115b09b #17 [ffff8810343bfc78] sk_prot_alloc at ffffffff81411808 #18 [ffff8810343bfcb8] sk_alloc at ffffffff8141197c #19 [ffff8810343bfce8] inet_create at ffffffff81483ba6 #20 [ffff8810343bfd38] __sock_create at ffffffff8140b4a7 #21 [ffff8810343bfd98] xs_create_sock at ffffffffa01f649b [sunrpc] #22 [ffff8810343bfdd8] xs_tcp_setup_socket at ffffffffa01f6965 [sunrpc] #23 [ffff8810343bfe38] worker_thread at ffffffff810887d0 #24 [ffff8810343bfee8] kthread at ffffffff8108dd96 #25 [ffff8810343bff48] kernel_thread at ffffffff8100c1ca rpciod is trying to allocate memory for a new socket to talk to the server. The VM ends up calling ->releasepage to get more memory, and it tries to do a blocking commit. That commit can't succeed however without a connected socket, so we deadlock. Fix this by setting PF_FSTRANS on the workqueue task prior to doing the socket allocation, and having nfs_release_page check for that flag when deciding whether to do a commit call. Also, set PF_FSTRANS unconditionally in rpc_async_schedule since that function can also do allocations sometimes. Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/file.c | 7 +++++-- net/sunrpc/sched.c | 2 ++ net/sunrpc/xprtrdma/transport.c | 3 ++- net/sunrpc/xprtsock.c | 10 ++++++++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index aa9b709fd328..f0f439dfeaa3 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -451,8 +451,11 @@ static int nfs_release_page(struct page *page, gfp_t gfp) dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); - /* Only do I/O if gfp is a superset of GFP_KERNEL */ - if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) { + /* Only do I/O if gfp is a superset of GFP_KERNEL, and we're not + * doing this memory reclaim for a fs-related allocation. + */ + if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL && + !(current->flags & PF_FSTRANS)) { int how = FLUSH_SYNC; /* Don't let kswapd deadlock waiting for OOM RPC calls */ diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 994cfea2bad6..eda32ae7dec4 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -790,7 +790,9 @@ void rpc_execute(struct rpc_task *task) static void rpc_async_schedule(struct work_struct *work) { + current->flags |= PF_FSTRANS; __rpc_execute(container_of(work, struct rpc_task, u.tk_work)); + current->flags &= ~PF_FSTRANS; } /** diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index b446e100286f..06cdbff79e4a 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -200,6 +200,7 @@ xprt_rdma_connect_worker(struct work_struct *work) int rc = 0; if (!xprt->shutdown) { + current->flags |= PF_FSTRANS; xprt_clear_connected(xprt); dprintk("RPC: %s: %sconnect\n", __func__, @@ -212,10 +213,10 @@ xprt_rdma_connect_worker(struct work_struct *work) out: xprt_wake_pending_tasks(xprt, rc); - out_clear: dprintk("RPC: %s: exit\n", __func__); xprt_clear_connecting(xprt); + current->flags &= ~PF_FSTRANS; } /* diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 890b03f8d877..b88c6bf657ba 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1895,6 +1895,8 @@ static void xs_local_setup_socket(struct work_struct *work) if (xprt->shutdown) goto out; + current->flags |= PF_FSTRANS; + clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); status = __sock_create(xprt->xprt_net, AF_LOCAL, SOCK_STREAM, 0, &sock, 1); @@ -1928,6 +1930,7 @@ static void xs_local_setup_socket(struct work_struct *work) out: xprt_clear_connecting(xprt); xprt_wake_pending_tasks(xprt, status); + current->flags &= ~PF_FSTRANS; } static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) @@ -1970,6 +1973,8 @@ static void xs_udp_setup_socket(struct work_struct *work) if (xprt->shutdown) goto out; + current->flags |= PF_FSTRANS; + /* Start by resetting any existing state */ xs_reset_transport(transport); sock = xs_create_sock(xprt, transport, @@ -1988,6 +1993,7 @@ static void xs_udp_setup_socket(struct work_struct *work) out: xprt_clear_connecting(xprt); xprt_wake_pending_tasks(xprt, status); + current->flags &= ~PF_FSTRANS; } /* @@ -2113,6 +2119,8 @@ static void xs_tcp_setup_socket(struct work_struct *work) if (xprt->shutdown) goto out; + current->flags |= PF_FSTRANS; + if (!sock) { clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); sock = xs_create_sock(xprt, transport, @@ -2162,6 +2170,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) case -EINPROGRESS: case -EALREADY: xprt_clear_connecting(xprt); + current->flags &= ~PF_FSTRANS; return; case -EINVAL: /* Happens, for instance, if the user specified a link @@ -2174,6 +2183,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) out: xprt_clear_connecting(xprt); xprt_wake_pending_tasks(xprt, status); + current->flags &= ~PF_FSTRANS; } /** -- GitLab From 4d71d5a6b6931f82fa9db44214019839a0ebbb4a Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 25 Jul 2012 16:53:36 +0100 Subject: [PATCH 0130/1799] NFS: Fix a number of bugs in the idmapper commit a427b9ec4eda8cd6e641ea24541d30b641fc3140 upstream. Fix a number of bugs in the NFS idmapper code: (1) Only registered key types can be passed to the core keys code, so register the legacy idmapper key type. This is a requirement because the unregister function cleans up keys belonging to that key type so that there aren't dangling pointers to the module left behind - including the key->type pointer. (2) Rename the legacy key type. You can't have two key types with the same name, and (1) would otherwise require that. (3) complete_request_key() must be called in the error path of nfs_idmap_legacy_upcall(). (4) There is one idmap struct for each nfs_client struct. This means that idmap->idmap_key_cons is shared without the use of a lock. This is a problem because key_instantiate_and_link() - as called indirectly by idmap_pipe_downcall() - releases anyone waiting for the key to be instantiated. What happens is that idmap_pipe_downcall() running in the rpc.idmapd thread, releases the NFS filesystem in whatever thread that is running in to continue. This may then make another idmapper call, overwriting idmap_key_cons before idmap_pipe_downcall() gets the chance to call complete_request_key(). I *think* that reading idmap_key_cons only once, before key_instantiate_and_link() is called, and then caching the result in a variable is sufficient. Bug (4) is the cause of: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [< (null)>] (null) PGD 0 Oops: 0010 [#1] SMP CPU 1 Modules linked in: ppdev parport_pc lp parport ip6table_filter ip6_tables ebtable_nat ebtables ipt_MASQUERADE iptable_nat nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack nfs fscache xt_CHECKSUM auth_rpcgss iptable_mangle nfs_acl bridge stp llc lockd be2iscsi iscsi_boot_sysfs bnx2i cnic uio cxgb4i cxgb4 cxgb3i libcxgbi cxgb3 mdio ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi snd_hda_codec_realtek snd_usb_audio snd_hda_intel snd_hda_codec snd_seq snd_pcm snd_hwdep snd_usbmidi_lib snd_rawmidi snd_timer uvcvideo videobuf2_core videodev media videobuf2_vmalloc snd_seq_device videobuf2_memops e1000e vhost_net iTCO_wdt joydev coretemp snd soundcore macvtap macvlan i2c_i801 snd_page_alloc tun iTCO_vendor_support microcode kvm_intel kvm sunrpc hid_logitech_dj usb_storage i915 drm_kms_helper drm i2c_algo_bit i2c_core video [last unloaded: scsi_wait_scan] Pid: 1229, comm: rpc.idmapd Not tainted 3.4.2-1.fc16.x86_64 #1 Gateway DX4710-UB801A/G33M05G1 RIP: 0010:[<0000000000000000>] [< (null)>] (null) RSP: 0018:ffff8801a3645d40 EFLAGS: 00010246 RAX: ffff880077707e30 RBX: ffff880077707f50 RCX: ffff8801a18ccd80 RDX: 0000000000000006 RSI: ffff8801a3645e75 RDI: ffff880077707f50 RBP: ffff8801a3645d88 R08: ffff8801a430f9c0 R09: ffff8801a3645db0 R10: 000000000000000a R11: 0000000000000246 R12: ffff8801a18ccd80 R13: ffff8801a3645e75 R14: ffff8801a430f9c0 R15: 0000000000000006 FS: 00007fb6fb51a700(0000) GS:ffff8801afc80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 00000001a49b0000 CR4: 00000000000027e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process rpc.idmapd (pid: 1229, threadinfo ffff8801a3644000, task ffff8801a3bf9710) Stack: ffffffff81260878 ffff8801a3645db0 ffff8801a3645db0 ffff880077707a90 ffff880077707f50 ffff8801a18ccd80 0000000000000006 ffff8801a3645e75 ffff8801a430f9c0 ffff8801a3645dd8 ffffffff81260983 ffff8801a3645de8 Call Trace: [] ? __key_instantiate_and_link+0x58/0x100 [] key_instantiate_and_link+0x63/0xa0 [] idmap_pipe_downcall+0x1cb/0x1e0 [nfs] [] rpc_pipe_write+0x67/0x90 [sunrpc] [] vfs_write+0xb3/0x180 [] sys_write+0x4a/0x90 [] system_call_fastpath+0x16/0x1b Code: Bad RIP value. RIP [< (null)>] (null) RSP CR2: 0000000000000000 Signed-off-by: David Howells Reviewed-by: Steve Dickson Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/idmap.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 93aa3a4c4b0f..929ba0111724 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -205,12 +205,18 @@ static int nfs_idmap_init_keyring(void) if (ret < 0) goto failed_put_key; + ret = register_key_type(&key_type_id_resolver_legacy); + if (ret < 0) + goto failed_reg_legacy; + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; id_resolver_cache = cred; return 0; +failed_reg_legacy: + unregister_key_type(&key_type_id_resolver); failed_put_key: key_put(keyring); failed_put_cred: @@ -222,6 +228,7 @@ static void nfs_idmap_quit_keyring(void) { key_revoke(id_resolver_cache->thread_keyring); unregister_key_type(&key_type_id_resolver); + unregister_key_type(&key_type_id_resolver_legacy); put_cred(id_resolver_cache); } @@ -385,7 +392,7 @@ static const struct rpc_pipe_ops idmap_upcall_ops = { }; static struct key_type key_type_id_resolver_legacy = { - .name = "id_resolver", + .name = "id_legacy", .instantiate = user_instantiate, .match = user_match, .revoke = user_revoke, @@ -658,6 +665,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, if (ret < 0) goto out2; + BUG_ON(idmap->idmap_key_cons != NULL); idmap->idmap_key_cons = cons; ret = rpc_queue_upcall(idmap->idmap_pipe, msg); @@ -671,8 +679,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, out1: kfree(msg); out0: - key_revoke(cons->key); - key_revoke(cons->authkey); + complete_request_key(cons, ret); return ret; } @@ -706,11 +713,18 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) { struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode); struct idmap *idmap = (struct idmap *)rpci->private; - struct key_construction *cons = idmap->idmap_key_cons; + struct key_construction *cons; struct idmap_msg im; size_t namelen_in; int ret; + /* If instantiation is successful, anyone waiting for key construction + * will have been woken up and someone else may now have used + * idmap_key_cons - so after this point we may no longer touch it. + */ + cons = ACCESS_ONCE(idmap->idmap_key_cons); + idmap->idmap_key_cons = NULL; + if (mlen != sizeof(im)) { ret = -ENOSPC; goto out; @@ -723,7 +737,7 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) if (!(im.im_status & IDMAP_STATUS_SUCCESS)) { ret = mlen; - complete_request_key(idmap->idmap_key_cons, -ENOKEY); + complete_request_key(cons, -ENOKEY); goto out_incomplete; } @@ -740,7 +754,7 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) } out: - complete_request_key(idmap->idmap_key_cons, ret); + complete_request_key(cons, ret); out_incomplete: return ret; } -- GitLab From 66b68d2374b0c251224c28c69fc25eeef343e122 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 4 Jun 2012 12:00:31 +0200 Subject: [PATCH 0131/1799] nouveau: Fix alignment requirements on src and dst addresses commit ce806a30470bcd846d148bf39d46de3ad7748228 upstream. Linear copy works by adding the offset to the buffer address, which may end up not being 16-byte aligned. Some tests I've written for prime_pcopy show that the engine allows this correctly, so the restriction on lowest 4 bits of address can be lifted safely. The comments added were by envyas, I think because I used a newer version. Signed-off-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nva3_copy.fuc | 4 +- drivers/gpu/drm/nouveau/nva3_copy.fuc.h | 94 +++++++++++++++++++++++-- drivers/gpu/drm/nouveau/nvc0_copy.fuc.h | 87 +++++++++++++++++++++-- 3 files changed, 175 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nva3_copy.fuc b/drivers/gpu/drm/nouveau/nva3_copy.fuc index abc36626fef0..219850d53286 100644 --- a/drivers/gpu/drm/nouveau/nva3_copy.fuc +++ b/drivers/gpu/drm/nouveau/nva3_copy.fuc @@ -119,9 +119,9 @@ dispatch_dma: // mthd 0x030c-0x0340, various stuff .b16 0xc3 14 .b32 #ctx_src_address_high ~0x000000ff -.b32 #ctx_src_address_low ~0xfffffff0 +.b32 #ctx_src_address_low ~0xffffffff .b32 #ctx_dst_address_high ~0x000000ff -.b32 #ctx_dst_address_low ~0xfffffff0 +.b32 #ctx_dst_address_low ~0xffffffff .b32 #ctx_src_pitch ~0x0007ffff .b32 #ctx_dst_pitch ~0x0007ffff .b32 #ctx_xcnt ~0x0000ffff diff --git a/drivers/gpu/drm/nouveau/nva3_copy.fuc.h b/drivers/gpu/drm/nouveau/nva3_copy.fuc.h index 1f33fbdc00be..37d6de3c9d61 100644 --- a/drivers/gpu/drm/nouveau/nva3_copy.fuc.h +++ b/drivers/gpu/drm/nouveau/nva3_copy.fuc.h @@ -1,37 +1,72 @@ -uint32_t nva3_pcopy_data[] = { +u32 nva3_pcopy_data[] = { +/* 0x0000: ctx_object */ 0x00000000, +/* 0x0004: ctx_dma */ +/* 0x0004: ctx_dma_query */ 0x00000000, +/* 0x0008: ctx_dma_src */ 0x00000000, +/* 0x000c: ctx_dma_dst */ 0x00000000, +/* 0x0010: ctx_query_address_high */ 0x00000000, +/* 0x0014: ctx_query_address_low */ 0x00000000, +/* 0x0018: ctx_query_counter */ 0x00000000, +/* 0x001c: ctx_src_address_high */ 0x00000000, +/* 0x0020: ctx_src_address_low */ 0x00000000, +/* 0x0024: ctx_src_pitch */ 0x00000000, +/* 0x0028: ctx_src_tile_mode */ 0x00000000, +/* 0x002c: ctx_src_xsize */ 0x00000000, +/* 0x0030: ctx_src_ysize */ 0x00000000, +/* 0x0034: ctx_src_zsize */ 0x00000000, +/* 0x0038: ctx_src_zoff */ 0x00000000, +/* 0x003c: ctx_src_xoff */ 0x00000000, +/* 0x0040: ctx_src_yoff */ 0x00000000, +/* 0x0044: ctx_src_cpp */ 0x00000000, +/* 0x0048: ctx_dst_address_high */ 0x00000000, +/* 0x004c: ctx_dst_address_low */ 0x00000000, +/* 0x0050: ctx_dst_pitch */ 0x00000000, +/* 0x0054: ctx_dst_tile_mode */ 0x00000000, +/* 0x0058: ctx_dst_xsize */ 0x00000000, +/* 0x005c: ctx_dst_ysize */ 0x00000000, +/* 0x0060: ctx_dst_zsize */ 0x00000000, +/* 0x0064: ctx_dst_zoff */ 0x00000000, +/* 0x0068: ctx_dst_xoff */ 0x00000000, +/* 0x006c: ctx_dst_yoff */ 0x00000000, +/* 0x0070: ctx_dst_cpp */ 0x00000000, +/* 0x0074: ctx_format */ 0x00000000, +/* 0x0078: ctx_swz_const0 */ 0x00000000, +/* 0x007c: ctx_swz_const1 */ 0x00000000, +/* 0x0080: ctx_xcnt */ 0x00000000, +/* 0x0084: ctx_ycnt */ 0x00000000, 0x00000000, 0x00000000, @@ -63,6 +98,7 @@ uint32_t nva3_pcopy_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0100: dispatch_table */ 0x00010000, 0x00000000, 0x00000000, @@ -73,6 +109,7 @@ uint32_t nva3_pcopy_data[] = { 0x00010162, 0x00000000, 0x00030060, +/* 0x0128: dispatch_dma */ 0x00010170, 0x00000000, 0x00010170, @@ -118,11 +155,11 @@ uint32_t nva3_pcopy_data[] = { 0x0000001c, 0xffffff00, 0x00000020, - 0x0000000f, + 0x00000000, 0x00000048, 0xffffff00, 0x0000004c, - 0x0000000f, + 0x00000000, 0x00000024, 0xfff80000, 0x00000050, @@ -146,7 +183,8 @@ uint32_t nva3_pcopy_data[] = { 0x00000800, }; -uint32_t nva3_pcopy_code[] = { +u32 nva3_pcopy_code[] = { +/* 0x0000: main */ 0x04fe04bd, 0x3517f000, 0xf10010fe, @@ -158,23 +196,31 @@ uint32_t nva3_pcopy_code[] = { 0x17f11031, 0x27f01200, 0x0012d003, +/* 0x002f: spin */ 0xf40031f4, 0x0ef40028, +/* 0x0035: ih */ 0x8001cffd, 0xf40812c4, 0x21f4060b, +/* 0x0041: ih_no_chsw */ 0x0412c472, 0xf4060bf4, +/* 0x004a: ih_no_cmd */ 0x11c4c321, 0x4001d00c, +/* 0x0052: swctx */ 0x47f101f8, 0x4bfe7700, 0x0007fe00, 0xf00204b9, 0x01f40643, 0x0604fa09, +/* 0x006b: swctx_load */ 0xfa060ef4, +/* 0x006e: swctx_done */ 0x03f80504, +/* 0x0072: chsw */ 0x27f100f8, 0x23cf1400, 0x1e3fc800, @@ -183,18 +229,22 @@ uint32_t nva3_pcopy_code[] = { 0x1e3af052, 0xf00023d0, 0x24d00147, +/* 0x0093: chsw_no_unload */ 0xcf00f880, 0x3dc84023, 0x220bf41e, 0xf40131f4, 0x57f05221, 0x0367f004, +/* 0x00a8: chsw_load_ctx_dma */ 0xa07856bc, 0xb6018068, 0x87d00884, 0x0162b600, +/* 0x00bb: chsw_finish_load */ 0xf0f018f4, 0x23d00237, +/* 0x00c3: dispatch */ 0xf100f880, 0xcf190037, 0x33cf4032, @@ -202,6 +252,7 @@ uint32_t nva3_pcopy_code[] = { 0x1024b607, 0x010057f1, 0x74bd64bd, +/* 0x00dc: dispatch_loop */ 0x58005658, 0x50b60157, 0x0446b804, @@ -211,6 +262,7 @@ uint32_t nva3_pcopy_code[] = { 0xb60276bb, 0x57bb0374, 0xdf0ef400, +/* 0x0100: dispatch_valid_mthd */ 0xb60246bb, 0x45bb0344, 0x01459800, @@ -220,31 +272,41 @@ uint32_t nva3_pcopy_code[] = { 0xb0014658, 0x1bf40064, 0x00538009, +/* 0x0127: dispatch_cmd */ 0xf4300ef4, 0x55f90132, 0xf40c01f4, +/* 0x0132: dispatch_invalid_bitfield */ 0x25f0250e, +/* 0x0135: dispatch_illegal_mthd */ 0x0125f002, +/* 0x0138: dispatch_error */ 0x100047f1, 0xd00042d0, 0x27f04043, 0x0002d040, +/* 0x0148: hostirq_wait */ 0xf08002cf, 0x24b04024, 0xf71bf400, +/* 0x0154: dispatch_done */ 0x1d0027f1, 0xd00137f0, 0x00f80023, +/* 0x0160: cmd_nop */ +/* 0x0162: cmd_pm_trigger */ 0x27f100f8, 0x34bd2200, 0xd00233f0, 0x00f80023, +/* 0x0170: cmd_dma */ 0x012842b7, 0xf00145b6, 0x43801e39, 0x0040b701, 0x0644b606, 0xf80043d0, +/* 0x0189: cmd_exec_set_format */ 0xf030f400, 0xb00001b0, 0x01b00101, @@ -256,20 +318,26 @@ uint32_t nva3_pcopy_code[] = { 0x70b63847, 0x0232f401, 0x94bd84bd, +/* 0x01b4: ncomp_loop */ 0xb60f4ac4, 0xb4bd0445, +/* 0x01bc: bpc_loop */ 0xf404a430, 0xa5ff0f18, 0x00cbbbc0, 0xf40231f4, +/* 0x01ce: cmp_c0 */ 0x1bf4220e, 0x10c7f00c, 0xf400cbbb, +/* 0x01da: cmp_c1 */ 0xa430160e, 0x0c18f406, 0xbb14c7f0, 0x0ef400cb, +/* 0x01e9: cmp_zero */ 0x80c7f107, +/* 0x01ed: bpc_next */ 0x01c83800, 0xb60180b6, 0xb5b801b0, @@ -280,6 +348,7 @@ uint32_t nva3_pcopy_code[] = { 0x98110680, 0x68fd2008, 0x0502f400, +/* 0x0216: dst_xcnt */ 0x75fd64bd, 0x1c078000, 0xf10078fd, @@ -304,6 +373,7 @@ uint32_t nva3_pcopy_code[] = { 0x980056d0, 0x56d01f06, 0x1030f440, +/* 0x0276: cmd_exec_set_surface_tiled */ 0x579800f8, 0x6879c70a, 0xb66478c7, @@ -311,9 +381,11 @@ uint32_t nva3_pcopy_code[] = { 0x0e76b060, 0xf0091bf4, 0x0ef40477, +/* 0x0291: xtile64 */ 0x027cf00f, 0xfd1170b6, 0x77f00947, +/* 0x029d: xtileok */ 0x0f5a9806, 0xfd115b98, 0xb7f000ab, @@ -371,6 +443,7 @@ uint32_t nva3_pcopy_code[] = { 0x67d00600, 0x0060b700, 0x0068d004, +/* 0x0382: cmd_exec_set_surface_linear */ 0x6cf000f8, 0x0260b702, 0x0864b602, @@ -381,13 +454,16 @@ uint32_t nva3_pcopy_code[] = { 0xb70067d0, 0x98040060, 0x67d00957, +/* 0x03ab: cmd_exec_wait */ 0xf900f800, 0xf110f900, 0xb6080007, +/* 0x03b6: loop */ 0x01cf0604, 0x0114f000, 0xfcfa1bf4, 0xf800fc10, +/* 0x03c5: cmd_exec_query */ 0x0d34c800, 0xf5701bf4, 0xf103ab21, @@ -417,6 +493,7 @@ uint32_t nva3_pcopy_code[] = { 0x47f10153, 0x44b60800, 0x0045d006, +/* 0x0438: query_counter */ 0x03ab21f5, 0x080c47f1, 0x980644b6, @@ -439,11 +516,13 @@ uint32_t nva3_pcopy_code[] = { 0x47f10153, 0x44b60800, 0x0045d006, +/* 0x0492: cmd_exec */ 0x21f500f8, 0x3fc803ab, 0x0e0bf400, 0x018921f5, 0x020047f1, +/* 0x04a7: cmd_exec_no_format */ 0xf11e0ef4, 0xb6081067, 0x77f00664, @@ -451,19 +530,24 @@ uint32_t nva3_pcopy_code[] = { 0x981c0780, 0x67d02007, 0x4067d000, +/* 0x04c2: cmd_exec_init_src_surface */ 0x32f444bd, 0xc854bd02, 0x0bf4043f, 0x8221f50a, 0x0a0ef403, +/* 0x04d4: src_tiled */ 0x027621f5, +/* 0x04db: cmd_exec_init_dst_surface */ 0xf40749f0, 0x57f00231, 0x083fc82c, 0xf50a0bf4, 0xf4038221, +/* 0x04ee: dst_tiled */ 0x21f50a0e, 0x49f00276, +/* 0x04f5: cmd_exec_kick */ 0x0057f108, 0x0654b608, 0xd0210698, @@ -473,6 +557,8 @@ uint32_t nva3_pcopy_code[] = { 0xc80054d0, 0x0bf40c3f, 0xc521f507, +/* 0x0519: cmd_exec_done */ +/* 0x051b: cmd_wrcache_flush */ 0xf100f803, 0xbd220027, 0x0133f034, diff --git a/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h b/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h index a8d17458ced1..cd879f31bb38 100644 --- a/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h +++ b/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h @@ -1,34 +1,65 @@ -uint32_t nvc0_pcopy_data[] = { +u32 nvc0_pcopy_data[] = { +/* 0x0000: ctx_object */ 0x00000000, +/* 0x0004: ctx_query_address_high */ 0x00000000, +/* 0x0008: ctx_query_address_low */ 0x00000000, +/* 0x000c: ctx_query_counter */ 0x00000000, +/* 0x0010: ctx_src_address_high */ 0x00000000, +/* 0x0014: ctx_src_address_low */ 0x00000000, +/* 0x0018: ctx_src_pitch */ 0x00000000, +/* 0x001c: ctx_src_tile_mode */ 0x00000000, +/* 0x0020: ctx_src_xsize */ 0x00000000, +/* 0x0024: ctx_src_ysize */ 0x00000000, +/* 0x0028: ctx_src_zsize */ 0x00000000, +/* 0x002c: ctx_src_zoff */ 0x00000000, +/* 0x0030: ctx_src_xoff */ 0x00000000, +/* 0x0034: ctx_src_yoff */ 0x00000000, +/* 0x0038: ctx_src_cpp */ 0x00000000, +/* 0x003c: ctx_dst_address_high */ 0x00000000, +/* 0x0040: ctx_dst_address_low */ 0x00000000, +/* 0x0044: ctx_dst_pitch */ 0x00000000, +/* 0x0048: ctx_dst_tile_mode */ 0x00000000, +/* 0x004c: ctx_dst_xsize */ 0x00000000, +/* 0x0050: ctx_dst_ysize */ 0x00000000, +/* 0x0054: ctx_dst_zsize */ 0x00000000, +/* 0x0058: ctx_dst_zoff */ 0x00000000, +/* 0x005c: ctx_dst_xoff */ 0x00000000, +/* 0x0060: ctx_dst_yoff */ 0x00000000, +/* 0x0064: ctx_dst_cpp */ 0x00000000, +/* 0x0068: ctx_format */ 0x00000000, +/* 0x006c: ctx_swz_const0 */ 0x00000000, +/* 0x0070: ctx_swz_const1 */ 0x00000000, +/* 0x0074: ctx_xcnt */ 0x00000000, +/* 0x0078: ctx_ycnt */ 0x00000000, 0x00000000, 0x00000000, @@ -63,6 +94,7 @@ uint32_t nvc0_pcopy_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0100: dispatch_table */ 0x00010000, 0x00000000, 0x00000000, @@ -111,11 +143,11 @@ uint32_t nvc0_pcopy_data[] = { 0x00000010, 0xffffff00, 0x00000014, - 0x0000000f, + 0x00000000, 0x0000003c, 0xffffff00, 0x00000040, - 0x0000000f, + 0x00000000, 0x00000018, 0xfff80000, 0x00000044, @@ -139,7 +171,8 @@ uint32_t nvc0_pcopy_data[] = { 0x00000800, }; -uint32_t nvc0_pcopy_code[] = { +u32 nvc0_pcopy_code[] = { +/* 0x0000: main */ 0x04fe04bd, 0x3517f000, 0xf10010fe, @@ -151,15 +184,20 @@ uint32_t nvc0_pcopy_code[] = { 0x17f11031, 0x27f01200, 0x0012d003, +/* 0x002f: spin */ 0xf40031f4, 0x0ef40028, +/* 0x0035: ih */ 0x8001cffd, 0xf40812c4, 0x21f4060b, +/* 0x0041: ih_no_chsw */ 0x0412c4ca, 0xf5070bf4, +/* 0x004b: ih_no_cmd */ 0xc4010221, 0x01d00c11, +/* 0x0053: swctx */ 0xf101f840, 0xfe770047, 0x47f1004b, @@ -188,8 +226,11 @@ uint32_t nvc0_pcopy_code[] = { 0xf00204b9, 0x01f40643, 0x0604fa09, +/* 0x00c3: swctx_load */ 0xfa060ef4, +/* 0x00c6: swctx_done */ 0x03f80504, +/* 0x00ca: chsw */ 0x27f100f8, 0x23cf1400, 0x1e3fc800, @@ -198,18 +239,22 @@ uint32_t nvc0_pcopy_code[] = { 0x1e3af053, 0xf00023d0, 0x24d00147, +/* 0x00eb: chsw_no_unload */ 0xcf00f880, 0x3dc84023, 0x090bf41e, 0xf40131f4, +/* 0x00fa: chsw_finish_load */ 0x37f05321, 0x8023d002, +/* 0x0102: dispatch */ 0x37f100f8, 0x32cf1900, 0x0033cf40, 0x07ff24e4, 0xf11024b6, 0xbd010057, +/* 0x011b: dispatch_loop */ 0x5874bd64, 0x57580056, 0x0450b601, @@ -219,6 +264,7 @@ uint32_t nvc0_pcopy_code[] = { 0xbb0f08f4, 0x74b60276, 0x0057bb03, +/* 0x013f: dispatch_valid_mthd */ 0xbbdf0ef4, 0x44b60246, 0x0045bb03, @@ -229,24 +275,33 @@ uint32_t nvc0_pcopy_code[] = { 0x64b00146, 0x091bf400, 0xf4005380, +/* 0x0166: dispatch_cmd */ 0x32f4300e, 0xf455f901, 0x0ef40c01, +/* 0x0171: dispatch_invalid_bitfield */ 0x0225f025, +/* 0x0174: dispatch_illegal_mthd */ +/* 0x0177: dispatch_error */ 0xf10125f0, 0xd0100047, 0x43d00042, 0x4027f040, +/* 0x0187: hostirq_wait */ 0xcf0002d0, 0x24f08002, 0x0024b040, +/* 0x0193: dispatch_done */ 0xf1f71bf4, 0xf01d0027, 0x23d00137, +/* 0x019f: cmd_nop */ 0xf800f800, +/* 0x01a1: cmd_pm_trigger */ 0x0027f100, 0xf034bd22, 0x23d00233, +/* 0x01af: cmd_exec_set_format */ 0xf400f800, 0x01b0f030, 0x0101b000, @@ -258,20 +313,26 @@ uint32_t nvc0_pcopy_code[] = { 0x3847c701, 0xf40170b6, 0x84bd0232, +/* 0x01da: ncomp_loop */ 0x4ac494bd, 0x0445b60f, +/* 0x01e2: bpc_loop */ 0xa430b4bd, 0x0f18f404, 0xbbc0a5ff, 0x31f400cb, 0x220ef402, +/* 0x01f4: cmp_c0 */ 0xf00c1bf4, 0xcbbb10c7, 0x160ef400, +/* 0x0200: cmp_c1 */ 0xf406a430, 0xc7f00c18, 0x00cbbb14, +/* 0x020f: cmp_zero */ 0xf1070ef4, +/* 0x0213: bpc_next */ 0x380080c7, 0x80b601c8, 0x01b0b601, @@ -283,6 +344,7 @@ uint32_t nvc0_pcopy_code[] = { 0x1d08980e, 0xf40068fd, 0x64bd0502, +/* 0x023c: dst_xcnt */ 0x800075fd, 0x78fd1907, 0x1057f100, @@ -307,15 +369,18 @@ uint32_t nvc0_pcopy_code[] = { 0x1c069800, 0xf44056d0, 0x00f81030, +/* 0x029c: cmd_exec_set_surface_tiled */ 0xc7075798, 0x78c76879, 0x0380b664, 0xb06077c7, 0x1bf40e76, 0x0477f009, +/* 0x02b7: xtile64 */ 0xf00f0ef4, 0x70b6027c, 0x0947fd11, +/* 0x02c3: xtileok */ 0x980677f0, 0x5b980c5a, 0x00abfd0e, @@ -374,6 +439,7 @@ uint32_t nvc0_pcopy_code[] = { 0xb70067d0, 0xd0040060, 0x00f80068, +/* 0x03a8: cmd_exec_set_surface_linear */ 0xb7026cf0, 0xb6020260, 0x57980864, @@ -384,12 +450,15 @@ uint32_t nvc0_pcopy_code[] = { 0x0060b700, 0x06579804, 0xf80067d0, +/* 0x03d1: cmd_exec_wait */ 0xf900f900, 0x0007f110, 0x0604b608, +/* 0x03dc: loop */ 0xf00001cf, 0x1bf40114, 0xfc10fcfa, +/* 0x03eb: cmd_exec_query */ 0xc800f800, 0x1bf40d34, 0xd121f570, @@ -419,6 +488,7 @@ uint32_t nvc0_pcopy_code[] = { 0x0153f026, 0x080047f1, 0xd00644b6, +/* 0x045e: query_counter */ 0x21f50045, 0x47f103d1, 0x44b6080c, @@ -442,11 +512,13 @@ uint32_t nvc0_pcopy_code[] = { 0x080047f1, 0xd00644b6, 0x00f80045, +/* 0x04b8: cmd_exec */ 0x03d121f5, 0xf4003fc8, 0x21f50e0b, 0x47f101af, 0x0ef40200, +/* 0x04cd: cmd_exec_no_format */ 0x1067f11e, 0x0664b608, 0x800177f0, @@ -454,18 +526,23 @@ uint32_t nvc0_pcopy_code[] = { 0x1d079819, 0xd00067d0, 0x44bd4067, +/* 0x04e8: cmd_exec_init_src_surface */ 0xbd0232f4, 0x043fc854, 0xf50a0bf4, 0xf403a821, +/* 0x04fa: src_tiled */ 0x21f50a0e, 0x49f0029c, +/* 0x0501: cmd_exec_init_dst_surface */ 0x0231f407, 0xc82c57f0, 0x0bf4083f, 0xa821f50a, 0x0a0ef403, +/* 0x0514: dst_tiled */ 0x029c21f5, +/* 0x051b: cmd_exec_kick */ 0xf10849f0, 0xb6080057, 0x06980654, @@ -475,7 +552,9 @@ uint32_t nvc0_pcopy_code[] = { 0x54d00546, 0x0c3fc800, 0xf5070bf4, +/* 0x053f: cmd_exec_done */ 0xf803eb21, +/* 0x0541: cmd_wrcache_flush */ 0x0027f100, 0xf034bd22, 0x23d00133, -- GitLab From 2a271d6a66d1d10f001c5653da68c1f72d0ded59 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 30 Jun 2012 19:14:57 -0400 Subject: [PATCH 0132/1799] ext4: pass a char * to ext4_count_free() instead of a buffer_head ptr commit f6fb99cadcd44660c68e13f6eab28333653621e6 upstream. Make it possible for ext4_count_free to operate on buffers and not just data in buffer_heads. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/balloc.c | 3 ++- fs/ext4/bitmap.c | 8 +++----- fs/ext4/ext4.h | 2 +- fs/ext4/ialloc.c | 3 ++- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 8da837be0c82..df76291d692b 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -584,7 +584,8 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb) if (bitmap_bh == NULL) continue; - x = ext4_count_free(bitmap_bh, sb->s_blocksize); + x = ext4_count_free(bitmap_bh->b_data, + EXT4_BLOCKS_PER_GROUP(sb) / 8); printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n", i, ext4_free_group_clusters(sb, gdp), x); bitmap_count += x; diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c index fa3af81ac565..012faaaec4ad 100644 --- a/fs/ext4/bitmap.c +++ b/fs/ext4/bitmap.c @@ -15,15 +15,13 @@ static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; -unsigned int ext4_count_free(struct buffer_head *map, unsigned int numchars) +unsigned int ext4_count_free(char *bitmap, unsigned int numchars) { unsigned int i, sum = 0; - if (!map) - return 0; for (i = 0; i < numchars; i++) - sum += nibblemap[map->b_data[i] & 0xf] + - nibblemap[(map->b_data[i] >> 4) & 0xf]; + sum += nibblemap[bitmap[i] & 0xf] + + nibblemap[(bitmap[i] >> 4) & 0xf]; return sum; } diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 0e01e90add8b..962988d14bb2 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1783,7 +1783,7 @@ struct mmpd_data { # define NORET_AND noreturn, /* bitmap.c */ -extern unsigned int ext4_count_free(struct buffer_head *, unsigned); +extern unsigned int ext4_count_free(char *bitmap, unsigned numchars); /* balloc.c */ extern unsigned int ext4_block_group(struct super_block *sb, diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 8900f8b2ad48..0ee374d27fdb 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -1013,7 +1013,8 @@ unsigned long ext4_count_free_inodes(struct super_block *sb) if (!bitmap_bh) continue; - x = ext4_count_free(bitmap_bh, EXT4_INODES_PER_GROUP(sb) / 8); + x = ext4_count_free(bitmap_bh->b_data, + EXT4_INODES_PER_GROUP(sb) / 8); printk(KERN_DEBUG "group %lu: stored = %d, counted = %lu\n", (unsigned long) i, ext4_free_inodes_count(sb, gdp), x); bitmap_count += x; -- GitLab From 25471391e7a0acace5821318fc0123a0a5cfdbbe Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 9 Jul 2012 16:27:05 -0400 Subject: [PATCH 0133/1799] ext4: fix overhead calculation used by ext4_statfs() commit 952fc18ef9ec707ebdc16c0786ec360295e5ff15 upstream. Commit f975d6bcc7a introduced bug which caused ext4_statfs() to miscalculate the number of file system overhead blocks. This causes the f_blocks field in the statfs structure to be larger than it should be. This would in turn cause the "df" output to show the number of data blocks in the file system and the number of data blocks used to be larger than they should be. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/bitmap.c | 4 -- fs/ext4/ext4.h | 4 +- fs/ext4/resize.c | 7 +- fs/ext4/super.c | 174 +++++++++++++++++++++++++++++++++-------------- 4 files changed, 132 insertions(+), 57 deletions(-) diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c index 012faaaec4ad..bbde5d582978 100644 --- a/fs/ext4/bitmap.c +++ b/fs/ext4/bitmap.c @@ -11,8 +11,6 @@ #include #include "ext4.h" -#ifdef EXT4FS_DEBUG - static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; unsigned int ext4_count_free(char *bitmap, unsigned int numchars) @@ -25,5 +23,3 @@ unsigned int ext4_count_free(char *bitmap, unsigned int numchars) return sum; } -#endif /* EXT4FS_DEBUG */ - diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 962988d14bb2..47d1c8cda0cb 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1140,8 +1140,7 @@ struct ext4_sb_info { unsigned long s_desc_per_block; /* Number of group descriptors per block */ ext4_group_t s_groups_count; /* Number of groups in the fs */ ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */ - unsigned long s_overhead_last; /* Last calculated overhead */ - unsigned long s_blocks_last; /* Last seen block count */ + unsigned long s_overhead; /* # of fs overhead clusters */ unsigned int s_cluster_ratio; /* Number of blocks per cluster */ unsigned int s_cluster_bits; /* log2 of s_cluster_ratio */ loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */ @@ -1950,6 +1949,7 @@ extern int ext4_group_extend(struct super_block *sb, extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count); /* super.c */ +extern int ext4_calculate_overhead(struct super_block *sb); extern void *ext4_kvmalloc(size_t size, gfp_t flags); extern void *ext4_kvzalloc(size_t size, gfp_t flags); extern void ext4_kvfree(void *ptr); diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 53589ff8824b..3407a62590d6 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -1141,7 +1141,7 @@ static void ext4_update_super(struct super_block *sb, struct ext4_new_group_data *group_data = flex_gd->groups; struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_super_block *es = sbi->s_es; - int i; + int i, ret; BUG_ON(flex_gd->count == 0 || group_data == NULL); /* @@ -1216,6 +1216,11 @@ static void ext4_update_super(struct super_block *sb, &sbi->s_flex_groups[flex_group].free_inodes); } + /* + * Update the fs overhead information + */ + ext4_calculate_overhead(sb); + if (test_opt(sb, DEBUG)) printk(KERN_DEBUG "EXT4-fs: added group %u:" "%llu blocks(%llu free %llu reserved)\n", flex_gd->count, diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a68703a56102..7fe3869d33d5 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -2944,6 +2944,114 @@ static void ext4_destroy_lazyinit_thread(void) kthread_stop(ext4_lazyinit_task); } +/* + * Note: calculating the overhead so we can be compatible with + * historical BSD practice is quite difficult in the face of + * clusters/bigalloc. This is because multiple metadata blocks from + * different block group can end up in the same allocation cluster. + * Calculating the exact overhead in the face of clustered allocation + * requires either O(all block bitmaps) in memory or O(number of block + * groups**2) in time. We will still calculate the superblock for + * older file systems --- and if we come across with a bigalloc file + * system with zero in s_overhead_clusters the estimate will be close to + * correct especially for very large cluster sizes --- but for newer + * file systems, it's better to calculate this figure once at mkfs + * time, and store it in the superblock. If the superblock value is + * present (even for non-bigalloc file systems), we will use it. + */ +static int count_overhead(struct super_block *sb, ext4_group_t grp, + char *buf) +{ + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct ext4_group_desc *gdp; + ext4_fsblk_t first_block, last_block, b; + ext4_group_t i, ngroups = ext4_get_groups_count(sb); + int s, j, count = 0; + + first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + + (grp * EXT4_BLOCKS_PER_GROUP(sb)); + last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; + for (i = 0; i < ngroups; i++) { + gdp = ext4_get_group_desc(sb, i, NULL); + b = ext4_block_bitmap(sb, gdp); + if (b >= first_block && b <= last_block) { + ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf); + count++; + } + b = ext4_inode_bitmap(sb, gdp); + if (b >= first_block && b <= last_block) { + ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf); + count++; + } + b = ext4_inode_table(sb, gdp); + if (b >= first_block && b + sbi->s_itb_per_group <= last_block) + for (j = 0; j < sbi->s_itb_per_group; j++, b++) { + int c = EXT4_B2C(sbi, b - first_block); + ext4_set_bit(c, buf); + count++; + } + if (i != grp) + continue; + s = 0; + if (ext4_bg_has_super(sb, grp)) { + ext4_set_bit(s++, buf); + count++; + } + for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) { + ext4_set_bit(EXT4_B2C(sbi, s++), buf); + count++; + } + } + if (!count) + return 0; + return EXT4_CLUSTERS_PER_GROUP(sb) - + ext4_count_free(buf, EXT4_CLUSTERS_PER_GROUP(sb) / 8); +} + +/* + * Compute the overhead and stash it in sbi->s_overhead + */ +int ext4_calculate_overhead(struct super_block *sb) +{ + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct ext4_super_block *es = sbi->s_es; + ext4_group_t i, ngroups = ext4_get_groups_count(sb); + ext4_fsblk_t overhead = 0; + char *buf = (char *) get_zeroed_page(GFP_KERNEL); + + memset(buf, 0, PAGE_SIZE); + if (!buf) + return -ENOMEM; + + /* + * Compute the overhead (FS structures). This is constant + * for a given filesystem unless the number of block groups + * changes so we cache the previous value until it does. + */ + + /* + * All of the blocks before first_data_block are overhead + */ + overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block)); + + /* + * Add the overhead found in each block group + */ + for (i = 0; i < ngroups; i++) { + int blks; + + blks = count_overhead(sb, i, buf); + overhead += blks; + if (blks) + memset(buf, 0, PAGE_SIZE); + cond_resched(); + } + sbi->s_overhead = overhead; + smp_wmb(); + free_page((unsigned long) buf); + return 0; +} + static int ext4_fill_super(struct super_block *sb, void *data, int silent) { char *orig_data = kstrdup(data, GFP_KERNEL); @@ -3558,6 +3666,18 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) percpu_counter_set(&sbi->s_dirtyclusters_counter, 0); no_journal: + /* + * Get the # of file system overhead blocks from the + * superblock if present. + */ + if (es->s_overhead_clusters) + sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters); + else { + ret = ext4_calculate_overhead(sb); + if (ret) + goto failed_mount_wq; + } + /* * The maximum number of concurrent works can be high and * concurrency isn't really necessary. Limit it to 1. @@ -4421,67 +4541,21 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) return err; } -/* - * Note: calculating the overhead so we can be compatible with - * historical BSD practice is quite difficult in the face of - * clusters/bigalloc. This is because multiple metadata blocks from - * different block group can end up in the same allocation cluster. - * Calculating the exact overhead in the face of clustered allocation - * requires either O(all block bitmaps) in memory or O(number of block - * groups**2) in time. We will still calculate the superblock for - * older file systems --- and if we come across with a bigalloc file - * system with zero in s_overhead_clusters the estimate will be close to - * correct especially for very large cluster sizes --- but for newer - * file systems, it's better to calculate this figure once at mkfs - * time, and store it in the superblock. If the superblock value is - * present (even for non-bigalloc file systems), we will use it. - */ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_super_block *es = sbi->s_es; - struct ext4_group_desc *gdp; + ext4_fsblk_t overhead = 0; u64 fsid; s64 bfree; - if (test_opt(sb, MINIX_DF)) { - sbi->s_overhead_last = 0; - } else if (es->s_overhead_clusters) { - sbi->s_overhead_last = le32_to_cpu(es->s_overhead_clusters); - } else if (sbi->s_blocks_last != ext4_blocks_count(es)) { - ext4_group_t i, ngroups = ext4_get_groups_count(sb); - ext4_fsblk_t overhead = 0; - - /* - * Compute the overhead (FS structures). This is constant - * for a given filesystem unless the number of block groups - * changes so we cache the previous value until it does. - */ - - /* - * All of the blocks before first_data_block are - * overhead - */ - overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block)); - - /* - * Add the overhead found in each block group - */ - for (i = 0; i < ngroups; i++) { - gdp = ext4_get_group_desc(sb, i, NULL); - overhead += ext4_num_overhead_clusters(sb, i, gdp); - cond_resched(); - } - sbi->s_overhead_last = overhead; - smp_wmb(); - sbi->s_blocks_last = ext4_blocks_count(es); - } + if (!test_opt(sb, MINIX_DF)) + overhead = sbi->s_overhead; buf->f_type = EXT4_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; - buf->f_blocks = (ext4_blocks_count(es) - - EXT4_C2B(sbi, sbi->s_overhead_last)); + buf->f_blocks = ext4_blocks_count(es) - EXT4_C2B(sbi, sbi->s_overhead); bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) - percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter); /* prevent underflow in case that few free space is available */ -- GitLab From 6918ff0bf4ba47ce863813fe5010796718219f8f Mon Sep 17 00:00:00 2001 From: Ashish Sangwan Date: Sun, 22 Jul 2012 22:49:08 -0400 Subject: [PATCH 0134/1799] ext4: fix hole punch failure when depth is greater than 0 commit 968dee77220768a5f52cf8b21d0bdb73486febef upstream. Whether to continue removing extents or not is decided by the return value of function ext4_ext_more_to_rm() which checks 2 conditions: a) if there are no more indexes to process. b) if the number of entries are decreased in the header of "depth -1". In case of hole punch, if the last block to be removed is not part of the last extent index than this index will not be deleted, hence the number of valid entries in the extent header of "depth - 1" will remain as it is and ext4_ext_more_to_rm will return 0 although the required blocks are not yet removed. This patch fixes the above mentioned problem as instead of removing the extents from the end of file, it starts removing the blocks from the particular extent from which removing blocks is actually required and continue backward until done. Signed-off-by: Ashish Sangwan Signed-off-by: Namjae Jeon Reviewed-by: Lukas Czerner Signed-off-by: Greg Kroah-Hartman --- fs/ext4/extents.c | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index abcdeab67f52..6b7daa45f6bf 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2503,10 +2503,10 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, { struct super_block *sb = inode->i_sb; int depth = ext_depth(inode); - struct ext4_ext_path *path; + struct ext4_ext_path *path = NULL; ext4_fsblk_t partial_cluster = 0; handle_t *handle; - int i, err; + int i = 0, err; ext_debug("truncate since %u to %u\n", start, end); @@ -2539,8 +2539,12 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, } depth = ext_depth(inode); ex = path[depth].p_ext; - if (!ex) + if (!ex) { + ext4_ext_drop_refs(path); + kfree(path); + path = NULL; goto cont; + } ee_block = le32_to_cpu(ex->ee_block); @@ -2570,8 +2574,6 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, if (err < 0) goto out; } - ext4_ext_drop_refs(path); - kfree(path); } cont: @@ -2580,19 +2582,27 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, * after i_size and walking into the tree depth-wise. */ depth = ext_depth(inode); - path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_NOFS); - if (path == NULL) { - ext4_journal_stop(handle); - return -ENOMEM; - } - path[0].p_depth = depth; - path[0].p_hdr = ext_inode_hdr(inode); + if (path) { + int k = i = depth; + while (--k > 0) + path[k].p_block = + le16_to_cpu(path[k].p_hdr->eh_entries)+1; + } else { + path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), + GFP_NOFS); + if (path == NULL) { + ext4_journal_stop(handle); + return -ENOMEM; + } + path[0].p_depth = depth; + path[0].p_hdr = ext_inode_hdr(inode); - if (ext4_ext_check(inode, path[0].p_hdr, depth)) { - err = -EIO; - goto out; + if (ext4_ext_check(inode, path[0].p_hdr, depth)) { + err = -EIO; + goto out; + } } - i = err = 0; + err = 0; while (i >= 0 && err == 0) { if (i == depth) { @@ -2706,8 +2716,10 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, out: ext4_ext_drop_refs(path); kfree(path); - if (err == -EAGAIN) + if (err == -EAGAIN) { + path = NULL; goto again; + } ext4_journal_stop(handle); return err; -- GitLab From 2dd71727e4bf6787caa56770b99a9102ac9a65f4 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Sun, 22 Jul 2012 23:59:40 -0400 Subject: [PATCH 0135/1799] ext4: don't let i_reserved_meta_blocks go negative commit 97795d2a5b8d3c8dc4365d4bd3404191840453ba upstream. If we hit a condition where we have allocated metadata blocks that were not appropriately reserved, we risk underflow of ei->i_reserved_meta_blocks. In turn, this can throw sbi->s_dirtyclusters_counter significantly out of whack and undermine the nondelalloc fallback logic in ext4_nonda_switch(). Warn if this occurs and set i_allocated_meta_blocks to avoid this problem. This condition is reproduced by xfstests 270 against ext2 with delalloc enabled: Mar 28 08:58:02 localhost kernel: [ 171.526344] EXT4-fs (loop1): delayed block allocation failed for inode 14 at logical offset 64486 with max blocks 64 with error -28 Mar 28 08:58:02 localhost kernel: [ 171.526346] EXT4-fs (loop1): This should not happen!! Data will be lost 270 ultimately fails with an inconsistent filesystem and requires an fsck to repair. The cause of the error is an underflow in ext4_da_update_reserve_space() due to an unreserved meta block allocation. Signed-off-by: Brian Foster Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c77b0bd2c711..b58845ce5bf1 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -279,6 +279,15 @@ void ext4_da_update_reserve_space(struct inode *inode, used = ei->i_reserved_data_blocks; } + if (unlikely(ei->i_allocated_meta_blocks > ei->i_reserved_meta_blocks)) { + ext4_msg(inode->i_sb, KERN_NOTICE, "%s: ino %lu, allocated %d " + "with only %d reserved metadata blocks\n", __func__, + inode->i_ino, ei->i_allocated_meta_blocks, + ei->i_reserved_meta_blocks); + WARN_ON(1); + ei->i_allocated_meta_blocks = ei->i_reserved_meta_blocks; + } + /* Update per-inode reservations */ ei->i_reserved_data_blocks -= used; ei->i_reserved_meta_blocks -= ei->i_allocated_meta_blocks; -- GitLab From c0ce1fd51e122606d555dfd57f5c703b2af12146 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 23 Jul 2012 00:00:20 -0400 Subject: [PATCH 0136/1799] ext4: undo ext4_calc_metadata_amount if we fail to claim space commit 03179fe92318e7934c180d96f12eff2cb36ef7b6 upstream. The function ext4_calc_metadata_amount() has side effects, although it's not obvious from its function name. So if we fail to claim space, regardless of whether we retry to claim the space again, or return an error, we need to undo these side effects. Otherwise we can end up incorrectly calculating the number of metadata blocks needed for the operation, which was responsible for an xfstests failure for test #271 when using an ext2 file system with delalloc enabled. Reported-by: Brian Foster Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index b58845ce5bf1..55a654d86182 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1113,6 +1113,17 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) struct ext4_inode_info *ei = EXT4_I(inode); unsigned int md_needed; int ret; + ext4_lblk_t save_last_lblock; + int save_len; + + /* + * We will charge metadata quota at writeout time; this saves + * us from metadata over-estimation, though we may go over by + * a small amount in the end. Here we just reserve for data. + */ + ret = dquot_reserve_block(inode, EXT4_C2B(sbi, 1)); + if (ret) + return ret; /* * recalculate the amount of metadata blocks to reserve @@ -1121,32 +1132,31 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) */ repeat: spin_lock(&ei->i_block_reservation_lock); + /* + * ext4_calc_metadata_amount() has side effects, which we have + * to be prepared undo if we fail to claim space. + */ + save_len = ei->i_da_metadata_calc_len; + save_last_lblock = ei->i_da_metadata_calc_last_lblock; md_needed = EXT4_NUM_B2C(sbi, ext4_calc_metadata_amount(inode, lblock)); trace_ext4_da_reserve_space(inode, md_needed); - spin_unlock(&ei->i_block_reservation_lock); - /* - * We will charge metadata quota at writeout time; this saves - * us from metadata over-estimation, though we may go over by - * a small amount in the end. Here we just reserve for data. - */ - ret = dquot_reserve_block(inode, EXT4_C2B(sbi, 1)); - if (ret) - return ret; /* * We do still charge estimated metadata to the sb though; * we cannot afford to run out of free blocks. */ if (ext4_claim_free_clusters(sbi, md_needed + 1, 0)) { - dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1)); + ei->i_da_metadata_calc_len = save_len; + ei->i_da_metadata_calc_last_lblock = save_last_lblock; + spin_unlock(&ei->i_block_reservation_lock); if (ext4_should_retry_alloc(inode->i_sb, &retries)) { yield(); goto repeat; } + dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1)); return -ENOSPC; } - spin_lock(&ei->i_block_reservation_lock); ei->i_reserved_data_blocks++; ei->i_reserved_meta_blocks += md_needed; spin_unlock(&ei->i_block_reservation_lock); -- GitLab From aa505bba77961634215eb8bdd8ab9f4bd0c6f1d1 Mon Sep 17 00:00:00 2001 From: Cloud Ren Date: Tue, 3 Jul 2012 16:51:48 +0000 Subject: [PATCH 0137/1799] atl1c: fix issue of transmit queue 0 timed out [ Upstream commit b94e52f62683dc0b00c6d1b58b80929a078c0fd5 ] some people report atl1c could cause system hang with following kernel trace info: --------------------------------------- WARNING: at.../net/sched/sch_generic.c:258 dev_watchdog+0x1db/0x1d0() ... NETDEV WATCHDOG: eth0 (atl1c): transmit queue 0 timed out ... --------------------------------------- This is caused by netif_stop_queue calling when cable Link is down. So remove netif_stop_queue, because link_watch will take it over. Signed-off-by: xiong Cc: stable Signed-off-by: Cloud Ren Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 1ef0c9275dee..65fe6324d817 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -267,7 +267,6 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) dev_warn(&pdev->dev, "stop mac failed\n"); atl1c_set_aspm(hw, false); netif_carrier_off(netdev); - netif_stop_queue(netdev); atl1c_phy_reset(hw); atl1c_phy_init(&adapter->hw); } else { -- GitLab From f7a47ee34686694148f6d34a4576385853c5e33f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 3 Jul 2012 20:55:21 +0000 Subject: [PATCH 0138/1799] netem: add limitation to reordered packets [ Upstream commit 960fb66e520a405dde39ff883f17ff2669c13d85 ] Fix two netem bugs : 1) When a frame was dropped by tfifo_enqueue(), drop counter was incremented twice. 2) When reordering is triggered, we enqueue a packet without checking queue limit. This can OOM pretty fast when this is repeated enough, since skbs are orphaned, no socket limit can help in this situation. Signed-off-by: Eric Dumazet Cc: Mark Gordon Cc: Andreas Terzis Cc: Yuchung Cheng Cc: Hagen Paul Pfeifer Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/sch_netem.c | 42 +++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index ebd22966f748..992acaac5de6 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -329,29 +329,22 @@ static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sche return PSCHED_NS2TICKS(ticks); } -static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) +static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) { struct sk_buff_head *list = &sch->q; psched_time_t tnext = netem_skb_cb(nskb)->time_to_send; - struct sk_buff *skb; - - if (likely(skb_queue_len(list) < sch->limit)) { - skb = skb_peek_tail(list); - /* Optimize for add at tail */ - if (likely(!skb || tnext >= netem_skb_cb(skb)->time_to_send)) - return qdisc_enqueue_tail(nskb, sch); + struct sk_buff *skb = skb_peek_tail(list); - skb_queue_reverse_walk(list, skb) { - if (tnext >= netem_skb_cb(skb)->time_to_send) - break; - } + /* Optimize for add at tail */ + if (likely(!skb || tnext >= netem_skb_cb(skb)->time_to_send)) + return __skb_queue_tail(list, nskb); - __skb_queue_after(list, skb, nskb); - sch->qstats.backlog += qdisc_pkt_len(nskb); - return NET_XMIT_SUCCESS; + skb_queue_reverse_walk(list, skb) { + if (tnext >= netem_skb_cb(skb)->time_to_send) + break; } - return qdisc_reshape_fail(nskb, sch); + __skb_queue_after(list, skb, nskb); } /* @@ -366,7 +359,6 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) /* We don't fill cb now as skb_unshare() may invalidate it */ struct netem_skb_cb *cb; struct sk_buff *skb2; - int ret; int count = 1; /* Random duplication */ @@ -414,6 +406,11 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8); } + if (unlikely(skb_queue_len(&sch->q) >= sch->limit)) + return qdisc_reshape_fail(skb, sch); + + sch->qstats.backlog += qdisc_pkt_len(skb); + cb = netem_skb_cb(skb); if (q->gap == 0 || /* not doing reordering */ q->counter < q->gap - 1 || /* inside last reordering gap */ @@ -445,7 +442,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) cb->time_to_send = now + delay; ++q->counter; - ret = tfifo_enqueue(skb, sch); + tfifo_enqueue(skb, sch); } else { /* * Do re-ordering by putting one out of N packets at the front @@ -455,16 +452,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) q->counter = 0; __skb_queue_head(&sch->q, skb); - sch->qstats.backlog += qdisc_pkt_len(skb); sch->qstats.requeues++; - ret = NET_XMIT_SUCCESS; - } - - if (ret != NET_XMIT_SUCCESS) { - if (net_xmit_drop_count(ret)) { - sch->qstats.drops++; - return ret; - } } return NET_XMIT_SUCCESS; -- GitLab From d680c0462d9f4d96b255853364fb0bcd5c202553 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 5 Jul 2012 11:45:13 +0000 Subject: [PATCH 0139/1799] gianfar: fix potential sk_wmem_alloc imbalance [ Upstream commit 313b037cf054ec908de92fb4c085403ffd7420d4 ] commit db83d136d7f753 (gianfar: Fix missing sock reference when processing TX time stamps) added a potential sk_wmem_alloc imbalance If the new skb has a different truesize than old one, we can get a negative sk_wmem_alloc once new skb is orphaned at TX completion. Now we no longer early orphan skbs in dev_hard_start_xmit(), this probably can lead to fatal bugs. Signed-off-by: Eric Dumazet Tested-by: Paul Gortmaker Cc: Manfred Rudigier Cc: Claudiu Manoil Cc: Jiajun Wu Cc: Andy Fleming Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/freescale/gianfar.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index e7bed5303997..24381e1298e2 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -2065,10 +2065,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } - /* Steal sock reference for processing TX time stamps */ - swap(skb_new->sk, skb->sk); - swap(skb_new->destructor, skb->destructor); - kfree_skb(skb); + if (skb->sk) + skb_set_owner_w(skb_new, skb->sk); + consume_skb(skb); skb = skb_new; } -- GitLab From a5b4b62d8517f12c77f912b8c249e36019d31a0c Mon Sep 17 00:00:00 2001 From: Amir Hanania Date: Mon, 9 Jul 2012 20:47:19 +0000 Subject: [PATCH 0140/1799] net: Fix memory leak - vlan_info struct [ Upstream commit efc73f4bbc238d4f579fb612c04c8e1dd8a82979 ] In driver reload test there is a memory leak. The structure vlan_info was not freed when the driver was removed. It was not released since the nr_vids var is one after last vlan was removed. The nr_vids is one, since vlan zero is added to the interface when the interface is being set, but the vlan zero is not deleted at unregister. Fix - delete vlan zero when we unregister the device. Signed-off-by: Amir Hanania Acked-by: John Fastabend Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/8021q/vlan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index efea35b02e7f..cf4a49c5623c 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -403,6 +403,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, break; case NETDEV_DOWN: + if (dev->features & NETIF_F_HW_VLAN_FILTER) + vlan_vid_del(dev, 0); + /* Put all VLANs for this dev in the down state too. */ for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); -- GitLab From af8ca6ddbb2928d5fb26f0a78710971e1210a299 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 10 Jul 2012 10:04:40 +0000 Subject: [PATCH 0141/1799] bnx2: Fix bug in bnx2_free_tx_skbs(). [ Upstream commit c1f5163de417dab01fa9daaf09a74bbb19303f3c ] In rare cases, bnx2x_free_tx_skbs() can unmap the wrong DMA address when it gets to the last entry of the tx ring. We were not using the proper macro to skip the last entry when advancing the tx index. Reported-by: Zongyun Lai Reviewed-by: Jeffrey Huang Signed-off-by: Michael Chan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/broadcom/bnx2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 8297e2868736..b8ade570759e 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -5372,7 +5372,7 @@ bnx2_free_tx_skbs(struct bnx2 *bp) int k, last; if (skb == NULL) { - j++; + j = NEXT_TX_BD(j); continue; } @@ -5384,8 +5384,8 @@ bnx2_free_tx_skbs(struct bnx2 *bp) tx_buf->skb = NULL; last = tx_buf->nr_frags; - j++; - for (k = 0; k < last; k++, j++) { + j = NEXT_TX_BD(j); + for (k = 0; k < last; k++, j = NEXT_TX_BD(j)) { tx_buf = &txr->tx_buf_ring[TX_RING_IDX(j)]; dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping), -- GitLab From d5eeca5f5c19c472f8f221a81bb27f15a7aeed6c Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 12 Jul 2012 03:39:11 +0000 Subject: [PATCH 0142/1799] sch_sfb: Fix missing NULL check [ Upstream commit 7ac2908e4b2edaec60e9090ddb4d9ceb76c05e7d ] Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=44461 Signed-off-by: Alan Cox Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/sch_sfb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c index d7eea99333e9..c6a5867d35c4 100644 --- a/net/sched/sch_sfb.c +++ b/net/sched/sch_sfb.c @@ -570,6 +570,8 @@ static int sfb_dump(struct Qdisc *sch, struct sk_buff *skb) sch->qstats.backlog = q->qdisc->qstats.backlog; opts = nla_nest_start(skb, TCA_OPTIONS); + if (opts == NULL) + goto nla_put_failure; NLA_PUT(skb, TCA_SFB_PARMS, sizeof(opt), &opt); return nla_nest_end(skb, opts); -- GitLab From 2936d35db07cc3c9e3f2d60ed90f9a72f2031130 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 16 Jul 2012 09:13:51 +0000 Subject: [PATCH 0143/1799] sctp: Fix list corruption resulting from freeing an association on a list [ Upstream commit 2eebc1e188e9e45886ee00662519849339884d6d ] A few days ago Dave Jones reported this oops: [22766.294255] general protection fault: 0000 [#1] PREEMPT SMP [22766.295376] CPU 0 [22766.295384] Modules linked in: [22766.387137] ffffffffa169f292 6b6b6b6b6b6b6b6b ffff880147c03a90 ffff880147c03a74 [22766.387135] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 00000000000 [22766.387136] Process trinity-watchdo (pid: 10896, threadinfo ffff88013e7d2000, [22766.387137] Stack: [22766.387140] ffff880147c03a10 [22766.387140] ffffffffa169f2b6 [22766.387140] ffff88013ed95728 [22766.387143] 0000000000000002 [22766.387143] 0000000000000000 [22766.387143] ffff880003fad062 [22766.387144] ffff88013c120000 [22766.387144] [22766.387145] Call Trace: [22766.387145] [22766.387150] [] ? __sctp_lookup_association+0x62/0xd0 [sctp] [22766.387154] [] __sctp_lookup_association+0x86/0xd0 [sctp] [22766.387157] [] sctp_rcv+0x207/0xbb0 [sctp] [22766.387161] [] ? trace_hardirqs_off_caller+0x28/0xd0 [22766.387163] [] ? nf_hook_slow+0x133/0x210 [22766.387166] [] ? ip_local_deliver_finish+0x4c/0x4c0 [22766.387168] [] ip_local_deliver_finish+0x18d/0x4c0 [22766.387169] [] ? ip_local_deliver_finish+0x4c/0x4c0 [22766.387171] [] ip_local_deliver+0x47/0x80 [22766.387172] [] ip_rcv_finish+0x150/0x680 [22766.387174] [] ip_rcv+0x214/0x320 [22766.387176] [] __netif_receive_skb+0x7b7/0x910 [22766.387178] [] ? __netif_receive_skb+0x11c/0x910 [22766.387180] [] ? put_lock_stats.isra.25+0xe/0x40 [22766.387182] [] netif_receive_skb+0x23/0x1f0 [22766.387183] [] ? dev_gro_receive+0x139/0x440 [22766.387185] [] napi_skb_finish+0x70/0xa0 [22766.387187] [] napi_gro_receive+0xf5/0x130 [22766.387218] [] e1000_receive_skb+0x59/0x70 [e1000e] [22766.387242] [] e1000_clean_rx_irq+0x28b/0x460 [e1000e] [22766.387266] [] e1000e_poll+0x78/0x430 [e1000e] [22766.387268] [] net_rx_action+0x1aa/0x3d0 [22766.387270] [] ? account_system_vtime+0x10f/0x130 [22766.387273] [] __do_softirq+0xe0/0x420 [22766.387275] [] call_softirq+0x1c/0x30 [22766.387278] [] do_softirq+0xd5/0x110 [22766.387279] [] irq_exit+0xd5/0xe0 [22766.387281] [] do_IRQ+0x63/0xd0 [22766.387283] [] common_interrupt+0x6f/0x6f [22766.387283] [22766.387284] [22766.387285] [] ? retint_swapgs+0x13/0x1b [22766.387285] Code: c0 90 5d c3 66 0f 1f 44 00 00 4c 89 c8 5d c3 0f 1f 00 55 48 89 e5 48 83 ec 20 48 89 5d e8 4c 89 65 f0 4c 89 6d f8 66 66 66 66 90 <0f> b7 87 98 00 00 00 48 89 fb 49 89 f5 66 c1 c0 08 66 39 46 02 [22766.387307] [22766.387307] RIP [22766.387311] [] sctp_assoc_is_match+0x19/0x90 [sctp] [22766.387311] RSP [22766.387142] ffffffffa16ab120 [22766.599537] ---[ end trace 3f6dae82e37b17f5 ]--- [22766.601221] Kernel panic - not syncing: Fatal exception in interrupt It appears from his analysis and some staring at the code that this is likely occuring because an association is getting freed while still on the sctp_assoc_hashtable. As a result, we get a gpf when traversing the hashtable while a freed node corrupts part of the list. Nominally I would think that an mibalanced refcount was responsible for this, but I can't seem to find any obvious imbalance. What I did note however was that the two places where we create an association using sctp_primitive_ASSOCIATE (__sctp_connect and sctp_sendmsg), have failure paths which free a newly created association after calling sctp_primitive_ASSOCIATE. sctp_primitive_ASSOCIATE brings us into the sctp_sf_do_prm_asoc path, which issues a SCTP_CMD_NEW_ASOC side effect, which in turn adds a new association to the aforementioned hash table. the sctp command interpreter that process side effects has not way to unwind previously processed commands, so freeing the association from the __sctp_connect or sctp_sendmsg error path would lead to a freed association remaining on this hash table. I've fixed this but modifying sctp_[un]hash_established to use hlist_del_init, which allows us to proerly use hlist_unhashed to check if the node is on a hashlist safely during a delete. That in turn alows us to safely call sctp_unhash_established in the __sctp_connect and sctp_sendmsg error paths before freeing them, regardles of what the associations state is on the hash list. I noted, while I was doing this, that the __sctp_unhash_endpoint was using hlist_unhsashed in a simmilar fashion, but never nullified any removed nodes pointers to make that function work properly, so I fixed that up in a simmilar fashion. I attempted to test this using a virtual guest running the SCTP_RR test from netperf in a loop while running the trinity fuzzer, both in a loop. I wasn't able to recreate the problem prior to this fix, nor was I able to trigger the failure after (neither of which I suppose is suprising). Given the trace above however, I think its likely that this is what we hit. Signed-off-by: Neil Horman Reported-by: davej@redhat.com CC: davej@redhat.com CC: "David S. Miller" CC: Vlad Yasevich CC: Sridhar Samudrala CC: linux-sctp@vger.kernel.org Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/input.c | 7 ++----- net/sctp/socket.c | 12 ++++++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/net/sctp/input.c b/net/sctp/input.c index 80f71af71384..be772c007dba 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -736,15 +736,12 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep) epb = &ep->base; - if (hlist_unhashed(&epb->node)) - return; - epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); head = &sctp_ep_hashtable[epb->hashent]; sctp_write_lock(&head->lock); - __hlist_del(&epb->node); + hlist_del_init(&epb->node); sctp_write_unlock(&head->lock); } @@ -825,7 +822,7 @@ static void __sctp_unhash_established(struct sctp_association *asoc) head = &sctp_assoc_hashtable[epb->hashent]; sctp_write_lock(&head->lock); - __hlist_del(&epb->node); + hlist_del_init(&epb->node); sctp_write_unlock(&head->lock); } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 92ba71dfe080..dba20d6e3247 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1231,8 +1231,14 @@ static int __sctp_connect(struct sock* sk, SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p" " kaddrs: %p err: %d\n", asoc, kaddrs, err); - if (asoc) + if (asoc) { + /* sctp_primitive_ASSOCIATE may have added this association + * To the hash table, try to unhash it, just in case, its a noop + * if it wasn't hashed so we're safe + */ + sctp_unhash_established(asoc); sctp_association_free(asoc); + } return err; } @@ -1942,8 +1948,10 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, goto out_unlock; out_free: - if (new_asoc) + if (new_asoc) { + sctp_unhash_established(asoc); sctp_association_free(asoc); + } out_unlock: sctp_release_sock(sk); -- GitLab From 60d2aa556cc3f00f1276ae363dc6601359180ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sjur=20Br=C3=A6ndeland?= Date: Sun, 15 Jul 2012 10:10:14 +0000 Subject: [PATCH 0144/1799] caif: Fix access to freed pernet memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 96f80d123eff05c3cd4701463786b87952a6c3ac ] unregister_netdevice_notifier() must be called before unregister_pernet_subsys() to avoid accessing already freed pernet memory. This fixes the following oops when doing rmmod: Call Trace: [] caif_device_notify+0x4d/0x5a0 [caif] [] unregister_netdevice_notifier+0xb9/0x100 [] caif_device_exit+0x1c/0x250 [caif] [] sys_delete_module+0x1a4/0x300 [] ? trace_hardirqs_on_caller+0x15d/0x1e0 [] ? trace_hardirqs_on_thunk+0x3a/0x3 [] system_call_fastpath+0x1a/0x1f RIP [] caif_get+0x51/0xb0 [caif] Signed-off-by: Sjur Brændeland Acked-by: "Eric W. Biederman" Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/caif/caif_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index aa6f716524fd..7bf4c21a279c 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -562,9 +562,9 @@ static int __init caif_device_init(void) static void __exit caif_device_exit(void) { - unregister_pernet_subsys(&caif_net_ops); unregister_netdevice_notifier(&caif_device_notifier); dev_remove_pack(&caif_packet_type); + unregister_pernet_subsys(&caif_net_ops); } module_init(caif_device_init); -- GitLab From a080e65186d367508e2b4e68290656ddce493136 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 17 Jul 2012 11:07:47 +0000 Subject: [PATCH 0145/1799] cipso: don't follow a NULL pointer when setsockopt() is called [ Upstream commit 89d7ae34cdda4195809a5a987f697a517a2a3177 ] As reported by Alan Cox, and verified by Lin Ming, when a user attempts to add a CIPSO option to a socket using the CIPSO_V4_TAG_LOCAL tag the kernel dies a terrible death when it attempts to follow a NULL pointer (the skb argument to cipso_v4_validate() is NULL when called via the setsockopt() syscall). This patch fixes this by first checking to ensure that the skb is non-NULL before using it to find the incoming network interface. In the unlikely case where the skb is NULL and the user attempts to add a CIPSO option with the _TAG_LOCAL tag we return an error as this is not something we want to allow. A simple reproducer, kindly supplied by Lin Ming, although you must have the CIPSO DOI #3 configure on the system first or you will be caught early in cipso_v4_validate(): #include #include #include #include #include struct local_tag { char type; char length; char info[4]; }; struct cipso { char type; char length; char doi[4]; struct local_tag local; }; int main(int argc, char **argv) { int sockfd; struct cipso cipso = { .type = IPOPT_CIPSO, .length = sizeof(struct cipso), .local = { .type = 128, .length = sizeof(struct local_tag), }, }; memset(cipso.doi, 0, 4); cipso.doi[3] = 3; sockfd = socket(AF_INET, SOCK_DGRAM, 0); #define SOL_IP 0 setsockopt(sockfd, SOL_IP, IP_OPTIONS, &cipso, sizeof(struct cipso)); return 0; } CC: Lin Ming Reported-by: Alan Cox Signed-off-by: Paul Moore Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/cipso_ipv4.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index c48adc565e92..667c1d4ca984 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1725,8 +1725,10 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option) case CIPSO_V4_TAG_LOCAL: /* This is a non-standard tag that we only allow for * local connections, so if the incoming interface is - * not the loopback device drop the packet. */ - if (!(skb->dev->flags & IFF_LOOPBACK)) { + * not the loopback device drop the packet. Further, + * there is no legitimate reason for setting this from + * userspace so reject it if skb is NULL. */ + if (skb == NULL || !(skb->dev->flags & IFF_LOOPBACK)) { err_offset = opt_iter; goto validate_return_locked; } -- GitLab From 4deb65e759dd2ff7dd5e40bd6d4bf0dad6d88269 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 22 Jul 2012 11:37:20 +0000 Subject: [PATCH 0146/1799] net: Fix references to out-of-scope variables in put_cmsg_compat() [ Upstream commit 818810472b129004c16fc51bf0a570b60776bfb7 ] In net/compat.c::put_cmsg_compat() we may assign 'data' the address of either the 'ctv' or 'cts' local variables inside the 'if (!COMPAT_USE_64BIT_TIME)' branch. Those variables go out of scope at the end of the 'if' statement, so when we use 'data' further down in 'copy_to_user(CMSG_COMPAT_DATA(cm), data, cmlen - sizeof(struct compat_cmsghdr))' there's no telling what it may be refering to - not good. Fix the problem by simply giving 'ctv' and 'cts' function scope. Signed-off-by: Jesper Juhl Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/compat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/compat.c b/net/compat.c index e055708b8ec9..ae6d67ad03b3 100644 --- a/net/compat.c +++ b/net/compat.c @@ -221,6 +221,8 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat { struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; struct compat_cmsghdr cmhdr; + struct compat_timeval ctv; + struct compat_timespec cts[3]; int cmlen; if (cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { @@ -229,8 +231,6 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat } if (!COMPAT_USE_64BIT_TIME) { - struct compat_timeval ctv; - struct compat_timespec cts[3]; if (level == SOL_SOCKET && type == SCM_TIMESTAMP) { struct timeval *tv = (struct timeval *)data; ctv.tv_sec = tv->tv_sec; -- GitLab From f63b1d926016ce39e06a9a39084d205e072541e2 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Mon, 23 Jul 2012 22:55:55 +0200 Subject: [PATCH 0147/1799] r8169: revert "add byte queue limit support". MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 17bcb684f08649a2ab6a7dcd8288332e72d208f1 ] This reverts commit 036dafa28da1e2565a8529de2ae663c37b7a0060. First it appears in bisection, then reverting it solves the usual netdev watchdog problem for different people. I don't have a proper fix yet so get rid of it. Bisected-and-reported-by: Alex Villacís Lasso Signed-off-by: Francois Romieu Cc: Josh Boyer Cc: Hayes Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/realtek/r8169.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 161e04517476..a73bbe7fb63a 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -5000,7 +5000,6 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp) { rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC); tp->cur_tx = tp->dirty_tx = 0; - netdev_reset_queue(tp->dev); } static void rtl_reset_work(struct rtl8169_private *tp) @@ -5155,8 +5154,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, txd->opts2 = cpu_to_le32(opts[1]); - netdev_sent_queue(dev, skb->len); - skb_tx_timestamp(skb); wmb(); @@ -5253,16 +5250,9 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); } -struct rtl_txc { - int packets; - int bytes; -}; - static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) { - struct rtl8169_stats *tx_stats = &tp->tx_stats; unsigned int dirty_tx, tx_left; - struct rtl_txc txc = { 0, 0 }; dirty_tx = tp->dirty_tx; smp_rmb(); @@ -5281,24 +5271,17 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, tp->TxDescArray + entry); if (status & LastFrag) { - struct sk_buff *skb = tx_skb->skb; - - txc.packets++; - txc.bytes += skb->len; - dev_kfree_skb(skb); + u64_stats_update_begin(&tp->tx_stats.syncp); + tp->tx_stats.packets++; + tp->tx_stats.bytes += tx_skb->skb->len; + u64_stats_update_end(&tp->tx_stats.syncp); + dev_kfree_skb(tx_skb->skb); tx_skb->skb = NULL; } dirty_tx++; tx_left--; } - u64_stats_update_begin(&tx_stats->syncp); - tx_stats->packets += txc.packets; - tx_stats->bytes += txc.bytes; - u64_stats_update_end(&tx_stats->syncp); - - netdev_completed_queue(dev, txc.packets, txc.bytes); - if (tp->dirty_tx != dirty_tx) { tp->dirty_tx = dirty_tx; /* Sync with rtl8169_start_xmit: -- GitLab From 2138dede8c23f5646c81381c71aac37e67b491b0 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Jul 2012 02:42:14 +0000 Subject: [PATCH 0148/1799] caif: fix NULL pointer check [ Upstream commit c66b9b7d365444b433307ebb18734757cb668a02 ] Reported-by: Resolves-bug: http://bugzilla.kernel.org/show_bug?44441 Signed-off-by: Alan Cox Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/caif/caif_serial.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index 8a3054b84812..5de74e762021 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -325,6 +325,9 @@ static int ldisc_open(struct tty_struct *tty) sprintf(name, "cf%s", tty->name); dev = alloc_netdev(sizeof(*ser), name, caifdev_setup); + if (!dev) + return -ENOMEM; + ser = netdev_priv(dev); ser->tty = tty_kref_get(tty); ser->dev = dev; -- GitLab From 1a8634186c17426f79c3bfcbc4fab75aa0f53c3b Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Jul 2012 08:16:25 +0000 Subject: [PATCH 0149/1799] wanmain: comparing array with NULL [ Upstream commit 8b72ff6484fe303e01498b58621810a114f3cf09 ] gcc really should warn about these ! Signed-off-by: Alan Cox Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/wanrouter/wanmain.c | 51 +++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 788a12c1eb5d..2ab785064b7e 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -602,36 +602,31 @@ static int wanrouter_device_new_if(struct wan_device *wandev, * successfully, add it to the interface list. */ - if (dev->name == NULL) { - err = -EINVAL; - } else { +#ifdef WANDEBUG + printk(KERN_INFO "%s: registering interface %s...\n", + wanrouter_modname, dev->name); +#endif - #ifdef WANDEBUG - printk(KERN_INFO "%s: registering interface %s...\n", - wanrouter_modname, dev->name); - #endif - - err = register_netdev(dev); - if (!err) { - struct net_device *slave = NULL; - unsigned long smp_flags=0; - - lock_adapter_irq(&wandev->lock, &smp_flags); - - if (wandev->dev == NULL) { - wandev->dev = dev; - } else { - for (slave=wandev->dev; - DEV_TO_SLAVE(slave); - slave = DEV_TO_SLAVE(slave)) - DEV_TO_SLAVE(slave) = dev; - } - ++wandev->ndev; - - unlock_adapter_irq(&wandev->lock, &smp_flags); - err = 0; /* done !!! */ - goto out; + err = register_netdev(dev); + if (!err) { + struct net_device *slave = NULL; + unsigned long smp_flags=0; + + lock_adapter_irq(&wandev->lock, &smp_flags); + + if (wandev->dev == NULL) { + wandev->dev = dev; + } else { + for (slave=wandev->dev; + DEV_TO_SLAVE(slave); + slave = DEV_TO_SLAVE(slave)) + DEV_TO_SLAVE(slave) = dev; } + ++wandev->ndev; + + unlock_adapter_irq(&wandev->lock, &smp_flags); + err = 0; /* done !!! */ + goto out; } if (wandev->del_if) wandev->del_if(wandev, dev); -- GitLab From ac6b310c5f5ecd6154e07069c6b6b67b7e768d8b Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Thu, 26 Jul 2012 22:52:21 +0000 Subject: [PATCH 0150/1799] tcp: Add TCP_USER_TIMEOUT negative value check [ Upstream commit 42493570100b91ef663c4c6f0c0fdab238f9d3c2 ] TCP_USER_TIMEOUT is a TCP level socket option that takes an unsigned int. But patch "tcp: Add TCP_USER_TIMEOUT socket option"(dca43c75) didn't check the negative values. If a user assign -1 to it, the socket will set successfully and wait for 4294967295 miliseconds. This patch add a negative value check to avoid this issue. Signed-off-by: Hangbin Liu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 6589e11d57b6..d6feb1ef4f2a 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2408,7 +2408,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level, /* Cap the max timeout in ms TCP will retry/retrans * before giving up and aborting (ETIMEDOUT) a connection. */ - icsk->icsk_user_timeout = msecs_to_jiffies(val); + if (val < 0) + err = -EINVAL; + else + icsk->icsk_user_timeout = msecs_to_jiffies(val); break; default: err = -ENOPROTOOPT; -- GitLab From e5481652427aa25fc74b45d755ff678df33601c1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 27 Jul 2012 01:46:51 +0000 Subject: [PATCH 0151/1799] USB: kaweth.c: use GFP_ATOMIC under spin_lock [ Upstream commit e4c7f259c5be99dcfc3d98f913590663b0305bf8 ] The problem is that we call this with a spin lock held. The call tree is: kaweth_start_xmit() holds kaweth->device_lock. -> kaweth_async_set_rx_mode() -> kaweth_control() -> kaweth_internal_control_msg() The kaweth_internal_control_msg() function is only called from kaweth_control() which used GFP_ATOMIC for its allocations. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/kaweth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index df2a2cf35a99..7a6ccd6c3b46 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -1302,7 +1302,7 @@ static int kaweth_internal_control_msg(struct usb_device *usb_dev, int retv; int length = 0; /* shut up GCC */ - urb = usb_alloc_urb(0, GFP_NOIO); + urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; -- GitLab From 202a3667cfc09edca2338a1fb5d6ffb0dddc9bcc Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Fri, 27 Jul 2012 02:58:22 +0000 Subject: [PATCH 0152/1799] net: fix rtnetlink IFF_PROMISC and IFF_ALLMULTI handling [ Upstream commit b1beb681cba5358f62e6187340660ade226a5fcc ] When device flags are set using rtnetlink, IFF_PROMISC and IFF_ALLMULTI flags are handled specially. Function dev_change_flags sets IFF_PROMISC and IFF_ALLMULTI bits in dev->gflags according to the passed value but do_setlink passes a result of rtnl_dev_combine_flags which takes those bits from dev->flags. This can be easily trigerred by doing: tcpdump -i eth0 & ip l s up eth0 ip sets IFF_UP flag in ifi_flags and ifi_change, which is combined with IFF_PROMISC by rtnl_dev_combine_flags, causing __dev_change_flags to set IFF_PROMISC in gflags. Reported-by: Max Matveev Signed-off-by: Jiri Benc Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/rtnetlink.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 90430b776ece..b8052bab69ca 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -671,6 +671,12 @@ static void set_operstate(struct net_device *dev, unsigned char transition) } } +static unsigned int rtnl_dev_get_flags(const struct net_device *dev) +{ + return (dev->flags & ~(IFF_PROMISC | IFF_ALLMULTI)) | + (dev->gflags & (IFF_PROMISC | IFF_ALLMULTI)); +} + static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, const struct ifinfomsg *ifm) { @@ -679,7 +685,7 @@ static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ if (ifm->ifi_change) flags = (flags & ifm->ifi_change) | - (dev->flags & ~ifm->ifi_change); + (rtnl_dev_get_flags(dev) & ~ifm->ifi_change); return flags; } -- GitLab From 2ce42ec4ef551b08d2e5d26775d838ac640f82ad Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Fri, 27 Jul 2012 10:38:50 +0000 Subject: [PATCH 0153/1799] tcp: perform DMA to userspace only if there is a task waiting for it [ Upstream commit 59ea33a68a9083ac98515e4861c00e71efdc49a1 ] Back in 2006, commit 1a2449a87b ("[I/OAT]: TCP recv offload to I/OAT") added support for receive offloading to IOAT dma engine if available. The code in tcp_rcv_established() tries to perform early DMA copy if applicable. It however does so without checking whether the userspace task is actually expecting the data in the buffer. This is not a problem under normal circumstances, but there is a corner case where this doesn't work -- and that's when MSG_TRUNC flag to recvmsg() is used. If the IOAT dma engine is not used, the code properly checks whether there is a valid ucopy.task and the socket is owned by userspace, but misses the check in the dmaengine case. This problem can be observed in real trivially -- for example 'tbench' is a good reproducer, as it makes a heavy use of MSG_TRUNC. On systems utilizing IOAT, you will soon find tbench waiting indefinitely in sk_wait_data(), as they have been already early-copied in tcp_rcv_established() using dma engine. This patch introduces the same check we are performing in the simple iovec copy case to the IOAT case as well. It fixes the indefinite recvmsg(MSG_TRUNC) hangs. Signed-off-by: Jiri Kosina Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_input.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 257b61789eeb..56a9c8d0bef1 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5441,7 +5441,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, if (tp->copied_seq == tp->rcv_nxt && len - tcp_header_len <= tp->ucopy.len) { #ifdef CONFIG_NET_DMA - if (tcp_dma_try_early_copy(sk, skb, tcp_header_len)) { + if (tp->ucopy.task == current && + sock_owned_by_user(sk) && + tcp_dma_try_early_copy(sk, skb, tcp_header_len)) { copied_early = 1; eaten = 1; } -- GitLab From 143d9963df6580491f9a5c38c9d4883786f78123 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Sun, 29 Jul 2012 19:45:14 +0000 Subject: [PATCH 0154/1799] net/tun: fix ioctl() based info leaks [ Upstream commits a117dacde0288f3ec60b6e5bcedae8fa37ee0dfc and 8bbb181308bc348e02bfdbebdedd4e4ec9d452ce ] The tun module leaks up to 36 bytes of memory by not fully initializing a structure located on the stack that gets copied to user memory by the TUNGETIFF and SIOCGIFHWADDR ioctl()s. Signed-off-by: Mathias Krause Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/tun.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index a06ad55d949c..8f13420dd31a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1255,10 +1255,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, int vnet_hdr_sz; int ret; - if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) + if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) { if (copy_from_user(&ifr, argp, ifreq_len)) return -EFAULT; - + } else { + memset(&ifr, 0, sizeof(ifr)); + } if (cmd == TUNGETFEATURES) { /* Currently this just means: "what IFF flags are valid?". * This is needed because we never checked for invalid flags on -- GitLab From 6091e5bc36cc2d74b2c5ab1ae2dcf32cf82e242f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 30 Jul 2012 16:06:42 +0100 Subject: [PATCH 0155/1799] USB: echi-dbgp: increase the controller wait time to come out of halt. commit f96a4216e85050c0a9d41a41ecb0ae9d8e39b509 upstream. The default 10 microsecond delay for the controller to come out of halt in dbgp_ehci_startup is too short, so increase it to 1 millisecond. This is based on emperical testing on various USB debug ports on modern machines such as a Lenovo X220i and an Ivybridge development platform that needed to wait ~450-950 microseconds. Signed-off-by: Colin Ian King Signed-off-by: Jason Wessel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/early/ehci-dbgp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 1fc8f1249806..347bb058e1ee 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -450,7 +450,7 @@ static int dbgp_ehci_startup(void) writel(FLAG_CF, &ehci_regs->configured_flag); /* Wait until the controller is no longer halted */ - loop = 10; + loop = 1000; do { status = readl(&ehci_regs->status); if (!(status & STS_HALT)) -- GitLab From 6fc6d9aea32a459f96ac8678f3e25170a6a8cfa9 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 1 Aug 2012 10:16:53 +0200 Subject: [PATCH 0156/1799] ALSA: snd-usb: fix clock source validity index commit aff252a848ce21b431ba822de3dab9c4c94571cb upstream. uac_clock_source_is_valid() uses the control selector value to access the bmControls bitmap of the clock source unit. This is wrong, as control selector values start from 1, while the bitmap uses all available bits. In other words, "Clock Validity Control" is stored in D3..2, not D5..4 of the clock selector unit's bmControls. Signed-off-by: Daniel Mack Reported-by: Andreas Koch Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/clock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 379baad3d5ad..5e634a2eb282 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -111,7 +111,8 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id) return 0; /* If a clock source can't tell us whether it's valid, we assume it is */ - if (!uac2_control_is_readable(cs_desc->bmControls, UAC2_CS_CONTROL_CLOCK_VALID)) + if (!uac2_control_is_readable(cs_desc->bmControls, + UAC2_CS_CONTROL_CLOCK_VALID - 1)) return 1; err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, -- GitLab From e25824fa92d90e667b4285eddf7da11c541691a0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 23 Jul 2012 11:35:55 +0200 Subject: [PATCH 0157/1799] ALSA: mpu401: Fix missing initialization of irq field commit bc733d495267a23ef8660220d696c6e549ce30b3 upstream. The irq field of struct snd_mpu401 is supposed to be initialized to -1. Since it's set to zero as of now, a probing error before the irq installation results in a kernel warning "Trying to free already-free IRQ 0". Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=44821 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/drivers/mpu401/mpu401_uart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index 1cff331a228e..4608c2ca43f8 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -554,6 +554,7 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, spin_lock_init(&mpu->output_lock); spin_lock_init(&mpu->timer_lock); mpu->hardware = hardware; + mpu->irq = -1; if (! (info_flags & MPU401_INFO_INTEGRATED)) { int res_size = hardware == MPU401_HW_PC98II ? 4 : 2; mpu->res = request_region(port, res_size, "MPU401 UART"); -- GitLab From ac1d1b446e2e93305611126caa2252c8243f087f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 25 Jul 2012 13:54:55 +0200 Subject: [PATCH 0158/1799] ALSA: hda - Fix invalid D3 of headphone DAC on VT202x codecs commit 6162552b0de6ba80937c3dd53e084967851cd199 upstream. We've got a bug report about the silent output from the headphone on a mobo with VT2021, and spotted out that this was because of the wrong D3 state on the DAC for the headphone output. The bug is triggered by the incomplete check for this DAC in set_widgets_power_state_vt1718S(). It checks only the connectivity of the primary output (0x27) but doesn't consider the path from the headphone pin (0x28). Now this patch fixes the problem by checking both pins for DAC 0x0b. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_via.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 06214fdc9486..3998d09bf241 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -3233,7 +3233,7 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec) { struct via_spec *spec = codec->spec; int imux_is_smixer; - unsigned int parm; + unsigned int parm, parm2; /* MUX6 (1eh) = stereo mixer */ imux_is_smixer = snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5; @@ -3256,7 +3256,7 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec) parm = AC_PWRST_D3; set_pin_power_state(codec, 0x27, &parm); update_power_state(codec, 0x1a, parm); - update_power_state(codec, 0xb, parm); + parm2 = parm; /* for pin 0x0b */ /* PW2 (26h), AOW2 (ah) */ parm = AC_PWRST_D3; @@ -3271,6 +3271,9 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec) if (!spec->hp_independent_mode) /* check for redirected HP */ set_pin_power_state(codec, 0x28, &parm); update_power_state(codec, 0x8, parm); + if (!spec->hp_independent_mode && parm2 != AC_PWRST_D3) + parm = parm2; + update_power_state(codec, 0xb, parm); /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */ update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm); -- GitLab From 09f7d3b6fa3511eb0975fb40cda48f032942f49d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 26 Jul 2012 08:17:20 +0200 Subject: [PATCH 0159/1799] ALSA: hda - Fix mute-LED GPIO setup for HP Mini 210 commit a3e199732b8e2b272e82cc1ccc49c35239ed6c5a upstream. BIOS on HP Mini 210 doesn't provide the proper "HP_Mute_LED" DMI string, thus the driver doesn't initialize the GPIO, too. In the earlier kernel, the driver falls back to GPIO1, but since 3.3 we've stopped this due to other wrongly advertised machines. For fixing this particular case, add a new model type to specify the default polarity explicitly so that the fallback to GPIO1 is handled. Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=772923 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_sigmatel.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 7494fbc1f265..dd83712fd74e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -100,6 +100,7 @@ enum { STAC_92HD83XXX_HP_cNB11_INTQUAD, STAC_HP_DV7_4000, STAC_HP_ZEPHYR, + STAC_92HD83XXX_HP_LED, STAC_92HD83XXX_MODELS }; @@ -1672,6 +1673,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", [STAC_HP_DV7_4000] = "hp-dv7-4000", [STAC_HP_ZEPHYR] = "hp-zephyr", + [STAC_92HD83XXX_HP_LED] = "hp-led", }; static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { @@ -1726,6 +1728,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561, "HP", STAC_HP_ZEPHYR), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660, + "HP Mini", STAC_92HD83XXX_HP_LED), {} /* terminator */ }; @@ -5528,6 +5532,7 @@ static void stac92hd8x_fill_auto_spec(struct hda_codec *codec) static int patch_stac92hd83xxx(struct hda_codec *codec) { struct sigmatel_spec *spec; + int default_polarity = -1; /* no default cfg */ int err; spec = kzalloc(sizeof(*spec), GFP_KERNEL); @@ -5576,9 +5581,12 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) case STAC_HP_ZEPHYR: spec->init = stac92hd83xxx_hp_zephyr_init; break; + case STAC_92HD83XXX_HP_LED: + default_polarity = 1; + break; } - if (find_mute_led_cfg(codec, -1/*no default cfg*/)) + if (find_mute_led_cfg(codec, default_polarity)) snd_printd("mute LED gpio %d polarity %d\n", spec->gpio_led, spec->gpio_led_polarity); -- GitLab From 22e0422852d3aa14ad9f1793b8d7cb9e74b81608 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 31 Jul 2012 10:16:59 +0200 Subject: [PATCH 0160/1799] ALSA: hda - Fix polarity of mute LED on HP Mini 210 commit ff8a1e274cbc11da6b57849f925b895a212b56c9 upstream. The commit a3e199732b made the LED working again on HP Mini 210 but with a wrong polarity. This patch fixes the polarity for this machine, and also introduce a new model string "hp-inv-led". Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=772923 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_sigmatel.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index dd83712fd74e..cf41d9219a60 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -101,6 +101,7 @@ enum { STAC_HP_DV7_4000, STAC_HP_ZEPHYR, STAC_92HD83XXX_HP_LED, + STAC_92HD83XXX_HP_INV_LED, STAC_92HD83XXX_MODELS }; @@ -1674,6 +1675,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { [STAC_HP_DV7_4000] = "hp-dv7-4000", [STAC_HP_ZEPHYR] = "hp-zephyr", [STAC_92HD83XXX_HP_LED] = "hp-led", + [STAC_92HD83XXX_HP_INV_LED] = "hp-inv-led", }; static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { @@ -5582,6 +5584,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) spec->init = stac92hd83xxx_hp_zephyr_init; break; case STAC_92HD83XXX_HP_LED: + default_polarity = 0; + break; + case STAC_92HD83XXX_HP_INV_LED: default_polarity = 1; break; } -- GitLab From 2a69bac35f3667f380d83ca5ed5b880ee7133154 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 31 Jul 2012 10:40:05 +0200 Subject: [PATCH 0161/1799] ALSA: hda - Fix mute-LED GPIO initialization for IDT codecs commit 1f43f6c1bc8d740e75b4177eb29110858bb5fea2 upstream. The IDT codecs initializes the GPIO setup for mute LEDs via snd_hda_sync_vmaster_hook(). This works in most cases except for the very first call, which is called before PCM and control creations. Thus before Master switch is set manually via alsactl, the mute LED may show the wrong state, depending on the polarity. Now it's fixed by calling the LED-status update function manually when no vmaster is set yet. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_sigmatel.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index cf41d9219a60..fd5331244171 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4437,7 +4437,13 @@ static int stac92xx_init(struct hda_codec *codec) snd_hda_jack_report_sync(codec); /* sync mute LED */ - snd_hda_sync_vmaster_hook(&spec->vmaster_mute); + if (spec->gpio_led) { + if (spec->vmaster_mute.hook) + snd_hda_sync_vmaster_hook(&spec->vmaster_mute); + else /* the very first init call doesn't have vmaster yet */ + stac92xx_update_led_status(codec, false); + } + if (spec->dac_list) stac92xx_power_down(codec); return 0; -- GitLab From 7dcb3c5de76a8516e7f2391dfbab2727f69ed010 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 2 Aug 2012 09:04:39 +0200 Subject: [PATCH 0162/1799] ALSA: hda - Support dock on Lenovo Thinkpad T530 with ALC269VC commit 707fba3fa76a4c8855552f5d4c1a12430c09bce8 upstream. Lenovo Thinkpad T530 with ALC269VC codec has a dock port but BIOS doesn't set up the pins properly. Enable the pins as well as on Thinkpad X230 Tablet. Reported-and-tested-by: Mario 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 88ccc0f62b1c..62e1627acda2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6156,6 +6156,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), -- GitLab From 9966af8a7ac83cdc9aa5a054e843fdecc6689aa0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 30 Jul 2012 18:24:19 +0100 Subject: [PATCH 0163/1799] ASoC: wm8962: Allow VMID time to fully ramp commit 9d40e5582c9c4cfb6977ba2a0ca9c2ed82c56f21 upstream. Required for reliable power up from cold. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8962.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 08850f8fdb58..96f6f9faa821 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2488,6 +2488,9 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec, /* VMID 2*250k */ snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, WM8962_VMID_SEL_MASK, 0x100); + + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) + msleep(100); break; case SND_SOC_BIAS_OFF: -- GitLab From 8f32469c980654a17e935dae06a3557b488910a4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 22 Jun 2012 17:21:17 +0100 Subject: [PATCH 0164/1799] ASoC: wm8994: Ensure there are enough BCLKs for four channels commit b8edf3e5522735c8ce78b81845f7a1a2d4a08626 upstream. Otherwise if someone tries to use all four channels on AIF1 with the device in master mode we won't be able to clock out all the data. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8994.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index f351b933f5c4..4c471a54893e 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2695,7 +2695,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - bclk_rate = params_rate(params) * 2; + bclk_rate = params_rate(params) * 4; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: bclk_rate *= 16; -- GitLab From 727cda365f7007f75a402f38ecd8bbf88a874e8f Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Sat, 28 Jul 2012 00:20:34 +0200 Subject: [PATCH 0165/1799] m68k: Make sys_atomic_cmpxchg_32 work on classic m68k commit 9e2760d18b3cf179534bbc27692c84879c61b97c upstream. User space access must always go through uaccess accessors, since on classic m68k user space and kernel space are completely separate. Signed-off-by: Andreas Schwab Tested-by: Thorsten Glaser Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- arch/m68k/kernel/sys_m68k.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index 8623f8dc16f8..9a5932ec3689 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -479,9 +479,13 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, goto bad_access; } - mem_value = *mem; + /* + * No need to check for EFAULT; we know that the page is + * present and writable. + */ + __get_user(mem_value, mem); if (mem_value == oldval) - *mem = newval; + __put_user(newval, mem); pte_unmap_unlock(pte, ptl); up_read(&mm->mmap_sem); -- GitLab From ef2e080c19599e3d0844f3bc599ee5dd627fc850 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Thu, 19 Apr 2012 00:53:36 +0200 Subject: [PATCH 0166/1799] m68k: Correct the Atari ALLOWINT definition commit c663600584a596b5e66258cc10716fb781a5c2c9 upstream. Booting a 3.2, 3.3, or 3.4-rc4 kernel on an Atari using the `nfeth' ethernet device triggers a WARN_ONCE() in generic irq handling code on the first irq for that device: WARNING: at kernel/irq/handle.c:146 handle_irq_event_percpu+0x134/0x142() irq 3 handler nfeth_interrupt+0x0/0x194 enabled interrupts Modules linked in: Call Trace: [<000299b2>] warn_slowpath_common+0x48/0x6a [<000299c0>] warn_slowpath_common+0x56/0x6a [<00029a4c>] warn_slowpath_fmt+0x2a/0x32 [<0005b34c>] handle_irq_event_percpu+0x134/0x142 [<0005b34c>] handle_irq_event_percpu+0x134/0x142 [<0000a584>] nfeth_interrupt+0x0/0x194 [<001ba0a8>] schedule_preempt_disabled+0x0/0xc [<0005b37a>] handle_irq_event+0x20/0x2c [<0005add4>] generic_handle_irq+0x2c/0x3a [<00002ab6>] do_IRQ+0x20/0x32 [<0000289e>] auto_irqhandler_fixup+0x4/0x6 [<00003144>] cpu_idle+0x22/0x2e [<001b8a78>] printk+0x0/0x18 [<0024d112>] start_kernel+0x37a/0x386 [<0003021d>] __do_proc_dointvec+0xb1/0x366 [<0003021d>] __do_proc_dointvec+0xb1/0x366 [<0024c31e>] _sinittext+0x31e/0x9c0 After invoking the irq's handler the kernel sees !irqs_disabled() and concludes that the handler erroneously enabled interrupts. However, debugging shows that !irqs_disabled() is true even before the handler is invoked, which indicates a problem in the platform code rather than the specific driver. The warning does not occur in 3.1 or older kernels. It turns out that the ALLOWINT definition for Atari is incorrect. The Atari definition of ALLOWINT is ~0x400, the stated purpose of that is to avoid taking HSYNC interrupts. irqs_disabled() returns true if the 3-bit ipl & 4 is non-zero. The nfeth interrupt runs at ipl 3 (it's autovector 3), but 3 & 4 is zero so irqs_disabled() is false, and the warning above is generated. When interrupts are explicitly disabled, ipl is set to 7. When they are enabled, ipl is masked with ALLOWINT. On Atari this will result in ipl = 3, which blocks interrupts at ipl 3 and below. So how come nfeth interrupts at ipl 3 are received at all? That's because ipl is reset to 2 by Atari-specific code in default_idle(), again with the stated purpose of blocking HSYNC interrupts. This discrepancy means that ipl 3 can remain blocked for longer than intended. Both default_idle() and falcon_hblhandler() identify HSYNC with ipl 2, and the "Atari ST/.../F030 Hardware Register Listing" agrees, but ALLOWINT is defined as if HSYNC was ipl 3. [As an experiment I modified default_idle() to reset ipl to 3, and as expected that resulted in all nfeth interrupts being blocked.] The fix is simple: define ALLOWINT as ~0x500 instead. This makes arch_local_irq_enable() consistent with default_idle(), and prevents the !irqs_disabled() problems for ipl 3 interrupts. Tested on Atari running in an Aranym VM. Signed-off-by: Mikael Pettersson Tested-by: Michael Schmitz Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- arch/m68k/include/asm/entry.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/m68k/include/asm/entry.h b/arch/m68k/include/asm/entry.h index 622138dc7288..34c25209b66e 100644 --- a/arch/m68k/include/asm/entry.h +++ b/arch/m68k/include/asm/entry.h @@ -33,8 +33,8 @@ /* the following macro is used when enabling interrupts */ #if defined(MACH_ATARI_ONLY) - /* block out HSYNC on the atari */ -#define ALLOWINT (~0x400) + /* block out HSYNC = ipl 2 on the atari */ +#define ALLOWINT (~0x500) #define MAX_NOINT_IPL 3 #else /* portable version */ -- GitLab From d48c1ba2979634ecbbe344a8bd65035f32777f1b Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Fri, 20 Jul 2012 11:53:29 -0700 Subject: [PATCH 0167/1799] futex: Test for pi_mutex on fault in futex_wait_requeue_pi() commit b6070a8d9853eda010a549fa9a09eb8d7269b929 upstream. If fixup_pi_state_owner() faults, pi_mutex may be NULL. Test for pi_mutex != NULL before testing the owner against current and possibly unlocking it. Signed-off-by: Darren Hart Cc: Dave Jones Cc: Dan Carpenter Link: http://lkml.kernel.org/r/dc59890338fc413606f04e5c5b131530734dae3d.1342809673.git.dvhart@linux.intel.com Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/futex.c b/kernel/futex.c index e2b0fb9a0b3b..05018bfe21a7 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -2370,7 +2370,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, * fault, unlock the rt_mutex and return the fault to userspace. */ if (ret == -EFAULT) { - if (rt_mutex_owner(pi_mutex) == current) + if (pi_mutex && rt_mutex_owner(pi_mutex) == current) rt_mutex_unlock(pi_mutex); } else if (ret == -EINTR) { /* -- GitLab From 47b6ff731a701d898c732e2f2dd67c5178fc0960 Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Fri, 20 Jul 2012 11:53:30 -0700 Subject: [PATCH 0168/1799] futex: Fix bug in WARN_ON for NULL q.pi_state commit f27071cb7fe3e1d37a9dbe6c0dfc5395cd40fa43 upstream. The WARN_ON in futex_wait_requeue_pi() for a NULL q.pi_state was testing the address (&q.pi_state) of the pointer instead of the value (q.pi_state) of the pointer. Correct it accordingly. Signed-off-by: Darren Hart Cc: Dave Jones Link: http://lkml.kernel.org/r/1c85d97f6e5f79ec389a4ead3e367363c74bd09a.1342809673.git.dvhart@linux.intel.com Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/futex.c b/kernel/futex.c index 05018bfe21a7..5551adaf7cdf 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -2343,7 +2343,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, * signal. futex_unlock_pi() will not destroy the lock_ptr nor * the pi_state. */ - WARN_ON(!&q.pi_state); + WARN_ON(!q.pi_state); pi_mutex = &q.pi_state->pi_mutex; ret = rt_mutex_finish_proxy_lock(pi_mutex, to, &rt_waiter, 1); debug_rt_mutex_free_waiter(&rt_waiter); -- GitLab From b3f9576e98e0dfb4f9be87618da4c5f6e8640ee0 Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Fri, 20 Jul 2012 11:53:31 -0700 Subject: [PATCH 0169/1799] futex: Forbid uaddr == uaddr2 in futex_wait_requeue_pi() commit 6f7b0a2a5c0fb03be7c25bd1745baa50582348ef upstream. If uaddr == uaddr2, then we have broken the rule of only requeueing from a non-pi futex to a pi futex with this call. If we attempt this, as the trinity test suite manages to do, we miss early wakeups as q.key is equal to key2 (because they are the same uaddr). We will then attempt to dereference the pi_mutex (which would exist had the futex_q been properly requeued to a pi futex) and trigger a NULL pointer dereference. Signed-off-by: Darren Hart Cc: Dave Jones Link: http://lkml.kernel.org/r/ad82bfe7f7d130247fbe2b5b4275654807774227.1342809673.git.dvhart@linux.intel.com Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index 5551adaf7cdf..3717e7b306e0 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -2231,11 +2231,11 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb, * @uaddr2: the pi futex we will take prior to returning to user-space * * The caller will wait on uaddr and will be requeued by futex_requeue() to - * uaddr2 which must be PI aware. Normal wakeup will wake on uaddr2 and - * complete the acquisition of the rt_mutex prior to returning to userspace. - * This ensures the rt_mutex maintains an owner when it has waiters; without - * one, the pi logic wouldn't know which task to boost/deboost, if there was a - * need to. + * uaddr2 which must be PI aware and unique from uaddr. Normal wakeup will wake + * on uaddr2 and complete the acquisition of the rt_mutex prior to returning to + * userspace. This ensures the rt_mutex maintains an owner when it has waiters; + * without one, the pi logic would not know which task to boost/deboost, if + * there was a need to. * * We call schedule in futex_wait_queue_me() when we enqueue and return there * via the following: @@ -2272,6 +2272,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, struct futex_q q = futex_q_init; int res, ret; + if (uaddr == uaddr2) + return -EINVAL; + if (!bitset) return -EINVAL; -- GitLab From 8067fa23092f2c4e18c29c90f7d5bb765dbf8954 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 9 Aug 2012 08:32:11 -0700 Subject: [PATCH 0170/1799] Linux 3.4.8 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e17a98c3ea53..a3c0c43a71d4 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 7 +SUBLEVEL = 8 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 5eaac83b7362a1944afde7e867e53c7135e36d68 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Thu, 26 Jul 2012 10:55:26 -0700 Subject: [PATCH 0171/1799] Redefine ATOMIC_INIT and ATOMIC64_INIT to drop the casts commit a119365586b0130dfea06457f584953e0ff6481d upstream. The following build error occured during a ia64 build with swap-over-NFS patches applied. net/core/sock.c:274:36: error: initializer element is not constant net/core/sock.c:274:36: error: (near initialization for 'memalloc_socks') net/core/sock.c:274:36: error: initializer element is not constant This is identical to a parisc build error. Fengguang Wu, Mel Gorman and James Bottomley did all the legwork to track the root cause of the problem. This fix and entire commit log is shamelessly copied from them with one extra detail to change a dubious runtime use of ATOMIC_INIT() to atomic_set() in drivers/char/mspec.c Dave Anglin says: > Here is the line in sock.i: > > struct static_key memalloc_socks = ((struct static_key) { .enabled = > ((atomic_t) { (0) }) }); The above line contains two compound literals. It also uses a designated initializer to initialize the field enabled. A compound literal is not a constant expression. The location of the above statement isn't fully clear, but if a compound literal occurs outside the body of a function, the initializer list must consist of constant expressions. Signed-off-by: Tony Luck Signed-off-by: Greg Kroah-Hartman --- arch/ia64/include/asm/atomic.h | 4 ++-- drivers/char/mspec.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h index 7d9116600a36..6e6fe1839f5d 100644 --- a/arch/ia64/include/asm/atomic.h +++ b/arch/ia64/include/asm/atomic.h @@ -17,8 +17,8 @@ #include -#define ATOMIC_INIT(i) ((atomic_t) { (i) }) -#define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) +#define ATOMIC_INIT(i) { (i) } +#define ATOMIC64_INIT(i) { (i) } #define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic64_read(v) (*(volatile long *)&(v)->counter) diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index 8b78750f1efe..845f97fd1832 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c @@ -283,7 +283,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, vdata->flags = flags; vdata->type = type; spin_lock_init(&vdata->lock); - vdata->refcnt = ATOMIC_INIT(1); + atomic_set(&vdata->refcnt, 1); vma->vm_private_data = vdata; vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP | VM_DONTEXPAND); -- GitLab From 88cdb96565315a7e127a1fcd6a8e2d1374be9aa2 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Wed, 20 Jun 2012 11:47:35 +0800 Subject: [PATCH 0172/1799] asus-wmi: use ASUS_WMI_METHODID_DSTS2 as default DSTS ID. commit 63a78bb1051b240417daad3a3fa9c1bb10646dca upstream. According to responses from the BIOS team, ASUS_WMI_METHODID_DSTS2 (0x53545344) will be used as future DSTS ID. In addition, calling asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL) returns ASUS_WMI_UNSUPPORTED_METHOD in new ASUS laptop PCs. This patch fixes no DSTS ID will be assigned in this case. Signed-off-by: Alex Hung Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/asus-wmi.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 77aadde5281c..556cbb455ed2 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -1467,14 +1467,9 @@ static int asus_wmi_platform_init(struct asus_wmi *asus) */ if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL)) asus->dsts_id = ASUS_WMI_METHODID_DSTS; - else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL)) + else asus->dsts_id = ASUS_WMI_METHODID_DSTS2; - if (!asus->dsts_id) { - pr_err("Can't find DSTS"); - return -ENODEV; - } - /* CWAP allow to define the behavior of the Fn+F2 key, * this method doesn't seems to be present on Eee PCs */ if (asus->driver->quirks->wapf >= 0) -- GitLab From 613975f7a65f75b6e720bfca721d2d99542c53b8 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 18 Jul 2012 11:17:11 -0700 Subject: [PATCH 0173/1799] sunrpc: clnt: Add missing braces commit cac5d07e3ca696dcacfb123553cf6c722111cfd3 upstream. Add a missing set of braces that commit 4e0038b6b24 ("SUNRPC: Move clnt->cl_server into struct rpc_xprt") forgot. Signed-off-by: Joe Perches Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/clnt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 25302c802460..57f2731d957a 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -1846,12 +1846,13 @@ call_timeout(struct rpc_task *task) return; } if (RPC_IS_SOFT(task)) { - if (clnt->cl_chatty) + if (clnt->cl_chatty) { rcu_read_lock(); printk(KERN_NOTICE "%s: server %s not responding, timed out\n", clnt->cl_protname, rcu_dereference(clnt->cl_xprt)->servername); rcu_read_unlock(); + } if (task->tk_flags & RPC_TASK_TIMEOUT) rpc_exit(task, -ETIMEDOUT); else -- GitLab From d281dc7448010256bf2e23a65e10a4f6fc786284 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Fri, 20 Jul 2012 15:57:48 +0400 Subject: [PATCH 0174/1799] SUNRPC: return negative value in case rpcbind client creation error commit caea33da898e4e14f0ba58173e3b7689981d2c0b upstream. Without this patch kernel will panic on LockD start, because lockd_up() checks lockd_up_net() result for negative value. From my pow it's better to return negative value from rpcbind routines instead of replacing all such checks like in lockd_up(). Signed-off-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/rpcb_clnt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 4c38b33ab8a8..4d53ad5220f3 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -251,7 +251,7 @@ static int rpcb_create_local_unix(struct net *net) if (IS_ERR(clnt)) { dprintk("RPC: failed to create AF_LOCAL rpcbind " "client (errno %ld).\n", PTR_ERR(clnt)); - result = -PTR_ERR(clnt); + result = PTR_ERR(clnt); goto out; } @@ -298,7 +298,7 @@ static int rpcb_create_local_net(struct net *net) if (IS_ERR(clnt)) { dprintk("RPC: failed to create local rpcbind " "client (errno %ld).\n", PTR_ERR(clnt)); - result = -PTR_ERR(clnt); + result = PTR_ERR(clnt); goto out; } -- GitLab From d7c61cba59ebdb18ebe357b7952f61e4100c2d92 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Mon, 30 Jul 2012 14:42:07 -0700 Subject: [PATCH 0175/1799] nilfs2: fix deadlock issue between chcp and thaw ioctls commit 572d8b3945a31bee7c40d21556803e4807fd9141 upstream. An fs-thaw ioctl causes deadlock with a chcp or mkcp -s command: chcp D ffff88013870f3d0 0 1325 1324 0x00000004 ... Call Trace: nilfs_transaction_begin+0x11c/0x1a0 [nilfs2] wake_up_bit+0x20/0x20 copy_from_user+0x18/0x30 [nilfs2] nilfs_ioctl_change_cpmode+0x7d/0xcf [nilfs2] nilfs_ioctl+0x252/0x61a [nilfs2] do_page_fault+0x311/0x34c get_unmapped_area+0x132/0x14e do_vfs_ioctl+0x44b/0x490 __set_task_blocked+0x5a/0x61 vm_mmap_pgoff+0x76/0x87 __set_current_blocked+0x30/0x4a sys_ioctl+0x4b/0x6f system_call_fastpath+0x16/0x1b thaw D ffff88013870d890 0 1352 1351 0x00000004 ... Call Trace: rwsem_down_failed_common+0xdb/0x10f call_rwsem_down_write_failed+0x13/0x20 down_write+0x25/0x27 thaw_super+0x13/0x9e do_vfs_ioctl+0x1f5/0x490 vm_mmap_pgoff+0x76/0x87 sys_ioctl+0x4b/0x6f filp_close+0x64/0x6c system_call_fastpath+0x16/0x1b where the thaw ioctl deadlocked at thaw_super() when called while chcp was waiting at nilfs_transaction_begin() called from nilfs_ioctl_change_cpmode(). This deadlock is 100% reproducible. This is because nilfs_ioctl_change_cpmode() first locks sb->s_umount in read mode and then waits for unfreezing in nilfs_transaction_begin(), whereas thaw_super() locks sb->s_umount in write mode. The locking of sb->s_umount here was intended to make snapshot mounts and the downgrade of snapshots to checkpoints exclusive. This fixes the deadlock issue by replacing the sb->s_umount usage in nilfs_ioctl_change_cpmode() with a dedicated mutex which protects snapshot mounts. Signed-off-by: Ryusuke Konishi Cc: Fernando Luis Vazquez Cao Tested-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/nilfs2/ioctl.c | 4 ++-- fs/nilfs2/super.c | 3 +++ fs/nilfs2/the_nilfs.c | 1 + fs/nilfs2/the_nilfs.h | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 2a70fce70c65..6fe98ed58545 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -182,7 +182,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, if (copy_from_user(&cpmode, argp, sizeof(cpmode))) goto out; - down_read(&inode->i_sb->s_umount); + mutex_lock(&nilfs->ns_snapshot_mount_mutex); nilfs_transaction_begin(inode->i_sb, &ti, 0); ret = nilfs_cpfile_change_cpmode( @@ -192,7 +192,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, else nilfs_transaction_commit(inode->i_sb); /* never fails */ - up_read(&inode->i_sb->s_umount); + mutex_unlock(&nilfs->ns_snapshot_mount_mutex); out: mnt_drop_write_file(filp); return ret; diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 1099a76cee59..496904b96b2b 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -948,6 +948,8 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, struct nilfs_root *root; int ret; + mutex_lock(&nilfs->ns_snapshot_mount_mutex); + down_read(&nilfs->ns_segctor_sem); ret = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, cno); up_read(&nilfs->ns_segctor_sem); @@ -972,6 +974,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, ret = nilfs_get_root_dentry(s, root, root_dentry); nilfs_put_root(root); out: + mutex_unlock(&nilfs->ns_snapshot_mount_mutex); return ret; } diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 501b7f8b739f..41e6a04a561f 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -76,6 +76,7 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev) nilfs->ns_bdev = bdev; atomic_set(&nilfs->ns_ndirtyblks, 0); init_rwsem(&nilfs->ns_sem); + mutex_init(&nilfs->ns_snapshot_mount_mutex); INIT_LIST_HEAD(&nilfs->ns_dirty_files); INIT_LIST_HEAD(&nilfs->ns_gc_inodes); spin_lock_init(&nilfs->ns_inode_lock); diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 9992b11312ff..de7435f0ef5c 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -47,6 +47,7 @@ enum { * @ns_flags: flags * @ns_bdev: block device * @ns_sem: semaphore for shared states + * @ns_snapshot_mount_mutex: mutex to protect snapshot mounts * @ns_sbh: buffer heads of on-disk super blocks * @ns_sbp: pointers to super block data * @ns_sbwtime: previous write time of super block @@ -99,6 +100,7 @@ struct the_nilfs { struct block_device *ns_bdev; struct rw_semaphore ns_sem; + struct mutex ns_snapshot_mount_mutex; /* * used for -- GitLab From 246dec1d5b521ad2cece0a4ea57a59dca2e3cf38 Mon Sep 17 00:00:00 2001 From: Luis Henriques Date: Tue, 19 Jun 2012 11:29:49 -0300 Subject: [PATCH 0176/1799] media: ene_ir: Fix driver initialisation commit b31b021988fed9e3741a46918f14ba9b063811db upstream. commit 9ef449c6b31bb6a8e6dedc24de475a3b8c79be20 ("[media] rc: Postpone ISR registration") fixed an early ISR registration on several drivers. It did however also introduced a bug by moving the invocation of pnp_port_start() to the end of the probe function. This patch fixes this issue by moving the invocation of pnp_port_start() to an earlier stage in the probe function. Signed-off-by: Luis Henriques Cc: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/rc/ene_ir.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index bef5296173c9..647dd951b0e8 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c @@ -1018,6 +1018,8 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) spin_lock_init(&dev->hw_lock); + dev->hw_io = pnp_port_start(pnp_dev, 0); + pnp_set_drvdata(pnp_dev, dev); dev->pnp_dev = pnp_dev; @@ -1072,7 +1074,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) /* claim the resources */ error = -EBUSY; - dev->hw_io = pnp_port_start(pnp_dev, 0); if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) { dev->hw_io = -1; dev->irq = -1; -- GitLab From 603cb88c3a73968a0fa498e252cbb781e62bb5b4 Mon Sep 17 00:00:00 2001 From: Greg Pearson Date: Mon, 30 Jul 2012 14:39:05 -0700 Subject: [PATCH 0177/1799] pcdp: use early_ioremap/early_iounmap to access pcdp table commit 6c4088ac3a4d82779903433bcd5f048c58fb1aca upstream. efi_setup_pcdp_console() is called during boot to parse the HCDP/PCDP EFI system table and setup an early console for printk output. The routine uses ioremap/iounmap to setup access to the HCDP/PCDP table information. The call to ioremap is happening early in the boot process which leads to a panic on x86_64 systems: panic+0x01ca do_exit+0x043c oops_end+0x00a7 no_context+0x0119 __bad_area_nosemaphore+0x0138 bad_area_nosemaphore+0x000e do_page_fault+0x0321 page_fault+0x0020 reserve_memtype+0x02a1 __ioremap_caller+0x0123 ioremap_nocache+0x0012 efi_setup_pcdp_console+0x002b setup_arch+0x03a9 start_kernel+0x00d4 x86_64_start_reservations+0x012c x86_64_start_kernel+0x00fe This replaces the calls to ioremap/iounmap in efi_setup_pcdp_console() with calls to early_ioremap/early_iounmap which can be called during early boot. This patch was tested on an x86_64 prototype system which uses the HCDP/PCDP table for early console setup. Signed-off-by: Greg Pearson Acked-by: Khalid Aziz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/pcdp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c index 51e0e2d8fac6..a330492e06f9 100644 --- a/drivers/firmware/pcdp.c +++ b/drivers/firmware/pcdp.c @@ -95,7 +95,7 @@ efi_setup_pcdp_console(char *cmdline) if (efi.hcdp == EFI_INVALID_TABLE_ADDR) return -ENODEV; - pcdp = ioremap(efi.hcdp, 4096); + pcdp = early_ioremap(efi.hcdp, 4096); printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, efi.hcdp); if (strstr(cmdline, "console=hcdp")) { @@ -131,6 +131,6 @@ efi_setup_pcdp_console(char *cmdline) } out: - iounmap(pcdp); + early_iounmap(pcdp, 4096); return rc; } -- GitLab From ce6f0ff8d1031931df7031a88f4085e5f196a854 Mon Sep 17 00:00:00 2001 From: Joonsoo Kim Date: Mon, 30 Jul 2012 14:39:04 -0700 Subject: [PATCH 0178/1799] mm: fix wrong argument of migrate_huge_pages() in soft_offline_huge_page() commit dc32f63453f56d07a1073a697dcd843dd3098c09 upstream. Commit a6bc32b89922 ("mm: compaction: introduce sync-light migration for use by compaction") changed the declaration of migrate_pages() and migrate_huge_pages(). But it missed changing the argument of migrate_huge_pages() in soft_offline_huge_page(). In this case, we should call migrate_huge_pages() with MIGRATE_SYNC. Additionally, there is a mismatch between type the of argument and the function declaration for migrate_pages(). Signed-off-by: Joonsoo Kim Cc: Christoph Lameter Cc: Mel Gorman Acked-by: David Rientjes Cc: "Aneesh Kumar K.V" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memory-failure.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 0de20d7168f7..274c3cc5fbc0 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1433,8 +1433,8 @@ static int soft_offline_huge_page(struct page *page, int flags) /* Keep page count to indicate a given hugepage is isolated. */ list_add(&hpage->lru, &pagelist); - ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0, - true); + ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, false, + MIGRATE_SYNC); if (ret) { struct page *page1, *page2; list_for_each_entry_safe(page1, page2, &pagelist, lru) @@ -1563,7 +1563,7 @@ int soft_offline_page(struct page *page, int flags) page_is_file_cache(page)); list_add(&page->lru, &pagelist); ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, - 0, MIGRATE_SYNC); + false, MIGRATE_SYNC); if (ret) { putback_lru_pages(&pagelist); pr_info("soft offline: %#lx: migration failed %d, type %lx\n", -- GitLab From 05aa0d1bc94e2809ec0ccb4be20860784e4640b1 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 13 Jul 2012 08:19:34 +0100 Subject: [PATCH 0179/1799] ARM: 7466/1: disable interrupt before spinning endlessly commit 98bd8b96b26db3399a48202318dca4aaa2515355 upstream. The CPU will endlessly spin at the end of machine_halt and machine_restart calls. However, this will lead to a soft lockup warning after about 20 seconds, if CONFIG_LOCKUP_DETECTOR is enabled, as system timer is still alive. Disable interrupt before going to spin endlessly, so that the lockup warning will never be seen. Reported-by: Marek Vasut Signed-off-by: Shawn Guo Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/process.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 2b7b017a20cd..48f36246a5d7 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -267,6 +267,7 @@ void machine_shutdown(void) void machine_halt(void) { machine_shutdown(); + local_irq_disable(); while (1); } @@ -288,6 +289,7 @@ void machine_restart(char *cmd) /* Whoops - the platform was unable to reboot. Tell the user! */ printk("Reboot failed -- System halted\n"); + local_irq_disable(); while (1); } -- GitLab From ea2ebaa71c978254c2a93bf561236aec8a167166 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 20 Jul 2012 02:03:43 +0100 Subject: [PATCH 0180/1799] ARM: 7476/1: vfp: only clear vfp state for current cpu in vfp_pm_suspend commit a84b895a2348f0dbff31b71ddf954f70a6cde368 upstream. vfp_pm_suspend runs on each cpu, only clear the hardware state pointer for the current cpu. Prevents a possible crash if one cpu clears the hw state pointer when another cpu has already checked if it is valid. Signed-off-by: Colin Cross Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/vfp/vfpmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index b0197b2c857d..da3b9292f9f0 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -460,7 +460,7 @@ static int vfp_pm_suspend(void) } /* clear any information we had about last context state */ - memset(vfp_current_hw_state, 0, sizeof(vfp_current_hw_state)); + vfp_current_hw_state[ti->cpu] = NULL; return 0; } -- GitLab From f95f7ae189b51123becde905e934954c86c8a0e2 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 20 Jul 2012 02:03:42 +0100 Subject: [PATCH 0181/1799] ARM: 7477/1: vfp: Always save VFP state in vfp_pm_suspend on UP commit 24b35521b8ddf088531258f06f681bb7b227bf47 upstream. vfp_pm_suspend should save the VFP state in suspend after any lazy context switch. If it only saves when the VFP is enabled, the state can get lost when, on a UP system: Thread 1 uses the VFP Context switch occurs to thread 2, VFP is disabled but the VFP context is not saved Thread 2 initiates suspend vfp_pm_suspend is called with the VFP disabled, and the unsaved VFP context of Thread 1 in the registers Modify vfp_pm_suspend to save the VFP context whenever vfp_current_hw_state is not NULL. Includes a fix from Ido Yariv , who pointed out that on SMP systems, the state pointer can be pointing to a freed task struct if a task exited on another cpu, fixed by using #ifndef CONFIG_SMP in the new if clause. Signed-off-by: Colin Cross Cc: Barry Song Cc: Catalin Marinas Cc: Ido Yariv Cc: Daniel Drake Cc: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/vfp/vfpmodule.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index da3b9292f9f0..1ef803aa7a5c 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -457,6 +457,12 @@ static int vfp_pm_suspend(void) /* disable, just in case */ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); + } else if (vfp_current_hw_state[ti->cpu]) { +#ifndef CONFIG_SMP + fmxr(FPEXC, fpexc | FPEXC_EN); + vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc); + fmxr(FPEXC, fpexc); +#endif } /* clear any information we had about last context state */ -- GitLab From 17c7d1468f968e153d39a94efeedd0a0e2a77c2a Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 20 Jul 2012 18:24:55 +0100 Subject: [PATCH 0182/1799] ARM: 7478/1: errata: extend workaround for erratum #720789 commit 5a783cbc48367cfc7b65afc75430953dfe60098f upstream. Commit cdf357f1 ("ARM: 6299/1: errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID") replaced by-ASID TLB flushing operations with all-ASID variants to workaround A9 erratum #720789. This patch extends the workaround to include the tlb_range operations, which were overlooked by the original patch. Tested-by: Steve Capper Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/mm/tlb-v7.S | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S index 845f461f8ec1..c2021139cb56 100644 --- a/arch/arm/mm/tlb-v7.S +++ b/arch/arm/mm/tlb-v7.S @@ -38,11 +38,19 @@ ENTRY(v7wbi_flush_user_tlb_range) dsb mov r0, r0, lsr #PAGE_SHIFT @ align address mov r1, r1, lsr #PAGE_SHIFT +#ifdef CONFIG_ARM_ERRATA_720789 + mov r3, #0 +#else asid r3, r3 @ mask ASID +#endif orr r0, r3, r0, lsl #PAGE_SHIFT @ Create initial MVA mov r1, r1, lsl #PAGE_SHIFT 1: +#ifdef CONFIG_ARM_ERRATA_720789 + ALT_SMP(mcr p15, 0, r0, c8, c3, 3) @ TLB invalidate U MVA all ASID (shareable) +#else ALT_SMP(mcr p15, 0, r0, c8, c3, 1) @ TLB invalidate U MVA (shareable) +#endif ALT_UP(mcr p15, 0, r0, c8, c7, 1) @ TLB invalidate U MVA add r0, r0, #PAGE_SZ @@ -67,7 +75,11 @@ ENTRY(v7wbi_flush_kern_tlb_range) mov r0, r0, lsl #PAGE_SHIFT mov r1, r1, lsl #PAGE_SHIFT 1: +#ifdef CONFIG_ARM_ERRATA_720789 + ALT_SMP(mcr p15, 0, r0, c8, c3, 3) @ TLB invalidate U MVA all ASID (shareable) +#else ALT_SMP(mcr p15, 0, r0, c8, c3, 1) @ TLB invalidate U MVA (shareable) +#endif ALT_UP(mcr p15, 0, r0, c8, c7, 1) @ TLB invalidate U MVA add r0, r0, #PAGE_SZ cmp r0, r1 -- GitLab From 7e49f71b7a6268bb9854b91f6fae3f070fb0222e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 23 Jul 2012 14:18:13 +0100 Subject: [PATCH 0183/1799] ARM: 7479/1: mm: avoid NULL dereference when flushing gate_vma with VIVT caches commit b74253f78400f9a4b42da84bb1de7540b88ce7c4 upstream. The vivt_flush_cache_{range,page} functions check that the mm_struct of the VMA being flushed has been active on the current CPU before performing the cache maintenance. The gate_vma has a NULL mm_struct pointer and, as such, will cause a kernel fault if we try to flush it with the above operations. This happens during ELF core dumps, which include the gate_vma as it may be useful for debugging purposes. This patch adds checks to the VIVT cache flushing functions so that VMAs with a NULL mm_struct are flushed unconditionally (the vectors page may be dirty if we use it to store the current TLS pointer). Reported-by: Gilles Chanteperdrix Tested-by: Uros Bizjak Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/cacheflush.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 1252a2675ca9..42dec04f6170 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -215,7 +215,9 @@ static inline void vivt_flush_cache_mm(struct mm_struct *mm) static inline void vivt_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) + struct mm_struct *mm = vma->vm_mm; + + if (!mm || cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm))) __cpuc_flush_user_range(start & PAGE_MASK, PAGE_ALIGN(end), vma->vm_flags); } @@ -223,7 +225,9 @@ vivt_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned static inline void vivt_flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn) { - if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) { + struct mm_struct *mm = vma->vm_mm; + + if (!mm || cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm))) { unsigned long addr = user_addr & PAGE_MASK; __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); } -- GitLab From 85869d9f5da8449613f5631961fe9309f9c2d0ad Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Sat, 28 Jul 2012 15:19:55 +0100 Subject: [PATCH 0184/1799] ARM: 7480/1: only call smp_send_stop() on SMP commit c5dff4ffd327088d85035bec535b7d0c9ea03151 upstream. On reboot or poweroff (machine_shutdown()) a call to smp_send_stop() is made (to stop the others CPU's) when CONFIG_SMP=y. arch/arm/kernel/process.c: void machine_shutdown(void) { #ifdef CONFIG_SMP smp_send_stop(); #endif } smp_send_stop() calls the function pointer smp_cross_call(), which is set on the smp_init_cpus() function for OMAP processors. arch/arm/mach-omap2/omap-smp.c: void __init smp_init_cpus(void) { ... set_smp_cross_call(gic_raise_softirq); ... } But the ARM setup_arch() function only calls smp_init_cpus() if CONFIG_SMP=y && is_smp(). arm/kernel/setup.c: void __init setup_arch(char **cmdline_p) { ... #ifdef CONFIG_SMP if (is_smp()) smp_init_cpus(); #endif ... } Newer OMAP CPU's are SMP machines so omap2plus_defconfig sets CONFIG_SMP=y. Unfortunately on an OMAP UP machine is_smp() returns false and smp_init_cpus() is never called and the smp_cross_call() function remains NULL. If the machine is rebooted or powered off, smp_send_stop() will be called (since CONFIG_SMP=y) leading to the following error: [ 42.815551] Restarting system. [ 42.819030] Unable to handle kernel NULL pointer dereference at virtual address 00000000 [ 42.827667] pgd = d7a74000 [ 42.830566] [00000000] *pgd=96ce7831, *pte=00000000, *ppte=00000000 [ 42.837249] Internal error: Oops: 80000007 [#1] SMP ARM [ 42.842773] Modules linked in: [ 42.846008] CPU: 0 Not tainted (3.5.0-rc3-next-20120622-00002-g62e87ba-dirty #44) [ 42.854278] PC is at 0x0 [ 42.856994] LR is at smp_send_stop+0x4c/0xe4 [ 42.861511] pc : [<00000000>] lr : [] psr: 60000013 [ 42.861511] sp : d6c85e70 ip : 00000000 fp : 00000000 [ 42.873626] r10: 00000000 r9 : d6c84000 r8 : 00000002 [ 42.879150] r7 : c07235a0 r6 : c06dd2d0 r5 : 000f4241 r4 : d6c85e74 [ 42.886047] r3 : 00000000 r2 : 00000000 r1 : 00000006 r0 : d6c85e74 [ 42.892944] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user [ 42.900482] Control: 10c5387d Table: 97a74019 DAC: 00000015 [ 42.906555] Process reboot (pid: 1166, stack limit = 0xd6c842f8) [ 42.912902] Stack: (0xd6c85e70 to 0xd6c86000) [ 42.917510] 5e60: c07235a0 00000000 00000000 d6c84000 [ 42.926177] 5e80: 01234567 c00143d0 4321fedc c00511bc d6c85ebc 00000168 00000460 00000000 [ 42.934814] 5ea0: c1017950 a0000013 c1017900 d8014390 d7ec3858 c0498e48 c1017950 00000000 [ 42.943481] 5ec0: d6ddde10 d6c85f78 00000003 00000000 d6ddde10 d6c84000 00000000 00000000 [ 42.952117] 5ee0: 00000002 00000000 00000000 c0088c88 00000002 00000000 00000000 c00f4b90 [ 42.960784] 5f00: 00000000 d6c85ebc d8014390 d7e311c8 60000013 00000103 00000002 d6c84000 [ 42.969421] 5f20: c00f3274 d6e00a00 00000001 60000013 d6c84000 00000000 00000000 c00895d4 [ 42.978057] 5f40: 00000002 d8007c80 d781f000 c00f6150 d8010cc0 c00f3274 d781f000 d6c84000 [ 42.986694] 5f60: c0013020 d6e00a00 00000001 20000010 0001257c ef000000 00000000 c00895d4 [ 42.995361] 5f80: 00000002 00000001 00000003 00000000 00000001 00000003 00000000 00000058 [ 43.003997] 5fa0: c00130c8 c0012f00 00000001 00000003 fee1dead 28121969 01234567 00000002 [ 43.012634] 5fc0: 00000001 00000003 00000000 00000058 00012584 0001257c 00000001 00000000 [ 43.021270] 5fe0: 000124bc bec5cc6c 00008f9c 4a2f7c40 20000010 fee1dead 00000000 00000000 [ 43.029968] [] (smp_send_stop+0x4c/0xe4) from [] (machine_restart+0xc/0x4c) [ 43.039154] [] (machine_restart+0xc/0x4c) from [] (sys_reboot+0x144/0x1f0) [ 43.048278] [] (sys_reboot+0x144/0x1f0) from [] (ret_fast_syscall+0x0/0x3c) [ 43.057464] Code: bad PC value [ 43.060760] ---[ end trace c3988d1dd0b8f0fb ]--- Add a check so smp_cross_call() is only called when there is more than one CPU on-line. Signed-off-by: Javier Martinez Canillas Acked-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/smp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 8f4644659777..7babc3f98a1a 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -590,7 +590,8 @@ void smp_send_stop(void) cpumask_copy(&mask, cpu_online_mask); cpumask_clear_cpu(smp_processor_id(), &mask); - smp_cross_call(&mask, IPI_CPU_STOP); + if (!cpumask_empty(&mask)) + smp_cross_call(&mask, IPI_CPU_STOP); /* Wait up to one second for other CPUs to stop */ timeout = USEC_PER_SEC; -- GitLab From 81155539833d8c492261a8fdd91e3e6579c274dd Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 30 Jul 2012 19:42:10 +0100 Subject: [PATCH 0185/1799] ARM: Fix undefined instruction exception handling commit 15ac49b65024f55c4371a53214879a9c77c4fbf9 upstream. While trying to get a v3.5 kernel booted on the cubox, I noticed that VFP does not work correctly with VFP bounce handling. This is because of the confusion over 16-bit vs 32-bit instructions, and where PC is supposed to point to. The rule is that FP handlers are entered with regs->ARM_pc pointing at the _next_ instruction to be executed. However, if the exception is not handled, regs->ARM_pc points at the faulting instruction. This is easy for ARM mode, because we know that the next instruction and previous instructions are separated by four bytes. This is not true of Thumb2 though. Since all FP instructions are 32-bit in Thumb2, it makes things easy. We just need to select the appropriate adjustment. Do this by moving the adjustment out of do_undefinstr() into the assembly code, as only the assembly code knows whether it's dealing with a 32-bit or 16-bit instruction. Acked-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/entry-armv.S | 111 +++++++++++++++++++++++------------ arch/arm/kernel/traps.c | 8 --- arch/arm/vfp/entry.S | 16 ++--- arch/arm/vfp/vfphw.S | 19 +++--- 4 files changed, 92 insertions(+), 62 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 7fd3ad048da9..8f29865810f3 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -244,6 +244,19 @@ svc_preempt: b 1b #endif +__und_fault: + @ Correct the PC such that it is pointing at the instruction + @ which caused the fault. If the faulting instruction was ARM + @ the PC will be pointing at the next instruction, and have to + @ subtract 4. Otherwise, it is Thumb, and the PC will be + @ pointing at the second half of the Thumb instruction. We + @ have to subtract 2. + ldr r2, [r0, #S_PC] + sub r2, r2, r1 + str r2, [r0, #S_PC] + b do_undefinstr +ENDPROC(__und_fault) + .align 5 __und_svc: #ifdef CONFIG_KPROBES @@ -261,25 +274,32 @@ __und_svc: @ @ r0 - instruction @ -#ifndef CONFIG_THUMB2_KERNEL +#ifndef CONFIG_THUMB2_KERNEL ldr r0, [r4, #-4] #else + mov r1, #2 ldrh r0, [r4, #-2] @ Thumb instruction at LR - 2 cmp r0, #0xe800 @ 32-bit instruction if xx >= 0 - ldrhhs r9, [r4] @ bottom 16 bits - orrhs r0, r9, r0, lsl #16 + blo __und_svc_fault + ldrh r9, [r4] @ bottom 16 bits + add r4, r4, #2 + str r4, [sp, #S_PC] + orr r0, r9, r0, lsl #16 #endif - adr r9, BSYM(1f) + adr r9, BSYM(__und_svc_finish) mov r2, r4 bl call_fpe + mov r1, #4 @ PC correction to apply +__und_svc_fault: mov r0, sp @ struct pt_regs *regs - bl do_undefinstr + bl __und_fault @ @ IRQs off again before pulling preserved data off the stack @ -1: disable_irq_notrace +__und_svc_finish: + disable_irq_notrace @ @ restore SPSR and restart the instruction @@ -423,25 +443,33 @@ __und_usr: mov r2, r4 mov r3, r5 + @ r2 = regs->ARM_pc, which is either 2 or 4 bytes ahead of the + @ faulting instruction depending on Thumb mode. + @ r3 = regs->ARM_cpsr @ - @ fall through to the emulation code, which returns using r9 if - @ it has emulated the instruction, or the more conventional lr - @ if we are to treat this as a real undefined instruction - @ - @ r0 - instruction + @ The emulation code returns using r9 if it has emulated the + @ instruction, or the more conventional lr if we are to treat + @ this as a real undefined instruction @ adr r9, BSYM(ret_from_exception) - adr lr, BSYM(__und_usr_unknown) + tst r3, #PSR_T_BIT @ Thumb mode? - itet eq @ explicit IT needed for the 1f label - subeq r4, r2, #4 @ ARM instr at LR - 4 - subne r4, r2, #2 @ Thumb instr at LR - 2 -1: ldreqt r0, [r4] + bne __und_usr_thumb + sub r4, r2, #4 @ ARM instr at LR - 4 +1: ldrt r0, [r4] #ifdef CONFIG_CPU_ENDIAN_BE8 - reveq r0, r0 @ little endian instruction + rev r0, r0 @ little endian instruction #endif - beq call_fpe + @ r0 = 32-bit ARM instruction which caused the exception + @ r2 = PC value for the following instruction (:= regs->ARM_pc) + @ r4 = PC value for the faulting instruction + @ lr = 32-bit undefined instruction function + adr lr, BSYM(__und_usr_fault_32) + b call_fpe + +__und_usr_thumb: @ Thumb instruction + sub r4, r2, #2 @ First half of thumb instr at LR - 2 #if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7 /* * Thumb-2 instruction handling. Note that because pre-v6 and >= v6 platforms @@ -455,7 +483,7 @@ __und_usr: ldr r5, .LCcpu_architecture ldr r5, [r5] cmp r5, #CPU_ARCH_ARMv7 - blo __und_usr_unknown + blo __und_usr_fault_16 @ 16bit undefined instruction /* * The following code won't get run unless the running CPU really is v7, so * coding round the lack of ldrht on older arches is pointless. Temporarily @@ -463,15 +491,18 @@ __und_usr: */ .arch armv6t2 #endif -2: - ARM( ldrht r5, [r4], #2 ) - THUMB( ldrht r5, [r4] ) - THUMB( add r4, r4, #2 ) +2: ldrht r5, [r4] cmp r5, #0xe800 @ 32bit instruction if xx != 0 - blo __und_usr_unknown -3: ldrht r0, [r4] + blo __und_usr_fault_16 @ 16bit undefined instruction +3: ldrht r0, [r2] add r2, r2, #2 @ r2 is PC + 2, make it PC + 4 + str r2, [sp, #S_PC] @ it's a 2x16bit instr, update orr r0, r0, r5, lsl #16 + adr lr, BSYM(__und_usr_fault_32) + @ r0 = the two 16-bit Thumb instructions which caused the exception + @ r2 = PC value for the following Thumb instruction (:= regs->ARM_pc) + @ r4 = PC value for the first 16-bit Thumb instruction + @ lr = 32bit undefined instruction function #if __LINUX_ARM_ARCH__ < 7 /* If the target arch was overridden, change it back: */ @@ -482,17 +513,13 @@ __und_usr: #endif #endif /* __LINUX_ARM_ARCH__ < 7 */ #else /* !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) */ - b __und_usr_unknown + b __und_usr_fault_16 #endif - UNWIND(.fnend ) + UNWIND(.fnend) ENDPROC(__und_usr) - @ - @ fallthrough to call_fpe - @ - /* - * The out of line fixup for the ldrt above. + * The out of line fixup for the ldrt instructions above. */ .pushsection .fixup, "ax" 4: mov pc, r9 @@ -523,11 +550,12 @@ ENDPROC(__und_usr) * NEON handler code. * * Emulators may wish to make use of the following registers: - * r0 = instruction opcode. - * r2 = PC+4 + * r0 = instruction opcode (32-bit ARM or two 16-bit Thumb) + * r2 = PC value to resume execution after successful emulation * r9 = normal "successful" return address - * r10 = this threads thread_info structure. + * r10 = this threads thread_info structure * lr = unrecognised instruction return address + * IRQs disabled, FIQs enabled. */ @ @ Fall-through from Thumb-2 __und_usr @@ -662,12 +690,17 @@ ENTRY(no_fp) mov pc, lr ENDPROC(no_fp) -__und_usr_unknown: - enable_irq +__und_usr_fault_32: + mov r1, #4 + b 1f +__und_usr_fault_16: + mov r1, #2 +1: enable_irq mov r0, sp adr lr, BSYM(ret_from_exception) - b do_undefinstr -ENDPROC(__und_usr_unknown) + b __und_fault +ENDPROC(__und_usr_fault_32) +ENDPROC(__und_usr_fault_16) .align 5 __pabt_usr: diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 63d402f75e25..a8ad1e34902e 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -370,18 +370,10 @@ static int call_undef_hook(struct pt_regs *regs, unsigned int instr) asmlinkage void __exception do_undefinstr(struct pt_regs *regs) { - unsigned int correction = thumb_mode(regs) ? 2 : 4; unsigned int instr; siginfo_t info; void __user *pc; - /* - * According to the ARM ARM, PC is 2 or 4 bytes ahead, - * depending whether we're in Thumb mode or not. - * Correct this offset. - */ - regs->ARM_pc -= correction; - pc = (void __user *)instruction_pointer(regs); if (processor_mode(regs) == SVC_MODE) { diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S index 4fa9903b83cf..cc926c985981 100644 --- a/arch/arm/vfp/entry.S +++ b/arch/arm/vfp/entry.S @@ -7,18 +7,20 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * - * Basic entry code, called from the kernel's undefined instruction trap. - * r0 = faulted instruction - * r5 = faulted PC+4 - * r9 = successful return - * r10 = thread_info structure - * lr = failure return */ #include #include #include "../kernel/entry-header.S" +@ VFP entry point. +@ +@ r0 = instruction opcode (32-bit ARM or two 16-bit Thumb) +@ r2 = PC value to resume execution after successful emulation +@ r9 = normal "successful" return address +@ r10 = this threads thread_info structure +@ lr = unrecognised instruction return address +@ IRQs disabled. +@ ENTRY(do_vfp) #ifdef CONFIG_PREEMPT ldr r4, [r10, #TI_PREEMPT] @ get preempt count diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index 2d30c7f6edd3..3a0efaad6090 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -61,13 +61,13 @@ @ VFP hardware support entry point. @ -@ r0 = faulted instruction -@ r2 = faulted PC+4 -@ r9 = successful return +@ r0 = instruction opcode (32-bit ARM or two 16-bit Thumb) +@ r2 = PC value to resume execution after successful emulation +@ r9 = normal "successful" return address @ r10 = vfp_state union @ r11 = CPU number -@ lr = failure return - +@ lr = unrecognised instruction return address +@ IRQs enabled. ENTRY(vfp_support_entry) DBGSTR3 "instr %08x pc %08x state %p", r0, r2, r10 @@ -161,9 +161,12 @@ vfp_hw_state_valid: @ exception before retrying branch @ out before setting an FPEXC that @ stops us reading stuff - VFPFMXR FPEXC, r1 @ restore FPEXC last - sub r2, r2, #4 - str r2, [sp, #S_PC] @ retry the instruction + VFPFMXR FPEXC, r1 @ Restore FPEXC last + sub r2, r2, #4 @ Retry current instruction - if Thumb + str r2, [sp, #S_PC] @ mode it's two 16-bit instructions, + @ else it's one 32-bit instruction, so + @ always subtract 4 from the following + @ instruction address. #ifdef CONFIG_PREEMPT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count -- GitLab From cd5deba98060332626da3369e4798d0de51456ff Mon Sep 17 00:00:00 2001 From: "Philipp A. Mohrenweiser" Date: Mon, 6 Aug 2012 13:14:18 +0200 Subject: [PATCH 0186/1799] ALSA: hda - add dock support for Thinkpad T430s commit 4407be6ba217514b1bc01488f8b56467d309e416 upstream. Add a model/fixup string "lenovo-dock", for Thinkpad T430s, to allow sound in docking station. Tested on Lenovo T430s with ThinkPad Mini Dock Plus Series 3 Signed-off-by: Philipp A. Mohrenweiser 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 62e1627acda2..a5b8d6d0ef96 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6157,6 +6157,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK), + SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), -- GitLab From 08899ba0982718342e5b2ab8dd917ab479fc7f4f Mon Sep 17 00:00:00 2001 From: Felix Kaechele Date: Mon, 6 Aug 2012 23:02:01 +0200 Subject: [PATCH 0187/1799] ALSA: hda - add dock support for Thinkpad X230 commit c8415a48fcb7a29889f4405d38c57db351e4b50a upstream. As with the ThinkPad Models X230 Tablet and T530 the X230 needs a qurik to correctly set up the pins for the dock port. Signed-off-by: Felix Kaechele 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 a5b8d6d0ef96..71dd0530a896 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6157,6 +6157,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK), + SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), -- GitLab From 55f5c43caba6cccd00840003fc0c80acc785ba83 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 7 Aug 2012 14:03:29 +0200 Subject: [PATCH 0188/1799] ALSA: hda - remove quirk for Dell Vostro 1015 commit e9fc83cb2e5877801a255a37ddbc5be996ea8046 upstream. This computer is confirmed working with model=auto on kernel 3.2. Also, parsing fails with hda-emu with the current model. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_conexant.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index d906c5b74cf0..389702708ea2 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -2975,7 +2975,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO), - SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO), SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x0510, "Dell Vostro", CXT5066_IDEAPAD), -- GitLab From 41a2033bf3bc1ecf19c743b452791ba492a6e75d Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 8 Aug 2012 08:43:37 +0200 Subject: [PATCH 0189/1799] ALSA: hda - Fix double quirk for Quanta FL1 / Lenovo Ideapad commit 012e7eb1e501d0120e0383b81477f63091f5e365 upstream. The same ID is twice in the quirk table, so the second one is not used. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 71dd0530a896..152d91b7e103 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6056,6 +6056,8 @@ static const struct alc_fixup alc269_fixups[] = { [ALC269_FIXUP_PCM_44K] = { .type = ALC_FIXUP_FUNC, .v.func = alc269_fixup_pcm_44k, + .chained = true, + .chain_id = ALC269_FIXUP_QUANTA_MUTE }, [ALC269_FIXUP_STEREO_DMIC] = { .type = ALC_FIXUP_FUNC, @@ -6160,8 +6162,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), - SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), - SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), + SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), #if 0 -- GitLab From cc9fdb9cdde35aafad3b11ce74e244f5da7ac3c0 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 31 Jul 2012 16:45:52 -0700 Subject: [PATCH 0190/1799] mm: mmu_notifier: fix freed page still mapped in secondary MMU commit 3ad3d901bbcfb15a5e4690e55350db0899095a68 upstream. mmu_notifier_release() is called when the process is exiting. It will delete all the mmu notifiers. But at this time the page belonging to the process is still present in page tables and is present on the LRU list, so this race will happen: CPU 0 CPU 1 mmu_notifier_release: try_to_unmap: hlist_del_init_rcu(&mn->hlist); ptep_clear_flush_notify: mmu nofifler not found free page !!!!!! /* * At the point, the page has been * freed, but it is still mapped in * the secondary MMU. */ mn->ops->release(mn, mm); Then the box is not stable and sometimes we can get this bug: [ 738.075923] BUG: Bad page state in process migrate-perf pfn:03bec [ 738.075931] page:ffffea00000efb00 count:0 mapcount:0 mapping: (null) index:0x8076 [ 738.075936] page flags: 0x20000000000014(referenced|dirty) The same issue is present in mmu_notifier_unregister(). We can call ->release before deleting the notifier to ensure the page has been unmapped from the secondary MMU before it is freed. Signed-off-by: Xiao Guangrong Cc: Avi Kivity Cc: Marcelo Tosatti Cc: Paul Gortmaker Cc: Andrea Arcangeli Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mmu_notifier.c | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c index 9a611d3a1848..862b60822d9f 100644 --- a/mm/mmu_notifier.c +++ b/mm/mmu_notifier.c @@ -33,6 +33,24 @@ void __mmu_notifier_release(struct mm_struct *mm) { struct mmu_notifier *mn; + struct hlist_node *n; + + /* + * RCU here will block mmu_notifier_unregister until + * ->release returns. + */ + rcu_read_lock(); + hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) + /* + * if ->release runs before mmu_notifier_unregister it + * must be handled as it's the only way for the driver + * to flush all existing sptes and stop the driver + * from establishing any more sptes before all the + * pages in the mm are freed. + */ + if (mn->ops->release) + mn->ops->release(mn, mm); + rcu_read_unlock(); spin_lock(&mm->mmu_notifier_mm->lock); while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) { @@ -46,23 +64,6 @@ void __mmu_notifier_release(struct mm_struct *mm) * mmu_notifier_unregister to return. */ hlist_del_init_rcu(&mn->hlist); - /* - * RCU here will block mmu_notifier_unregister until - * ->release returns. - */ - rcu_read_lock(); - spin_unlock(&mm->mmu_notifier_mm->lock); - /* - * if ->release runs before mmu_notifier_unregister it - * must be handled as it's the only way for the driver - * to flush all existing sptes and stop the driver - * from establishing any more sptes before all the - * pages in the mm are freed. - */ - if (mn->ops->release) - mn->ops->release(mn, mm); - rcu_read_unlock(); - spin_lock(&mm->mmu_notifier_mm->lock); } spin_unlock(&mm->mmu_notifier_mm->lock); @@ -284,16 +285,13 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) { BUG_ON(atomic_read(&mm->mm_count) <= 0); - spin_lock(&mm->mmu_notifier_mm->lock); if (!hlist_unhashed(&mn->hlist)) { - hlist_del_rcu(&mn->hlist); - /* * RCU here will force exit_mmap to wait ->release to finish * before freeing the pages. */ rcu_read_lock(); - spin_unlock(&mm->mmu_notifier_mm->lock); + /* * exit_mmap will block in mmu_notifier_release to * guarantee ->release is called before freeing the @@ -302,8 +300,11 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) if (mn->ops->release) mn->ops->release(mn, mm); rcu_read_unlock(); - } else + + spin_lock(&mm->mmu_notifier_mm->lock); + hlist_del_rcu(&mn->hlist); spin_unlock(&mm->mmu_notifier_mm->lock); + } /* * Wait any running method to finish, of course including -- GitLab From fb060f3d95d29c385063151c8a09faa4d1a02f2f Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 31 Jul 2012 10:05:34 +1000 Subject: [PATCH 0191/1799] md/raid1: don't abort a resync on the first badblock. commit b7219ccb33aa0df9949a60c68b5e9f712615e56f upstream. If a resync of a RAID1 array with 2 devices finds a known bad block one device it will neither read from, or write to, that device for this block offset. So there will be one read_target (The other device) and zero write targets. This condition causes md/raid1 to abort the resync assuming that it has finished - without known bad blocks this would be true. When there are no write targets because of the presence of bad blocks we should only skip over the area covered by the bad block. RAID10 already gets this right, raid1 doesn't. Or didn't. As this can cause a 'sync' to abort early and appear to have succeeded it could lead to some data corruption, so it suitable for -stable. Reported-by: Alexander Lyakas Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid1.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d7add9d5bac2..23904d233735 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2429,7 +2429,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp /* There is nowhere to write, so all non-sync * drives must be failed - so we are finished */ - sector_t rv = max_sector - sector_nr; + sector_t rv; + if (min_bad > 0) + max_sector = sector_nr + min_bad; + rv = max_sector - sector_nr; *skipped = 1; put_buf(r1_bio); return rv; -- GitLab From 8b0331a46c6aa9f853e1208b0ce137c4d1d4fc1a Mon Sep 17 00:00:00 2001 From: Alexander Holler Date: Sat, 21 Apr 2012 00:11:07 +0200 Subject: [PATCH 0192/1799] video/smscufx: fix line counting in fb_write commit 2fe2d9f47cfe1a3e66e7d087368b3d7155b04c15 upstream. Line 0 and 1 were both written to line 0 (on the display) and all subsequent lines had an offset of -1. The result was that the last line on the display was never overwritten by writes to /dev/fbN. The origin of this bug seems to have been udlfb. Signed-off-by: Alexander Holler Signed-off-by: Florian Tobias Schandinat Signed-off-by: Greg Kroah-Hartman --- drivers/video/smscufx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c index ccbfef5e828f..1e1e2d267f4c 100644 --- a/drivers/video/smscufx.c +++ b/drivers/video/smscufx.c @@ -904,7 +904,7 @@ static ssize_t ufx_ops_write(struct fb_info *info, const char __user *buf, result = fb_sys_write(info, buf, count, ppos); if (result > 0) { - int start = max((int)(offset / info->fix.line_length) - 1, 0); + int start = max((int)(offset / info->fix.line_length), 0); int lines = min((u32)((result / info->fix.line_length) + 1), (u32)info->var.yres); -- GitLab From 59c5bc1eb294df764567e29630dacbd04cb1e8ab Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Wed, 1 Aug 2012 17:48:36 +0300 Subject: [PATCH 0193/1799] ore: Fix out-of-bounds access in _ios_obj() commit 9e62bb4458ad2cf28bd701aa5fab380b846db326 upstream. _ios_obj() is accessed by group_index not device_table index. The oc->comps array is only a group_full of devices at a time it is not like ore_comp_dev() which is indexed by a global device_table index. This did not BUG until now because exofs only uses a single COMP for all devices. But with other FSs like PanFS this is not true. This bug was only in the write_path, all other users were using it correctly [This is a bug since 3.2 Kernel] Signed-off-by: Boaz Harrosh Signed-off-by: Greg Kroah-Hartman --- fs/exofs/ore.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c index 24a49d47e935..1585db1aa365 100644 --- a/fs/exofs/ore.c +++ b/fs/exofs/ore.c @@ -837,11 +837,11 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp) bio->bi_rw |= REQ_WRITE; } - osd_req_write(or, _ios_obj(ios, dev), per_dev->offset, - bio, per_dev->length); + osd_req_write(or, _ios_obj(ios, cur_comp), + per_dev->offset, bio, per_dev->length); ORE_DBGMSG("write(0x%llx) offset=0x%llx " "length=0x%llx dev=%d\n", - _LLU(_ios_obj(ios, dev)->id), + _LLU(_ios_obj(ios, cur_comp)->id), _LLU(per_dev->offset), _LLU(per_dev->length), dev); } else if (ios->kern_buff) { @@ -853,20 +853,20 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp) (ios->si.unit_off + ios->length > ios->layout->stripe_unit)); - ret = osd_req_write_kern(or, _ios_obj(ios, per_dev->dev), + ret = osd_req_write_kern(or, _ios_obj(ios, cur_comp), per_dev->offset, ios->kern_buff, ios->length); if (unlikely(ret)) goto out; ORE_DBGMSG2("write_kern(0x%llx) offset=0x%llx " "length=0x%llx dev=%d\n", - _LLU(_ios_obj(ios, dev)->id), + _LLU(_ios_obj(ios, cur_comp)->id), _LLU(per_dev->offset), _LLU(ios->length), per_dev->dev); } else { - osd_req_set_attributes(or, _ios_obj(ios, dev)); + osd_req_set_attributes(or, _ios_obj(ios, cur_comp)); ORE_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n", - _LLU(_ios_obj(ios, dev)->id), + _LLU(_ios_obj(ios, cur_comp)->id), ios->out_attr_len, dev); } -- GitLab From 73ee3f4cbd1e240e53c51283a3e6110f222ef424 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Tue, 31 Jul 2012 12:44:43 +0800 Subject: [PATCH 0194/1799] ACPI processor: Fix tick_broadcast_mask online/offline regression commit b7db60f45d74497c723dc7ae1370cf0b37dfb0d8 upstream. In commit 99b725084 "ACPI processor hotplug: Delay acpi_processor_start() call for hotplugged cores", acpi_processor_hotplug(pr) was wrongly replaced by acpi_processor_cst_has_changed() inside the acpi_cpu_soft_notify(). This patch will restore it back, fixing the tick_broadcast_mask regression: https://lkml.org/lkml/2012/7/30/169 Signed-off-by: Feng Tang Cc: Thomas Renninger Reviewed-by: Rafael J. Wysocki Reviewed-by: Deepthi Dharwar Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/processor_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 0734086537b8..bbac51e79d1f 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -442,7 +442,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, /* Normal CPU soft online event */ } else { acpi_processor_ppc_has_changed(pr, 0); - acpi_processor_cst_has_changed(pr); + acpi_processor_hotplug(pr); acpi_processor_reevaluate_tstate(pr, action); acpi_processor_tstate_has_changed(pr); } -- GitLab From 33db2f2ced18a4119746e8fa89a3aba13a9d2eac Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 1 Aug 2012 21:03:21 +0200 Subject: [PATCH 0195/1799] mac80211: cancel mesh path timer commit dd4c9260e7f23f2e951cbfb2726e468c6d30306c upstream. The mesh path timer needs to be canceled when leaving the mesh as otherwise it could fire after the interface has been removed already. Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/mesh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index e5fbb7cf3562..e80fa33b504d 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -595,6 +595,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) del_timer_sync(&sdata->u.mesh.housekeeping_timer); del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); + del_timer_sync(&sdata->u.mesh.mesh_path_timer); /* * If the timer fired while we waited for it, it will have * requeued the work. Now the work will be running again -- GitLab From ccf0b822f9fbbde08d56c2be07c0ab4c17036d1d Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Thu, 2 Aug 2012 11:58:50 +0530 Subject: [PATCH 0196/1799] ath9k: Add PID/VID support for AR1111 commit d4e5979c0da95791aa717c18e162540c7a596360 upstream. AR1111 is same as AR9485. The h/w difference between them is quite insignificant, Felix suggests only very few baseband features may not be available in AR1111. The h/w code for AR9485 is already present, so AR1111 should work fine with the addition of its PID/VID. Reported-by: Tim Bentley Cc: Felix Bitterli Signed-off-by: Mohammed Shafi Shajakhan Tested-by: Tim Bentley Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/hw.c | 1 + drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/pci.c | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 6dfd96448846..28a0edd57f08 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -676,6 +676,7 @@ int ath9k_hw_init(struct ath_hw *ah) case AR9300_DEVID_AR9340: case AR9300_DEVID_AR9580: case AR9300_DEVID_AR9462: + case AR9485_DEVID_AR1111: break; default: if (common->bus_ops->ath_bus_type == ATH_USB) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e88f182ff45c..f8e1fbbbfc5e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -48,6 +48,7 @@ #define AR9300_DEVID_AR9580 0x0033 #define AR9300_DEVID_AR9462 0x0034 #define AR9300_DEVID_AR9330 0x0035 +#define AR9485_DEVID_AR1111 0x0037 #define AR5416_AR9100_DEVID 0x000b diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 77dc327def8d..e44097a7529a 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -35,6 +35,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ + { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ { 0 } }; -- GitLab From 0295403cd835f7260c6d9262817138f9f1cd8e19 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 24 Jul 2012 08:35:39 +0200 Subject: [PATCH 0197/1799] wireless: reg: restore previous behaviour of chan->max_power calculations commit 5e31fc0815a4e2c72b1b495fe7a0d8f9bfb9e4b4 upstream. commit eccc068e8e84c8fe997115629925e0422a98e4de Author: Hong Wu Date: Wed Jan 11 20:33:39 2012 +0200 wireless: Save original maximum regulatory transmission power for the calucation of the local maximum transmit pow changed the way we calculate chan->max_power as min(chan->max_power, chan->max_reg_power). That broke rt2x00 (and perhaps some other drivers) that do not set chan->max_power. It is not so easy to fix this problem correctly in rt2x00. According to commit eccc068e8 changelog, change claim only to save maximum regulatory power - changing setting of chan->max_power was side effect. This patch restore previous calculations of chan->max_power and do not touch chan->max_reg_power. Signed-off-by: Stanislaw Gruszka Acked-by: Luis R. Rodriguez Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/wireless/reg.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index baf5704740ee..460af03d8149 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -891,7 +891,21 @@ static void handle_channel(struct wiphy *wiphy, chan->max_antenna_gain = min(chan->orig_mag, (int) MBI_TO_DBI(power_rule->max_antenna_gain)); chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); - chan->max_power = min(chan->max_power, chan->max_reg_power); + if (chan->orig_mpwr) { + /* + * Devices that have their own custom regulatory domain + * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the + * passed country IE power settings. + */ + if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && + wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && + wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) + chan->max_power = chan->max_reg_power; + else + chan->max_power = min(chan->orig_mpwr, + chan->max_reg_power); + } else + chan->max_power = chan->max_reg_power; } static void handle_band(struct wiphy *wiphy, -- GitLab From cabf5b0af54cec6a2f9ce674cbc96fc8aa2fc468 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 25 Jul 2012 16:28:19 +0100 Subject: [PATCH 0198/1799] x86, nops: Missing break resulting in incorrect selection on Intel commit d6250a3f12edb3a86db9598ffeca3de8b4a219e9 upstream. The Intel case falls through into the generic case which then changes the values. For cases like the P6 it doesn't do the right thing so this seems to be a screwup. Signed-off-by: Alan Cox Link: http://lkml.kernel.org/n/tip-lww2uirad4skzjlmrm0vru8o@git.kernel.org Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/alternative.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 1f84794f0759..73ef56c5a8b3 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -219,7 +219,7 @@ void __init arch_init_ideal_nops(void) ideal_nops = intel_nops; #endif } - + break; default: #ifdef CONFIG_X86_64 ideal_nops = k8_nops; -- GitLab From 0110bbfbc8ed1b5240a51e8c767c44a856424139 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 2 Jul 2012 07:52:16 -0400 Subject: [PATCH 0199/1799] random: make 'add_interrupt_randomness()' do something sane commit 775f4b297b780601e61787b766f306ed3e1d23eb upstream. We've been moving away from add_interrupt_randomness() for various reasons: it's too expensive to do on every interrupt, and flooding the CPU with interrupts could theoretically cause bogus floods of entropy from a somewhat externally controllable source. This solves both problems by limiting the actual randomness addition to just once a second or after 64 interrupts, whicever comes first. During that time, the interrupt cycle data is buffered up in a per-cpu pool. Also, we make sure the the nonblocking pool used by urandom is initialized before we start feeding the normal input pool. This assures that /dev/urandom is returning unpredictable data as soon as possible. (Based on an original patch by Linus, but significantly modified by tytso.) Tested-by: Eric Wustrow Reported-by: Eric Wustrow Reported-by: Nadia Heninger Reported-by: Zakir Durumeric Reported-by: J. Alex Halderman Signed-off-by: Linus Torvalds Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- drivers/char/random.c | 103 +++++++++++++++++++++++++++++++------- drivers/mfd/ab3100-core.c | 2 - include/linux/random.h | 2 +- kernel/irq/handle.c | 7 ++- 4 files changed, 90 insertions(+), 24 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 4ec04a754733..c59dbc6e7580 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -127,19 +127,15 @@ * * void add_input_randomness(unsigned int type, unsigned int code, * unsigned int value); - * void add_interrupt_randomness(int irq); + * void add_interrupt_randomness(int irq, int irq_flags); * void add_disk_randomness(struct gendisk *disk); * * add_input_randomness() uses the input layer interrupt timing, as well as * the event type information from the hardware. * - * add_interrupt_randomness() uses the inter-interrupt timing as random - * inputs to the entropy pool. Note that not all interrupts are good - * sources of randomness! For example, the timer interrupts is not a - * good choice, because the periodicity of the interrupts is too - * regular, and hence predictable to an attacker. Network Interface - * Controller interrupts are a better measure, since the timing of the - * NIC interrupts are more unpredictable. + * add_interrupt_randomness() uses the interrupt timing as random + * inputs to the entropy pool. Using the cycle counters and the irq source + * as inputs, it feeds the randomness roughly once a second. * * add_disk_randomness() uses what amounts to the seek time of block * layer request events, on a per-disk_devt basis, as input to the @@ -248,6 +244,7 @@ #include #include #include +#include #ifdef CONFIG_GENERIC_HARDIRQS # include @@ -256,6 +253,7 @@ #include #include #include +#include #include /* @@ -421,7 +419,9 @@ struct entropy_store { spinlock_t lock; unsigned add_ptr; int entropy_count; + int entropy_total; int input_rotate; + unsigned int initialized:1; __u8 last_data[EXTRACT_SIZE]; }; @@ -454,6 +454,10 @@ static struct entropy_store nonblocking_pool = { .pool = nonblocking_pool_data }; +static __u32 const twist_table[8] = { + 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, + 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 }; + /* * This function adds bytes into the entropy "pool". It does not * update the entropy estimate. The caller should call @@ -467,9 +471,6 @@ static struct entropy_store nonblocking_pool = { static void mix_pool_bytes_extract(struct entropy_store *r, const void *in, int nbytes, __u8 out[64]) { - static __u32 const twist_table[8] = { - 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, - 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 }; unsigned long i, j, tap1, tap2, tap3, tap4, tap5; int input_rotate; int wordmask = r->poolinfo->poolwords - 1; @@ -528,6 +529,36 @@ static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes) mix_pool_bytes_extract(r, in, bytes, NULL); } +struct fast_pool { + __u32 pool[4]; + unsigned long last; + unsigned short count; + unsigned char rotate; + unsigned char last_timer_intr; +}; + +/* + * This is a fast mixing routine used by the interrupt randomness + * collector. It's hardcoded for an 128 bit pool and assumes that any + * locks that might be needed are taken by the caller. + */ +static void fast_mix(struct fast_pool *f, const void *in, int nbytes) +{ + const char *bytes = in; + __u32 w; + unsigned i = f->count; + unsigned input_rotate = f->rotate; + + while (nbytes--) { + w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^ + f->pool[(i + 1) & 3]; + f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7]; + input_rotate += (i++ & 3) ? 7 : 14; + } + f->count = i; + f->rotate = input_rotate; +} + /* * Credit (or debit) the entropy store with n bits of entropy */ @@ -551,6 +582,12 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits) entropy_count = r->poolinfo->POOLBITS; r->entropy_count = entropy_count; + if (!r->initialized && nbits > 0) { + r->entropy_total += nbits; + if (r->entropy_total > 128) + r->initialized = 1; + } + /* should we wake readers? */ if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) { wake_up_interruptible(&random_read_wait); @@ -700,17 +737,48 @@ void add_input_randomness(unsigned int type, unsigned int code, } EXPORT_SYMBOL_GPL(add_input_randomness); -void add_interrupt_randomness(int irq) +static DEFINE_PER_CPU(struct fast_pool, irq_randomness); + +void add_interrupt_randomness(int irq, int irq_flags) { - struct timer_rand_state *state; + struct entropy_store *r; + struct fast_pool *fast_pool = &__get_cpu_var(irq_randomness); + struct pt_regs *regs = get_irq_regs(); + unsigned long now = jiffies; + __u32 input[4], cycles = get_cycles(); + + input[0] = cycles ^ jiffies; + input[1] = irq; + if (regs) { + __u64 ip = instruction_pointer(regs); + input[2] = ip; + input[3] = ip >> 32; + } - state = get_timer_rand_state(irq); + fast_mix(fast_pool, input, sizeof(input)); - if (state == NULL) + if ((fast_pool->count & 1023) && + !time_after(now, fast_pool->last + HZ)) return; - DEBUG_ENT("irq event %d\n", irq); - add_timer_randomness(state, 0x100 + irq); + fast_pool->last = now; + + r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; + mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool)); + /* + * If we don't have a valid cycle counter, and we see + * back-to-back timer interrupts, then skip giving credit for + * any entropy. + */ + if (cycles == 0) { + if (irq_flags & __IRQF_TIMER) { + if (fast_pool->last_timer_intr) + return; + fast_pool->last_timer_intr = 1; + } else + fast_pool->last_timer_intr = 0; + } + credit_entropy_bits(r, 1); } #ifdef CONFIG_BLOCK @@ -971,6 +1039,7 @@ static void init_std_data(struct entropy_store *r) spin_lock_irqsave(&r->lock, flags); r->entropy_count = 0; + r->entropy_total = 0; spin_unlock_irqrestore(&r->lock, flags); now = ktime_get_real(); diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 1efad20fb175..9522d6bda4f7 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -409,8 +409,6 @@ static irqreturn_t ab3100_irq_handler(int irq, void *data) u32 fatevent; int err; - add_interrupt_randomness(irq); - err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1, event_regs, 3); if (err) diff --git a/include/linux/random.h b/include/linux/random.h index 8f74538c96db..6ef39d7f2db1 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -52,7 +52,7 @@ extern void rand_initialize_irq(int irq); extern void add_input_randomness(unsigned int type, unsigned int code, unsigned int value); -extern void add_interrupt_randomness(int irq); +extern void add_interrupt_randomness(int irq, int irq_flags); extern void get_random_bytes(void *buf, int nbytes); void generate_random_uuid(unsigned char uuid_out[16]); diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index bdb180325551..131ca176b497 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -133,7 +133,7 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) { irqreturn_t retval = IRQ_NONE; - unsigned int random = 0, irq = desc->irq_data.irq; + unsigned int flags = 0, irq = desc->irq_data.irq; do { irqreturn_t res; @@ -161,7 +161,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) /* Fall through to add to randomness */ case IRQ_HANDLED: - random |= action->flags; + flags |= action->flags; break; default: @@ -172,8 +172,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) action = action->next; } while (action); - if (random & IRQF_SAMPLE_RANDOM) - add_interrupt_randomness(irq); + add_interrupt_randomness(irq, flags); if (!noirqdebug) note_interrupt(irq, desc, retval); -- GitLab From e0604ba541f04a542ee9a7f6a468a60688ad8c72 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 4 Jul 2012 10:38:30 -0400 Subject: [PATCH 0200/1799] random: use lockless techniques in the interrupt path commit 902c098a3663de3fa18639efbb71b6080f0bcd3c upstream. The real-time Linux folks don't like add_interrupt_randomness() taking a spinlock since it is called in the low-level interrupt routine. This also allows us to reduce the overhead in the fast path, for the random driver, which is the interrupt collection path. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- drivers/char/random.c | 78 +++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index c59dbc6e7580..ed7849342255 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -418,9 +418,9 @@ struct entropy_store { /* read-write data: */ spinlock_t lock; unsigned add_ptr; + unsigned input_rotate; int entropy_count; int entropy_total; - int input_rotate; unsigned int initialized:1; __u8 last_data[EXTRACT_SIZE]; }; @@ -468,26 +468,24 @@ static __u32 const twist_table[8] = { * it's cheap to do so and helps slightly in the expected case where * the entropy is concentrated in the low-order bits. */ -static void mix_pool_bytes_extract(struct entropy_store *r, const void *in, - int nbytes, __u8 out[64]) +static void __mix_pool_bytes(struct entropy_store *r, const void *in, + int nbytes, __u8 out[64]) { unsigned long i, j, tap1, tap2, tap3, tap4, tap5; int input_rotate; int wordmask = r->poolinfo->poolwords - 1; const char *bytes = in; __u32 w; - unsigned long flags; - /* Taps are constant, so we can load them without holding r->lock. */ tap1 = r->poolinfo->tap1; tap2 = r->poolinfo->tap2; tap3 = r->poolinfo->tap3; tap4 = r->poolinfo->tap4; tap5 = r->poolinfo->tap5; - spin_lock_irqsave(&r->lock, flags); - input_rotate = r->input_rotate; - i = r->add_ptr; + smp_rmb(); + input_rotate = ACCESS_ONCE(r->input_rotate); + i = ACCESS_ONCE(r->add_ptr); /* mix one byte at a time to simplify size handling and churn faster */ while (nbytes--) { @@ -514,19 +512,23 @@ static void mix_pool_bytes_extract(struct entropy_store *r, const void *in, input_rotate += i ? 7 : 14; } - r->input_rotate = input_rotate; - r->add_ptr = i; + ACCESS_ONCE(r->input_rotate) = input_rotate; + ACCESS_ONCE(r->add_ptr) = i; + smp_wmb(); if (out) for (j = 0; j < 16; j++) ((__u32 *)out)[j] = r->pool[(i - j) & wordmask]; - - spin_unlock_irqrestore(&r->lock, flags); } -static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes) +static void mix_pool_bytes(struct entropy_store *r, const void *in, + int nbytes, __u8 out[64]) { - mix_pool_bytes_extract(r, in, bytes, NULL); + unsigned long flags; + + spin_lock_irqsave(&r->lock, flags); + __mix_pool_bytes(r, in, nbytes, out); + spin_unlock_irqrestore(&r->lock, flags); } struct fast_pool { @@ -564,23 +566,22 @@ static void fast_mix(struct fast_pool *f, const void *in, int nbytes) */ static void credit_entropy_bits(struct entropy_store *r, int nbits) { - unsigned long flags; - int entropy_count; + int entropy_count, orig; if (!nbits) return; - spin_lock_irqsave(&r->lock, flags); - DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name); - entropy_count = r->entropy_count; +retry: + entropy_count = orig = ACCESS_ONCE(r->entropy_count); entropy_count += nbits; if (entropy_count < 0) { DEBUG_ENT("negative entropy/overflow\n"); entropy_count = 0; } else if (entropy_count > r->poolinfo->POOLBITS) entropy_count = r->poolinfo->POOLBITS; - r->entropy_count = entropy_count; + if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) + goto retry; if (!r->initialized && nbits > 0) { r->entropy_total += nbits; @@ -593,7 +594,6 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits) wake_up_interruptible(&random_read_wait); kill_fasync(&fasync, SIGIO, POLL_IN); } - spin_unlock_irqrestore(&r->lock, flags); } /********************************************************************* @@ -680,7 +680,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) sample.cycles = get_cycles(); sample.num = num; - mix_pool_bytes(&input_pool, &sample, sizeof(sample)); + mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL); /* * Calculate number of bits of randomness we probably added. @@ -764,7 +764,7 @@ void add_interrupt_randomness(int irq, int irq_flags) fast_pool->last = now; r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; - mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool)); + __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL); /* * If we don't have a valid cycle counter, and we see * back-to-back timer interrupts, then skip giving credit for @@ -829,7 +829,7 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) bytes = extract_entropy(r->pull, tmp, bytes, random_read_wakeup_thresh / 8, rsvd); - mix_pool_bytes(r, tmp, bytes); + mix_pool_bytes(r, tmp, bytes, NULL); credit_entropy_bits(r, bytes*8); } } @@ -890,9 +890,11 @@ static void extract_buf(struct entropy_store *r, __u8 *out) int i; __u32 hash[5], workspace[SHA_WORKSPACE_WORDS]; __u8 extract[64]; + unsigned long flags; /* Generate a hash across the pool, 16 words (512 bits) at a time */ sha_init(hash); + spin_lock_irqsave(&r->lock, flags); for (i = 0; i < r->poolinfo->poolwords; i += 16) sha_transform(hash, (__u8 *)(r->pool + i), workspace); @@ -905,7 +907,8 @@ static void extract_buf(struct entropy_store *r, __u8 *out) * brute-forcing the feedback as hard as brute-forcing the * hash. */ - mix_pool_bytes_extract(r, hash, sizeof(hash), extract); + __mix_pool_bytes(r, hash, sizeof(hash), extract); + spin_unlock_irqrestore(&r->lock, flags); /* * To avoid duplicates, we atomically extract a portion of the @@ -928,11 +931,10 @@ static void extract_buf(struct entropy_store *r, __u8 *out) } static ssize_t extract_entropy(struct entropy_store *r, void *buf, - size_t nbytes, int min, int reserved) + size_t nbytes, int min, int reserved) { ssize_t ret = 0, i; __u8 tmp[EXTRACT_SIZE]; - unsigned long flags; xfer_secondary_pool(r, nbytes); nbytes = account(r, nbytes, min, reserved); @@ -941,6 +943,8 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, extract_buf(r, tmp); if (fips_enabled) { + unsigned long flags; + spin_lock_irqsave(&r->lock, flags); if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) panic("Hardware RNG duplicated output!\n"); @@ -1034,22 +1038,18 @@ EXPORT_SYMBOL(get_random_bytes); static void init_std_data(struct entropy_store *r) { int i; - ktime_t now; - unsigned long flags; + ktime_t now = ktime_get_real(); + unsigned long rv; - spin_lock_irqsave(&r->lock, flags); r->entropy_count = 0; r->entropy_total = 0; - spin_unlock_irqrestore(&r->lock, flags); - - now = ktime_get_real(); - mix_pool_bytes(r, &now, sizeof(now)); - for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof flags) { - if (!arch_get_random_long(&flags)) + mix_pool_bytes(r, &now, sizeof(now), NULL); + for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) { + if (!arch_get_random_long(&rv)) break; - mix_pool_bytes(r, &flags, sizeof(flags)); + mix_pool_bytes(r, &rv, sizeof(rv), NULL); } - mix_pool_bytes(r, utsname(), sizeof(*(utsname()))); + mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL); } static int rand_initialize(void) @@ -1186,7 +1186,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count) count -= bytes; p += bytes; - mix_pool_bytes(r, buf, bytes); + mix_pool_bytes(r, buf, bytes, NULL); cond_resched(); } -- GitLab From 1d0eb350ee278cb257178a14c4c9d965d7d2835e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 4 Jul 2012 11:16:01 -0400 Subject: [PATCH 0201/1799] random: create add_device_randomness() interface commit a2080a67abe9e314f9e9c2cc3a4a176e8a8f8793 upstream. Add a new interface, add_device_randomness() for adding data to the random pool that is likely to differ between two devices (or possibly even per boot). This would be things like MAC addresses or serial numbers, or the read-out of the RTC. This does *not* add any actual entropy to the pool, but it initializes the pool to different values for devices that might otherwise be identical and have very little entropy available to them (particularly common in the embedded world). [ Modified by tytso to mix in a timestamp, since there may be some variability caused by the time needed to detect/configure the hardware in question. ] Signed-off-by: Linus Torvalds Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- drivers/char/random.c | 28 ++++++++++++++++++++++++++++ include/linux/random.h | 1 + 2 files changed, 29 insertions(+) diff --git a/drivers/char/random.c b/drivers/char/random.c index ed7849342255..0b22268207b5 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -125,11 +125,20 @@ * The current exported interfaces for gathering environmental noise * from the devices are: * + * void add_device_randomness(const void *buf, unsigned int size); * void add_input_randomness(unsigned int type, unsigned int code, * unsigned int value); * void add_interrupt_randomness(int irq, int irq_flags); * void add_disk_randomness(struct gendisk *disk); * + * add_device_randomness() is for adding data to the random pool that + * is likely to differ between two devices (or possibly even per boot). + * This would be things like MAC addresses or serial numbers, or the + * read-out of the RTC. This does *not* add any actual entropy to the + * pool, but it initializes the pool to different values for devices + * that might otherwise be identical and have very little entropy + * available to them (particularly common in the embedded world). + * * add_input_randomness() uses the input layer interrupt timing, as well as * the event type information from the hardware. * @@ -646,6 +655,25 @@ static void set_timer_rand_state(unsigned int irq, } #endif +/* + * Add device- or boot-specific data to the input and nonblocking + * pools to help initialize them to unique values. + * + * None of this adds any entropy, it is meant to avoid the + * problem of the nonblocking pool having similar initial state + * across largely identical devices. + */ +void add_device_randomness(const void *buf, unsigned int size) +{ + unsigned long time = get_cycles() ^ jiffies; + + mix_pool_bytes(&input_pool, buf, size, NULL); + mix_pool_bytes(&input_pool, &time, sizeof(time), NULL); + mix_pool_bytes(&nonblocking_pool, buf, size, NULL); + mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL); +} +EXPORT_SYMBOL(add_device_randomness); + static struct timer_rand_state input_timer_state; /* diff --git a/include/linux/random.h b/include/linux/random.h index 6ef39d7f2db1..e14b4387354a 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -50,6 +50,7 @@ struct rnd_state { extern void rand_initialize_irq(int irq); +extern void add_device_randomness(const void *, unsigned int); extern void add_input_randomness(unsigned int type, unsigned int code, unsigned int value); extern void add_interrupt_randomness(int irq, int irq_flags); -- GitLab From 76b9be5d7feba335f0bfd4edf0386296cdaf57f2 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 4 Jul 2012 11:22:20 -0400 Subject: [PATCH 0202/1799] usb: feed USB device information to the /dev/random driver commit b04b3156a20d395a7faa8eed98698d1e17a36000 upstream. Send the USB device's serial, product, and manufacturer strings to the /dev/random driver to help seed its pools. Cc: Linus Torvalds Acked-by: Greg KH Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6241b717042d..e727b876726c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -1951,6 +1952,14 @@ int usb_new_device(struct usb_device *udev) /* Tell the world! */ announce_device(udev); + if (udev->serial) + add_device_randomness(udev->serial, strlen(udev->serial)); + if (udev->product) + add_device_randomness(udev->product, strlen(udev->product)); + if (udev->manufacturer) + add_device_randomness(udev->manufacturer, + strlen(udev->manufacturer)); + device_enable_async_suspend(&udev->dev); /* -- GitLab From e48fa33d22f6a28b57ade6522230755eae394548 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 4 Jul 2012 21:23:25 -0400 Subject: [PATCH 0203/1799] net: feed /dev/random with the MAC address when registering a device commit 7bf2357524408b97fec58344caf7397f8140c3fd upstream. Signed-off-by: "Theodore Ts'o" Cc: David Miller Cc: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 3 +++ net/core/rtnetlink.c | 1 + 2 files changed, 4 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index 533c586c64db..c299416d0e89 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1173,6 +1173,7 @@ static int __dev_open(struct net_device *dev) net_dmaengine_get(); dev_set_rx_mode(dev); dev_activate(dev); + add_device_randomness(dev->dev_addr, dev->addr_len); } return ret; @@ -4765,6 +4766,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) err = ops->ndo_set_mac_address(dev, sa); if (!err) call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + add_device_randomness(dev->dev_addr, dev->addr_len); return err; } EXPORT_SYMBOL(dev_set_mac_address); @@ -5543,6 +5545,7 @@ int register_netdevice(struct net_device *dev) dev_init_scheduler(dev); dev_hold(dev); list_netdevice(dev); + add_device_randomness(dev->dev_addr, dev->addr_len); /* Notify protocols, that a new device appeared. */ ret = call_netdevice_notifiers(NETDEV_REGISTER, dev); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index b8052bab69ca..900fc6162c42 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1376,6 +1376,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, goto errout; send_addr_notify = 1; modified = 1; + add_device_randomness(dev->dev_addr, dev->addr_len); } if (tb[IFLA_MTU]) { -- GitLab From f5caa70697d4da107f8fd33fe74977a8ec192aaf Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 5 Jul 2012 10:21:01 -0400 Subject: [PATCH 0204/1799] random: use the arch-specific rng in xfer_secondary_pool commit e6d4947b12e8ad947add1032dd754803c6004824 upstream. If the CPU supports a hardware random number generator, use it in xfer_secondary_pool(), where it will significantly improve things and where we can afford it. Also, remove the use of the arch-specific rng in add_timer_randomness(), since the call is significantly slower than get_cycles(), and we're much better off using it in xfer_secondary_pool() anyway. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- drivers/char/random.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 0b22268207b5..2296ff162316 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -254,6 +254,7 @@ #include #include #include +#include #ifdef CONFIG_GENERIC_HARDIRQS # include @@ -702,11 +703,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) goto out; sample.jiffies = jiffies; - - /* Use arch random value, fall back to cycles */ - if (!arch_get_random_int(&sample.cycles)) - sample.cycles = get_cycles(); - + sample.cycles = get_cycles(); sample.num = num; mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL); @@ -838,7 +835,11 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, */ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) { - __u32 tmp[OUTPUT_POOL_WORDS]; + union { + __u32 tmp[OUTPUT_POOL_WORDS]; + long hwrand[4]; + } u; + int i; if (r->pull && r->entropy_count < nbytes * 8 && r->entropy_count < r->poolinfo->POOLBITS) { @@ -849,17 +850,23 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) /* pull at least as many as BYTES as wakeup BITS */ bytes = max_t(int, bytes, random_read_wakeup_thresh / 8); /* but never more than the buffer size */ - bytes = min_t(int, bytes, sizeof(tmp)); + bytes = min_t(int, bytes, sizeof(u.tmp)); DEBUG_ENT("going to reseed %s with %d bits " "(%d of %d requested)\n", r->name, bytes * 8, nbytes * 8, r->entropy_count); - bytes = extract_entropy(r->pull, tmp, bytes, + bytes = extract_entropy(r->pull, u.tmp, bytes, random_read_wakeup_thresh / 8, rsvd); - mix_pool_bytes(r, tmp, bytes, NULL); + mix_pool_bytes(r, u.tmp, bytes, NULL); credit_entropy_bits(r, bytes*8); } + kmemcheck_mark_initialized(&u.hwrand, sizeof(u.hwrand)); + for (i = 0; i < 4; i++) + if (arch_get_random_long(&u.hwrand[i])) + break; + if (i) + mix_pool_bytes(r, &u.hwrand, sizeof(u.hwrand), 0); } /* -- GitLab From 29aef9dee78ac45c5bd7f91434b05144ec220abd Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 5 Jul 2012 10:35:23 -0400 Subject: [PATCH 0205/1799] random: add new get_random_bytes_arch() function commit c2557a303ab6712bb6e09447df828c557c710ac9 upstream. Create a new function, get_random_bytes_arch() which will use the architecture-specific hardware random number generator if it is present. Change get_random_bytes() to not use the HW RNG, even if it is avaiable. The reason for this is that the hw random number generator is fast (if it is present), but it requires that we trust the hardware manufacturer to have not put in a back door. (For example, an increasing counter encrypted by an AES key known to the NSA.) It's unlikely that Intel (for example) was paid off by the US Government to do this, but it's impossible for them to prove otherwise --- especially since Bull Mountain is documented to use AES as a whitener. Hence, the output of an evil, trojan-horse version of RDRAND is statistically indistinguishable from an RDRAND implemented to the specifications claimed by Intel. Short of using a tunnelling electronic microscope to reverse engineer an Ivy Bridge chip and disassembling and analyzing the CPU microcode, there's no way for us to tell for sure. Since users of get_random_bytes() in the Linux kernel need to be able to support hardware systems where the HW RNG is not present, most time-sensitive users of this interface have already created their own cryptographic RNG interface which uses get_random_bytes() as a seed. So it's much better to use the HW RNG to improve the existing random number generator, by mixing in any entropy returned by the HW RNG into /dev/random's entropy pool, but to always _use_ /dev/random's entropy pool. This way we get almost of the benefits of the HW RNG without any potential liabilities. The only benefits we forgo is the speed/performance enhancements --- and generic kernel code can't depend on depend on get_random_bytes() having the speed of a HW RNG anyway. For those places that really want access to the arch-specific HW RNG, if it is available, we provide get_random_bytes_arch(). Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- drivers/char/random.c | 29 ++++++++++++++++++++++++----- include/linux/random.h | 1 + 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 2296ff162316..ed7e283b6cb5 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1038,17 +1038,34 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, /* * This function is the exported kernel interface. It returns some - * number of good random numbers, suitable for seeding TCP sequence - * numbers, etc. + * number of good random numbers, suitable for key generation, seeding + * TCP sequence numbers, etc. It does not use the hw random number + * generator, if available; use get_random_bytes_arch() for that. */ void get_random_bytes(void *buf, int nbytes) +{ + extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0); +} +EXPORT_SYMBOL(get_random_bytes); + +/* + * This function will use the architecture-specific hardware random + * number generator if it is available. The arch-specific hw RNG will + * almost certainly be faster than what we can do in software, but it + * is impossible to verify that it is implemented securely (as + * opposed, to, say, the AES encryption of a sequence number using a + * key known by the NSA). So it's useful if we need the speed, but + * only if we're willing to trust the hardware manufacturer not to + * have put in a back door. + */ +void get_random_bytes_arch(void *buf, int nbytes) { char *p = buf; while (nbytes) { unsigned long v; int chunk = min(nbytes, (int)sizeof(unsigned long)); - + if (!arch_get_random_long(&v)) break; @@ -1057,9 +1074,11 @@ void get_random_bytes(void *buf, int nbytes) nbytes -= chunk; } - extract_entropy(&nonblocking_pool, p, nbytes, 0, 0); + if (nbytes) + extract_entropy(&nonblocking_pool, p, nbytes, 0, 0); } -EXPORT_SYMBOL(get_random_bytes); +EXPORT_SYMBOL(get_random_bytes_arch); + /* * init_std_data - initialize pool with system data diff --git a/include/linux/random.h b/include/linux/random.h index e14b4387354a..29e217a7e6d0 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -56,6 +56,7 @@ extern void add_input_randomness(unsigned int type, unsigned int code, extern void add_interrupt_randomness(int irq, int irq_flags); extern void get_random_bytes(void *buf, int nbytes); +extern void get_random_bytes_arch(void *buf, int nbytes); void generate_random_uuid(unsigned char uuid_out[16]); #ifndef MODULE -- GitLab From 38e16fc638792ddc12da853c4836602a8708e166 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 4 Jul 2012 16:19:30 -0400 Subject: [PATCH 0206/1799] random: add tracepoints for easier debugging and verification commit 00ce1db1a634746040ace24c09a4e3a7949a3145 upstream. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- drivers/char/random.c | 26 ++++++- include/trace/events/random.h | 134 ++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 4 deletions(-) create mode 100644 include/trace/events/random.h diff --git a/drivers/char/random.c b/drivers/char/random.c index ed7e283b6cb5..45dd04702946 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -266,6 +266,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include + /* * Configuration information */ @@ -478,8 +481,8 @@ static __u32 const twist_table[8] = { * it's cheap to do so and helps slightly in the expected case where * the entropy is concentrated in the low-order bits. */ -static void __mix_pool_bytes(struct entropy_store *r, const void *in, - int nbytes, __u8 out[64]) +static void _mix_pool_bytes(struct entropy_store *r, const void *in, + int nbytes, __u8 out[64]) { unsigned long i, j, tap1, tap2, tap3, tap4, tap5; int input_rotate; @@ -531,13 +534,21 @@ static void __mix_pool_bytes(struct entropy_store *r, const void *in, ((__u32 *)out)[j] = r->pool[(i - j) & wordmask]; } -static void mix_pool_bytes(struct entropy_store *r, const void *in, +static void __mix_pool_bytes(struct entropy_store *r, const void *in, int nbytes, __u8 out[64]) +{ + trace_mix_pool_bytes_nolock(r->name, nbytes, _RET_IP_); + _mix_pool_bytes(r, in, nbytes, out); +} + +static void mix_pool_bytes(struct entropy_store *r, const void *in, + int nbytes, __u8 out[64]) { unsigned long flags; + trace_mix_pool_bytes(r->name, nbytes, _RET_IP_); spin_lock_irqsave(&r->lock, flags); - __mix_pool_bytes(r, in, nbytes, out); + _mix_pool_bytes(r, in, nbytes, out); spin_unlock_irqrestore(&r->lock, flags); } @@ -585,6 +596,7 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits) retry: entropy_count = orig = ACCESS_ONCE(r->entropy_count); entropy_count += nbits; + if (entropy_count < 0) { DEBUG_ENT("negative entropy/overflow\n"); entropy_count = 0; @@ -599,6 +611,9 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits) r->initialized = 1; } + trace_credit_entropy_bits(r->name, nbits, entropy_count, + r->entropy_total, _RET_IP_); + /* should we wake readers? */ if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) { wake_up_interruptible(&random_read_wait); @@ -971,6 +986,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, ssize_t ret = 0, i; __u8 tmp[EXTRACT_SIZE]; + trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); xfer_secondary_pool(r, nbytes); nbytes = account(r, nbytes, min, reserved); @@ -1005,6 +1021,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, ssize_t ret = 0, i; __u8 tmp[EXTRACT_SIZE]; + trace_extract_entropy_user(r->name, nbytes, r->entropy_count, _RET_IP_); xfer_secondary_pool(r, nbytes); nbytes = account(r, nbytes, 0, 0); @@ -1062,6 +1079,7 @@ void get_random_bytes_arch(void *buf, int nbytes) { char *p = buf; + trace_get_random_bytes(nbytes, _RET_IP_); while (nbytes) { unsigned long v; int chunk = min(nbytes, (int)sizeof(unsigned long)); diff --git a/include/trace/events/random.h b/include/trace/events/random.h new file mode 100644 index 000000000000..422df19de732 --- /dev/null +++ b/include/trace/events/random.h @@ -0,0 +1,134 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM random + +#if !defined(_TRACE_RANDOM_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_RANDOM_H + +#include +#include + +DECLARE_EVENT_CLASS(random__mix_pool_bytes, + TP_PROTO(const char *pool_name, int bytes, unsigned long IP), + + TP_ARGS(pool_name, bytes, IP), + + TP_STRUCT__entry( + __field( const char *, pool_name ) + __field( int, bytes ) + __field(unsigned long, IP ) + ), + + TP_fast_assign( + __entry->pool_name = pool_name; + __entry->bytes = bytes; + __entry->IP = IP; + ), + + TP_printk("%s pool: bytes %d caller %pF", + __entry->pool_name, __entry->bytes, (void *)__entry->IP) +); + +DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes, + TP_PROTO(const char *pool_name, int bytes, unsigned long IP), + + TP_ARGS(pool_name, bytes, IP) +); + +DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock, + TP_PROTO(const char *pool_name, int bytes, unsigned long IP), + + TP_ARGS(pool_name, bytes, IP) +); + +TRACE_EVENT(credit_entropy_bits, + TP_PROTO(const char *pool_name, int bits, int entropy_count, + int entropy_total, unsigned long IP), + + TP_ARGS(pool_name, bits, entropy_count, entropy_total, IP), + + TP_STRUCT__entry( + __field( const char *, pool_name ) + __field( int, bits ) + __field( int, entropy_count ) + __field( int, entropy_total ) + __field(unsigned long, IP ) + ), + + TP_fast_assign( + __entry->pool_name = pool_name; + __entry->bits = bits; + __entry->entropy_count = entropy_count; + __entry->entropy_total = entropy_total; + __entry->IP = IP; + ), + + TP_printk("%s pool: bits %d entropy_count %d entropy_total %d " + "caller %pF", __entry->pool_name, __entry->bits, + __entry->entropy_count, __entry->entropy_total, + (void *)__entry->IP) +); + +TRACE_EVENT(get_random_bytes, + TP_PROTO(int nbytes, unsigned long IP), + + TP_ARGS(nbytes, IP), + + TP_STRUCT__entry( + __field( int, nbytes ) + __field(unsigned long, IP ) + ), + + TP_fast_assign( + __entry->nbytes = nbytes; + __entry->IP = IP; + ), + + TP_printk("nbytes %d caller %pF", __entry->nbytes, (void *)__entry->IP) +); + +DECLARE_EVENT_CLASS(random__extract_entropy, + TP_PROTO(const char *pool_name, int nbytes, int entropy_count, + unsigned long IP), + + TP_ARGS(pool_name, nbytes, entropy_count, IP), + + TP_STRUCT__entry( + __field( const char *, pool_name ) + __field( int, nbytes ) + __field( int, entropy_count ) + __field(unsigned long, IP ) + ), + + TP_fast_assign( + __entry->pool_name = pool_name; + __entry->nbytes = nbytes; + __entry->entropy_count = entropy_count; + __entry->IP = IP; + ), + + TP_printk("%s pool: nbytes %d entropy_count %d caller %pF", + __entry->pool_name, __entry->nbytes, __entry->entropy_count, + (void *)__entry->IP) +); + + +DEFINE_EVENT(random__extract_entropy, extract_entropy, + TP_PROTO(const char *pool_name, int nbytes, int entropy_count, + unsigned long IP), + + TP_ARGS(pool_name, nbytes, entropy_count, IP) +); + +DEFINE_EVENT(random__extract_entropy, extract_entropy_user, + TP_PROTO(const char *pool_name, int nbytes, int entropy_count, + unsigned long IP), + + TP_ARGS(pool_name, nbytes, entropy_count, IP) +); + + + +#endif /* _TRACE_RANDOM_H */ + +/* This part must be outside protection */ +#include -- GitLab From ba6a40b952f6384eaec33af9f6c31d3a67ac073e Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 4 Jul 2012 11:32:48 -0400 Subject: [PATCH 0207/1799] MAINTAINERS: Theodore Ts'o is taking over the random driver commit 330e0a01d54c2b8606c56816f99af6ebc58ec92c upstream. Matt Mackall stepped down as the /dev/random driver maintainer last year, so Theodore Ts'o is taking back the /dev/random driver. Cc: Matt Mackall Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index b36270986501..a60009da7280 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5566,7 +5566,7 @@ F: Documentation/blockdev/ramdisk.txt F: drivers/block/brd.c RANDOM NUMBER DRIVER -M: Matt Mackall +M: Theodore Ts'o" S: Maintained F: drivers/char/random.c -- GitLab From ec947d6fbb66bc4e55eef7550b4fc835090a42be Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Jul 2012 20:19:17 +0000 Subject: [PATCH 0208/1799] rtc: wm831x: Feed the write counter into device_add_randomness() commit 9dccf55f4cb011a7552a8a2749a580662f5ed8ed upstream. The tamper evident features of the RTC include the "write counter" which is a pseudo-random number regenerated whenever we set the RTC. Since this value is unpredictable it should provide some useful seeding to the random number generator. Only do this on boot since the goal is to seed the pool rather than add useful entropy. Signed-off-by: Mark Brown Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-wm831x.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 3b6e6a67e765..41c06fe5415c 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c @@ -24,7 +24,7 @@ #include #include #include - +#include /* * R16416 (0x4020) - RTC Write Counter @@ -96,6 +96,26 @@ struct wm831x_rtc { unsigned int alarm_enabled:1; }; +static void wm831x_rtc_add_randomness(struct wm831x *wm831x) +{ + int ret; + u16 reg; + + /* + * The write counter contains a pseudo-random number which is + * regenerated every time we set the RTC so it should be a + * useful per-system source of entropy. + */ + ret = wm831x_reg_read(wm831x, WM831X_RTC_WRITE_COUNTER); + if (ret >= 0) { + reg = ret; + add_device_randomness(®, sizeof(reg)); + } else { + dev_warn(wm831x->dev, "Failed to read RTC write counter: %d\n", + ret); + } +} + /* * Read current time and date in RTC */ @@ -431,6 +451,8 @@ static int wm831x_rtc_probe(struct platform_device *pdev) alm_irq, ret); } + wm831x_rtc_add_randomness(wm831x); + return 0; err: -- GitLab From 12dae51a7567bb1e583ee0de6af538db256504db Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Jul 2012 20:23:21 +0000 Subject: [PATCH 0209/1799] mfd: wm831x: Feed the device UUID into device_add_randomness() commit 27130f0cc3ab97560384da437e4621fc4e94f21c upstream. wm831x devices contain a unique ID value. Feed this into the newly added device_add_randomness() to add some per device seed data to the pool. Signed-off-by: Mark Brown Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/wm831x-otp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mfd/wm831x-otp.c b/drivers/mfd/wm831x-otp.c index f742745ff354..b90f3e06b6c9 100644 --- a/drivers/mfd/wm831x-otp.c +++ b/drivers/mfd/wm831x-otp.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -66,6 +67,7 @@ static DEVICE_ATTR(unique_id, 0444, wm831x_unique_id_show, NULL); int wm831x_otp_init(struct wm831x *wm831x) { + char uuid[WM831X_UNIQUE_ID_LEN]; int ret; ret = device_create_file(wm831x->dev, &dev_attr_unique_id); @@ -73,6 +75,12 @@ int wm831x_otp_init(struct wm831x *wm831x) dev_err(wm831x->dev, "Unique ID attribute not created: %d\n", ret); + ret = wm831x_unique_id_read(wm831x, uuid); + if (ret == 0) + add_device_randomness(uuid, sizeof(uuid)); + else + dev_err(wm831x->dev, "Failed to read UUID: %d\n", ret); + return ret; } -- GitLab From 26665db4f7fa71c56eeb9205e79927cfc21e70c4 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 14 Jul 2012 20:27:52 -0400 Subject: [PATCH 0210/1799] random: remove rand_initialize_irq() commit c5857ccf293968348e5eb4ebedc68074de3dcda6 upstream. With the new interrupt sampling system, we are no longer using the timer_rand_state structure in the irq descriptor, so we can stop initializing it now. [ Merged in fixes from Sedat to find some last missing references to rand_initialize_irq() ] Signed-off-by: "Theodore Ts'o" Signed-off-by: Sedat Dilek Signed-off-by: Greg Kroah-Hartman --- arch/ia64/kernel/irq_ia64.c | 1 - drivers/char/random.c | 55 ------------------------------------- drivers/mfd/ab3100-core.c | 3 -- include/linux/irqdesc.h | 1 - include/linux/random.h | 2 -- kernel/irq/manage.c | 17 ------------ 6 files changed, 79 deletions(-) diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 5c3e0888265a..1034884b77da 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -23,7 +23,6 @@ #include #include #include -#include /* for rand_initialize_irq() */ #include #include #include diff --git a/drivers/char/random.c b/drivers/char/random.c index 45dd04702946..e08be062023f 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -634,43 +634,6 @@ struct timer_rand_state { unsigned dont_count_entropy:1; }; -#ifndef CONFIG_GENERIC_HARDIRQS - -static struct timer_rand_state *irq_timer_state[NR_IRQS]; - -static struct timer_rand_state *get_timer_rand_state(unsigned int irq) -{ - return irq_timer_state[irq]; -} - -static void set_timer_rand_state(unsigned int irq, - struct timer_rand_state *state) -{ - irq_timer_state[irq] = state; -} - -#else - -static struct timer_rand_state *get_timer_rand_state(unsigned int irq) -{ - struct irq_desc *desc; - - desc = irq_to_desc(irq); - - return desc->timer_rand_state; -} - -static void set_timer_rand_state(unsigned int irq, - struct timer_rand_state *state) -{ - struct irq_desc *desc; - - desc = irq_to_desc(irq); - - desc->timer_rand_state = state; -} -#endif - /* * Add device- or boot-specific data to the input and nonblocking * pools to help initialize them to unique values. @@ -1133,24 +1096,6 @@ static int rand_initialize(void) } module_init(rand_initialize); -void rand_initialize_irq(int irq) -{ - struct timer_rand_state *state; - - state = get_timer_rand_state(irq); - - if (state) - return; - - /* - * If kzalloc returns null, we just won't use that entropy - * source. - */ - state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL); - if (state) - set_timer_rand_state(irq, state); -} - #ifdef CONFIG_BLOCK void rand_initialize_disk(struct gendisk *disk) { diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 9522d6bda4f7..1287645b984d 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -931,9 +931,6 @@ static int __devinit ab3100_probe(struct i2c_client *client, err = request_threaded_irq(client->irq, NULL, ab3100_irq_handler, IRQF_ONESHOT, "ab3100-core", ab3100); - /* This real unpredictable IRQ is of course sampled for entropy */ - rand_initialize_irq(client->irq); - if (err) goto exit_no_irq; diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index f1e2527006bd..9a323d12de1c 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -39,7 +39,6 @@ struct module; */ struct irq_desc { struct irq_data irq_data; - struct timer_rand_state *timer_rand_state; unsigned int __percpu *kstat_irqs; irq_flow_handler_t handle_irq; #ifdef CONFIG_IRQ_PREFLOW_FASTEOI diff --git a/include/linux/random.h b/include/linux/random.h index 29e217a7e6d0..ac621ce886ca 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -48,8 +48,6 @@ struct rnd_state { #ifdef __KERNEL__ -extern void rand_initialize_irq(int irq); - extern void add_device_randomness(const void *, unsigned int); extern void add_input_randomness(unsigned int type, unsigned int code, unsigned int value); diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 89a3ea82569b..b9d1d83ec381 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -890,22 +890,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) return -ENOSYS; if (!try_module_get(desc->owner)) return -ENODEV; - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & IRQF_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * Yes, this might clear the entropy pool if the wrong - * driver is attempted to be loaded, without actually - * installing a new handler, but is this really a problem, - * only the sysadmin is able to do this. - */ - rand_initialize_irq(irq); - } /* * Check whether the interrupt nests into another interrupt @@ -1339,7 +1323,6 @@ EXPORT_SYMBOL(free_irq); * Flags: * * IRQF_SHARED Interrupt is shared - * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy * IRQF_TRIGGER_* Specify active edge(s) or level * */ -- GitLab From 73e62ae900d632d1bee9ab96c22508f8947da91a Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Mon, 23 Jul 2012 09:47:57 -0700 Subject: [PATCH 0211/1799] random: Add comment to random_initialize() commit cbc96b7594b5691d61eba2db8b2ea723645be9ca upstream. Many platforms have per-machine instance data (serial numbers, asset tags, etc.) squirreled away in areas that are accessed during early system bringup. Mixing this data into the random pools has a very high value in providing better random data, so we should allow (and even encourage) architecture code to call add_device_randomness() from the setup_arch() paths. However, this limits our options for internal structure of the random driver since random_initialize() is not called until long after setup_arch(). Add a big fat comment to rand_initialize() spelling out this requirement. Suggested-by: Theodore Ts'o Signed-off-by: Tony Luck Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- drivers/char/random.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/char/random.c b/drivers/char/random.c index e08be062023f..9d8bcd50baf5 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1087,6 +1087,16 @@ static void init_std_data(struct entropy_store *r) mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL); } +/* + * Note that setup_arch() may call add_device_randomness() + * long before we get here. This allows seeding of the pools + * with some platform dependent data very early in the boot + * process. But it limits our options here. We must use + * statically allocated structures that already have all + * initializations complete at compile time. We should also + * take care not to overwrite the precious per platform data + * we were given. + */ static int rand_initialize(void) { init_std_data(&input_pool); -- GitLab From af2eb889f75b4206de39ea86f4f154498a9327f3 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Fri, 20 Jul 2012 13:15:20 -0700 Subject: [PATCH 0212/1799] dmi: Feed DMI table to /dev/random driver commit d114a33387472555188f142ed8e98acdb8181c6d upstream. Send the entire DMI (SMBIOS) table to the /dev/random driver to help seed its pools. Signed-off-by: Tony Luck Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/dmi_scan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 153980be4ee6..b298158cb922 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -6,6 +6,7 @@ #include #include #include +#include #include /* @@ -111,6 +112,8 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *, dmi_table(buf, dmi_len, dmi_num, decode, NULL); + add_device_randomness(buf, dmi_len); + dmi_iounmap(buf, dmi_len); return 0; } -- GitLab From 7d696f0636c31f81d5cb613d45114d43896cfdb0 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 27 Jul 2012 22:26:08 -0400 Subject: [PATCH 0213/1799] random: mix in architectural randomness in extract_buf() commit d2e7c96af1e54b507ae2a6a7dd2baf588417a7e5 upstream. Mix in any architectural randomness in extract_buf() instead of xfer_secondary_buf(). This allows us to mix in more architectural randomness, and it also makes xfer_secondary_buf() faster, moving a tiny bit of additional CPU overhead to process which is extracting the randomness. [ Commit description modified by tytso to remove an extended advertisement for the RDRAND instruction. ] Signed-off-by: H. Peter Anvin Acked-by: Ingo Molnar Cc: DJ Johnston Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- drivers/char/random.c | 56 ++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 9d8bcd50baf5..d98b2a614cc8 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -277,6 +277,8 @@ #define SEC_XFER_SIZE 512 #define EXTRACT_SIZE 10 +#define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long)) + /* * The minimum number of bits of entropy before we wake up a read on * /dev/random. Should be enough to do a significant reseed. @@ -813,11 +815,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, */ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) { - union { - __u32 tmp[OUTPUT_POOL_WORDS]; - long hwrand[4]; - } u; - int i; + __u32 tmp[OUTPUT_POOL_WORDS]; if (r->pull && r->entropy_count < nbytes * 8 && r->entropy_count < r->poolinfo->POOLBITS) { @@ -828,23 +826,17 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) /* pull at least as many as BYTES as wakeup BITS */ bytes = max_t(int, bytes, random_read_wakeup_thresh / 8); /* but never more than the buffer size */ - bytes = min_t(int, bytes, sizeof(u.tmp)); + bytes = min_t(int, bytes, sizeof(tmp)); DEBUG_ENT("going to reseed %s with %d bits " "(%d of %d requested)\n", r->name, bytes * 8, nbytes * 8, r->entropy_count); - bytes = extract_entropy(r->pull, u.tmp, bytes, + bytes = extract_entropy(r->pull, tmp, bytes, random_read_wakeup_thresh / 8, rsvd); - mix_pool_bytes(r, u.tmp, bytes, NULL); + mix_pool_bytes(r, tmp, bytes, NULL); credit_entropy_bits(r, bytes*8); } - kmemcheck_mark_initialized(&u.hwrand, sizeof(u.hwrand)); - for (i = 0; i < 4; i++) - if (arch_get_random_long(&u.hwrand[i])) - break; - if (i) - mix_pool_bytes(r, &u.hwrand, sizeof(u.hwrand), 0); } /* @@ -901,15 +893,19 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, static void extract_buf(struct entropy_store *r, __u8 *out) { int i; - __u32 hash[5], workspace[SHA_WORKSPACE_WORDS]; + union { + __u32 w[5]; + unsigned long l[LONGS(EXTRACT_SIZE)]; + } hash; + __u32 workspace[SHA_WORKSPACE_WORDS]; __u8 extract[64]; unsigned long flags; /* Generate a hash across the pool, 16 words (512 bits) at a time */ - sha_init(hash); + sha_init(hash.w); spin_lock_irqsave(&r->lock, flags); for (i = 0; i < r->poolinfo->poolwords; i += 16) - sha_transform(hash, (__u8 *)(r->pool + i), workspace); + sha_transform(hash.w, (__u8 *)(r->pool + i), workspace); /* * We mix the hash back into the pool to prevent backtracking @@ -920,14 +916,14 @@ static void extract_buf(struct entropy_store *r, __u8 *out) * brute-forcing the feedback as hard as brute-forcing the * hash. */ - __mix_pool_bytes(r, hash, sizeof(hash), extract); + __mix_pool_bytes(r, hash.w, sizeof(hash.w), extract); spin_unlock_irqrestore(&r->lock, flags); /* * To avoid duplicates, we atomically extract a portion of the * pool while mixing, and hash one final time. */ - sha_transform(hash, extract, workspace); + sha_transform(hash.w, extract, workspace); memset(extract, 0, sizeof(extract)); memset(workspace, 0, sizeof(workspace)); @@ -936,11 +932,23 @@ static void extract_buf(struct entropy_store *r, __u8 *out) * pattern, we fold it in half. Thus, we always feed back * twice as much data as we output. */ - hash[0] ^= hash[3]; - hash[1] ^= hash[4]; - hash[2] ^= rol32(hash[2], 16); - memcpy(out, hash, EXTRACT_SIZE); - memset(hash, 0, sizeof(hash)); + hash.w[0] ^= hash.w[3]; + hash.w[1] ^= hash.w[4]; + hash.w[2] ^= rol32(hash.w[2], 16); + + /* + * If we have a architectural hardware random number + * generator, mix that in, too. + */ + for (i = 0; i < LONGS(EXTRACT_SIZE); i++) { + unsigned long v; + if (!arch_get_random_long(&v)) + break; + hash.l[i] ^= v; + } + + memcpy(out, &hash, EXTRACT_SIZE); + memset(&hash, 0, sizeof(hash)); } static ssize_t extract_entropy(struct entropy_store *r, void *buf, -- GitLab From 20e24cb2c6a9d72c2b1627ddd54584ec87b54082 Mon Sep 17 00:00:00 2001 From: Austin Hendrix Date: Mon, 4 Jun 2012 15:27:51 -0700 Subject: [PATCH 0214/1799] HID: multitouch: add support for Novatek touchscreen commit 4db703ead4535792ea54dba7275fdd1527848e74 upstream. Add support for a Novatek touchscreen panel as a generic HID multitouch panel. Signed-off-by: Austin Hendrix Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-multitouch.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index bb1abf83798b..18613d429cd9 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -567,6 +567,9 @@ #define USB_VENDOR_ID_NINTENDO 0x057e #define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306 +#define USB_VENDOR_ID_NOVATEK 0x0603 +#define USB_DEVICE_ID_NOVATEK_PCT 0x0600 + #define USB_VENDOR_ID_NTRIG 0x1b96 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index a6197f572039..e754dff1da5f 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -940,6 +940,11 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC, USB_DEVICE_ID_PANABOARD_UBT880) }, + /* Novatek Panel */ + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_NOVATEK, + USB_DEVICE_ID_NOVATEK_PCT) }, + /* PenMount panels */ { .driver_data = MT_CLS_CONFIDENCE, HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, -- GitLab From 21bba6e1209f246ee7fd71daf7cde00aa4564832 Mon Sep 17 00:00:00 2001 From: Lionel Vaux Date: Sun, 22 Jul 2012 11:32:20 +0200 Subject: [PATCH 0215/1799] HID: add support for Cypress barcode scanner 04B4:ED81 commit 76c9d8fe2c7fc34ffc387d8022c5828d6ff9df48 upstream. Add yet another device to the list of Cypress barcode scanners needing the CP_RDESC_SWAPPED_MIN_MAX quirk. Signed-off-by: Lionel Vaux (iouri) Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-cypress.c | 2 ++ drivers/hid/hid-ids.h | 1 + 3 files changed, 4 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 973c238eb9f6..64587af1c028 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1410,6 +1410,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c index 2f0be4c66af7..9e43aaca9774 100644 --- a/drivers/hid/hid-cypress.c +++ b/drivers/hid/hid-cypress.c @@ -129,6 +129,8 @@ static const struct hid_device_id cp_devices[] = { .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3), .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4), + .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE), .driver_data = CP_2WHEEL_MOUSE_HACK }, { } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 18613d429cd9..6e303e1b8f21 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -231,6 +231,7 @@ #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 #define USB_DEVICE_ID_CYPRESS_BARCODE_3 0xbca1 +#define USB_DEVICE_ID_CYPRESS_BARCODE_4 0xed81 #define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001 #define USB_VENDOR_ID_DEALEXTREAME 0x10c5 -- GitLab From 575b5ea19669112f9f7a7e2c09e9cdb914f4683e Mon Sep 17 00:00:00 2001 From: Cyrus Lien Date: Mon, 23 Jul 2012 17:11:51 +0800 Subject: [PATCH 0216/1799] HID: add ASUS AIO keyboard model AK1D commit 2d8767bb421574dfcf48e4be0751ce7d8f73d5d7 upstream. Add Asus All-In-One PC keyboard model AK1D. BugLink: https://bugs.launchpad.net/bugs/1027789 Signed-off-by: Cyrus Lien Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-chicony.c | 1 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c index b99af346fdff..a2abb8e15727 100644 --- a/drivers/hid/hid-chicony.c +++ b/drivers/hid/hid-chicony.c @@ -60,6 +60,7 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi, static const struct hid_device_id ch_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, { } }; MODULE_DEVICE_TABLE(hid, ch_devices); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 64587af1c028..41d4437411c3 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1404,6 +1404,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 6e303e1b8f21..41ad6ff548ce 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -202,6 +202,7 @@ #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d #define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 #define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123 +#define USB_DEVICE_ID_CHICONY_AK1D 0x1125 #define USB_VENDOR_ID_CHUNGHWAT 0x2247 #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 -- GitLab From a434a3c014dfc52d07efa7817f1339124300aed4 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Sun, 6 May 2012 11:11:04 -0600 Subject: [PATCH 0217/1799] x86, microcode: microcode_core.c simple_strtoul cleanup commit e826abd523913f63eb03b59746ffb16153c53dc4 upstream. Change reload_for_cpu() in kernel/microcode_core.c to call kstrtoul() instead of calling obsoleted simple_strtoul(). Signed-off-by: Shuah Khan Reviewed-by: Borislav Petkov Link: http://lkml.kernel.org/r/1336324264.2897.9.camel@lorien2 Signed-off-by: H. Peter Anvin Cc: Henrique de Moraes Holschuh Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/microcode_core.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index c9bda6d6035c..fbdfc6917180 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -299,12 +299,11 @@ static ssize_t reload_store(struct device *dev, { unsigned long val; int cpu = dev->id; - int ret = 0; - char *end; + ssize_t ret = 0; - val = simple_strtoul(buf, &end, 0); - if (end == buf) - return -EINVAL; + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; if (val == 1) { get_online_cpus(); -- GitLab From a05f127752f743db1b53e0309977573566ce5b6f Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 21 Jun 2012 14:07:16 +0200 Subject: [PATCH 0218/1799] x86, microcode: Sanitize per-cpu microcode reloading interface commit c9fc3f778a6a215ace14ee556067c73982b6d40f upstream. Microcode reloading in a per-core manner is a very bad idea for both major x86 vendors. And the thing is, we have such interface with which we can end up with different microcode versions applied on different cores of an otherwise homogeneous wrt (family,model,stepping) system. So turn off the possibility of doing that per core and allow it only system-wide. This is a minimal fix which we'd like to see in stable too thus the more-or-less arbitrary decision to allow system-wide reloading only on the BSP: $ echo 1 > /sys/devices/system/cpu/cpu0/microcode/reload ... and disable the interface on the other cores: $ echo 1 > /sys/devices/system/cpu/cpu23/microcode/reload -bash: echo: write error: Invalid argument Also, allowing the reload only from one CPU (the BSP in that case) doesn't allow the reload procedure to degenerate into an O(n^2) deal when triggering reloads from all /sys/devices/system/cpu/cpuX/microcode/reload sysfs nodes simultaneously. A more generic fix will follow. Signed-off-by: Borislav Petkov Cc: Henrique de Moraes Holschuh Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1340280437-7718-2-git-send-email-bp@amd64.org Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/microcode_core.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index fbdfc6917180..24b852b61be3 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -298,19 +298,31 @@ static ssize_t reload_store(struct device *dev, const char *buf, size_t size) { unsigned long val; - int cpu = dev->id; - ssize_t ret = 0; + int cpu; + ssize_t ret = 0, tmp_ret; + + /* allow reload only from the BSP */ + if (boot_cpu_data.cpu_index != dev->id) + return -EINVAL; ret = kstrtoul(buf, 0, &val); if (ret) return ret; - if (val == 1) { - get_online_cpus(); - if (cpu_online(cpu)) - ret = reload_for_cpu(cpu); - put_online_cpus(); + if (val != 1) + return size; + + get_online_cpus(); + for_each_online_cpu(cpu) { + tmp_ret = reload_for_cpu(cpu); + if (tmp_ret != 0) + pr_warn("Error reloading microcode on CPU %d\n", cpu); + + /* save retval of the first encountered reload error */ + if (!ret) + ret = tmp_ret; } + put_online_cpus(); if (!ret) ret = size; -- GitLab From 49ca240411df57586fecddd1152ff30cbef82d59 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 31 Jul 2012 16:46:20 -0700 Subject: [PATCH 0219/1799] mm: hugetlbfs: close race during teardown of hugetlbfs shared page tables commit d833352a4338dc31295ed832a30c9ccff5c7a183 upstream. If a process creates a large hugetlbfs mapping that is eligible for page table sharing and forks heavily with children some of whom fault and others which destroy the mapping then it is possible for page tables to get corrupted. Some teardowns of the mapping encounter a "bad pmd" and output a message to the kernel log. The final teardown will trigger a BUG_ON in mm/filemap.c. This was reproduced in 3.4 but is known to have existed for a long time and goes back at least as far as 2.6.37. It was probably was introduced in 2.6.20 by [39dde65c: shared page table for hugetlb page]. The messages look like this; [ ..........] Lots of bad pmd messages followed by this [ 127.164256] mm/memory.c:391: bad pmd ffff880412e04fe8(80000003de4000e7). [ 127.164257] mm/memory.c:391: bad pmd ffff880412e04ff0(80000003de6000e7). [ 127.164258] mm/memory.c:391: bad pmd ffff880412e04ff8(80000003de0000e7). [ 127.186778] ------------[ cut here ]------------ [ 127.186781] kernel BUG at mm/filemap.c:134! [ 127.186782] invalid opcode: 0000 [#1] SMP [ 127.186783] CPU 7 [ 127.186784] Modules linked in: af_packet cpufreq_conservative cpufreq_userspace cpufreq_powersave acpi_cpufreq mperf ext3 jbd dm_mod coretemp crc32c_intel usb_storage ghash_clmulni_intel aesni_intel i2c_i801 r8169 mii uas sr_mod cdrom sg iTCO_wdt iTCO_vendor_support shpchp serio_raw cryptd aes_x86_64 e1000e pci_hotplug dcdbas aes_generic container microcode ext4 mbcache jbd2 crc16 sd_mod crc_t10dif i915 drm_kms_helper drm i2c_algo_bit ehci_hcd ahci libahci usbcore rtc_cmos usb_common button i2c_core intel_agp video intel_gtt fan processor thermal thermal_sys hwmon ata_generic pata_atiixp libata scsi_mod [ 127.186801] [ 127.186802] Pid: 9017, comm: hugetlbfs-test Not tainted 3.4.0-autobuild #53 Dell Inc. OptiPlex 990/06D7TR [ 127.186804] RIP: 0010:[] [] __delete_from_page_cache+0x15e/0x160 [ 127.186809] RSP: 0000:ffff8804144b5c08 EFLAGS: 00010002 [ 127.186810] RAX: 0000000000000001 RBX: ffffea000a5c9000 RCX: 00000000ffffffc0 [ 127.186811] RDX: 0000000000000000 RSI: 0000000000000009 RDI: ffff88042dfdad00 [ 127.186812] RBP: ffff8804144b5c18 R08: 0000000000000009 R09: 0000000000000003 [ 127.186813] R10: 0000000000000000 R11: 000000000000002d R12: ffff880412ff83d8 [ 127.186814] R13: ffff880412ff83d8 R14: 0000000000000000 R15: ffff880412ff83d8 [ 127.186815] FS: 00007fe18ed2c700(0000) GS:ffff88042dce0000(0000) knlGS:0000000000000000 [ 127.186816] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 127.186817] CR2: 00007fe340000503 CR3: 0000000417a14000 CR4: 00000000000407e0 [ 127.186818] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 127.186819] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 127.186820] Process hugetlbfs-test (pid: 9017, threadinfo ffff8804144b4000, task ffff880417f803c0) [ 127.186821] Stack: [ 127.186822] ffffea000a5c9000 0000000000000000 ffff8804144b5c48 ffffffff810ed83b [ 127.186824] ffff8804144b5c48 000000000000138a 0000000000001387 ffff8804144b5c98 [ 127.186825] ffff8804144b5d48 ffffffff811bc925 ffff8804144b5cb8 0000000000000000 [ 127.186827] Call Trace: [ 127.186829] [] delete_from_page_cache+0x3b/0x80 [ 127.186832] [] truncate_hugepages+0x115/0x220 [ 127.186834] [] hugetlbfs_evict_inode+0x13/0x30 [ 127.186837] [] evict+0xa7/0x1b0 [ 127.186839] [] iput_final+0xd3/0x1f0 [ 127.186840] [] iput+0x39/0x50 [ 127.186842] [] d_kill+0xf8/0x130 [ 127.186843] [] dput+0xd2/0x1a0 [ 127.186845] [] __fput+0x170/0x230 [ 127.186848] [] ? rb_erase+0xce/0x150 [ 127.186849] [] fput+0x1d/0x30 [ 127.186851] [] remove_vma+0x37/0x80 [ 127.186853] [] do_munmap+0x2d2/0x360 [ 127.186855] [] sys_shmdt+0xc9/0x170 [ 127.186857] [] system_call_fastpath+0x16/0x1b [ 127.186858] Code: 0f 1f 44 00 00 48 8b 43 08 48 8b 00 48 8b 40 28 8b b0 40 03 00 00 85 f6 0f 88 df fe ff ff 48 89 df e8 e7 cb 05 00 e9 d2 fe ff ff <0f> 0b 55 83 e2 fd 48 89 e5 48 83 ec 30 48 89 5d d8 4c 89 65 e0 [ 127.186868] RIP [] __delete_from_page_cache+0x15e/0x160 [ 127.186870] RSP [ 127.186871] ---[ end trace 7cbac5d1db69f426 ]--- The bug is a race and not always easy to reproduce. To reproduce it I was doing the following on a single socket I7-based machine with 16G of RAM. $ hugeadm --pool-pages-max DEFAULT:13G $ echo $((18*1048576*1024)) > /proc/sys/kernel/shmmax $ echo $((18*1048576*1024)) > /proc/sys/kernel/shmall $ for i in `seq 1 9000`; do ./hugetlbfs-test; done On my particular machine, it usually triggers within 10 minutes but enabling debug options can change the timing such that it never hits. Once the bug is triggered, the machine is in trouble and needs to be rebooted. The machine will respond but processes accessing proc like "ps aux" will hang due to the BUG_ON. shutdown will also hang and needs a hard reset or a sysrq-b. The basic problem is a race between page table sharing and teardown. For the most part page table sharing depends on i_mmap_mutex. In some cases, it is also taking the mm->page_table_lock for the PTE updates but with shared page tables, it is the i_mmap_mutex that is more important. Unfortunately it appears to be also insufficient. Consider the following situation Process A Process B --------- --------- hugetlb_fault shmdt LockWrite(mmap_sem) do_munmap unmap_region unmap_vmas unmap_single_vma unmap_hugepage_range Lock(i_mmap_mutex) Lock(mm->page_table_lock) huge_pmd_unshare/unmap tables <--- (1) Unlock(mm->page_table_lock) Unlock(i_mmap_mutex) huge_pte_alloc ... Lock(i_mmap_mutex) ... vma_prio_walk, find svma, spte ... Lock(mm->page_table_lock) ... share spte ... Unlock(mm->page_table_lock) ... Unlock(i_mmap_mutex) ... hugetlb_no_page <--- (2) free_pgtables unlink_file_vma hugetlb_free_pgd_range remove_vma_list In this scenario, it is possible for Process A to share page tables with Process B that is trying to tear them down. The i_mmap_mutex on its own does not prevent Process A walking Process B's page tables. At (1) above, the page tables are not shared yet so it unmaps the PMDs. Process A sets up page table sharing and at (2) faults a new entry. Process B then trips up on it in free_pgtables. This patch fixes the problem by adding a new function __unmap_hugepage_range_final that is only called when the VMA is about to be destroyed. This function clears VM_MAYSHARE during unmap_hugepage_range() under the i_mmap_mutex. This makes the VMA ineligible for sharing and avoids the race. Superficially this looks like it would then be vunerable to truncate and madvise issues but hugetlbfs has its own truncate handlers so does not use unmap_mapping_range() and does not support madvise(DONTNEED). This should be treated as a -stable candidate if it is merged. Test program is as follows. The test case was mostly written by Michal Hocko with a few minor changes to reproduce this bug. ==== CUT HERE ==== static size_t huge_page_size = (2UL << 20); static size_t nr_huge_page_A = 512; static size_t nr_huge_page_B = 5632; unsigned int get_random(unsigned int max) { struct timeval tv; gettimeofday(&tv, NULL); srandom(tv.tv_usec); return random() % max; } static void play(void *addr, size_t size) { unsigned char *start = addr, *end = start + size, *a; start += get_random(size/2); /* we could itterate on huge pages but let's give it more time. */ for (a = start; a < end; a += 4096) *a = 0; } int main(int argc, char **argv) { key_t key = IPC_PRIVATE; size_t sizeA = nr_huge_page_A * huge_page_size; size_t sizeB = nr_huge_page_B * huge_page_size; int shmidA, shmidB; void *addrA = NULL, *addrB = NULL; int nr_children = 300, n = 0; if ((shmidA = shmget(key, sizeA, IPC_CREAT|SHM_HUGETLB|0660)) == -1) { perror("shmget:"); return 1; } if ((addrA = shmat(shmidA, addrA, SHM_R|SHM_W)) == (void *)-1UL) { perror("shmat"); return 1; } if ((shmidB = shmget(key, sizeB, IPC_CREAT|SHM_HUGETLB|0660)) == -1) { perror("shmget:"); return 1; } if ((addrB = shmat(shmidB, addrB, SHM_R|SHM_W)) == (void *)-1UL) { perror("shmat"); return 1; } fork_child: switch(fork()) { case 0: switch (n%3) { case 0: play(addrA, sizeA); break; case 1: play(addrB, sizeB); break; case 2: break; } break; case -1: perror("fork:"); break; default: if (++n < nr_children) goto fork_child; play(addrA, sizeA); break; } shmdt(addrA); shmdt(addrB); do { wait(NULL); } while (--n > 0); shmctl(shmidA, IPC_RMID, NULL); shmctl(shmidB, IPC_RMID, NULL); return 0; } [akpm@linux-foundation.org: name the declaration's args, fix CONFIG_HUGETLBFS=n build] Signed-off-by: Hugh Dickins Reviewed-by: Michal Hocko Signed-off-by: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/hugetlb.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 263e17703b31..a799df59d310 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2392,6 +2392,22 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, { mutex_lock(&vma->vm_file->f_mapping->i_mmap_mutex); __unmap_hugepage_range(vma, start, end, ref_page); + /* + * Clear this flag so that x86's huge_pmd_share page_table_shareable + * test will fail on a vma being torn down, and not grab a page table + * on its way out. We're lucky that the flag has such an appropriate + * name, and can in fact be safely cleared here. We could clear it + * before the __unmap_hugepage_range above, but all that's necessary + * is to clear it before releasing the i_mmap_mutex below. + * + * This works because in the contexts this is called, the VMA is + * going to be destroyed. It is not vunerable to madvise(DONTNEED) + * because madvise is not supported on hugetlbfs. The same applies + * for direct IO. unmap_hugepage_range() is only being called just + * before free_pgtables() so clearing VM_MAYSHARE will not cause + * surprises later. + */ + vma->vm_flags &= ~VM_MAYSHARE; mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex); } @@ -2958,9 +2974,14 @@ void hugetlb_change_protection(struct vm_area_struct *vma, } } spin_unlock(&mm->page_table_lock); - mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex); - + /* + * Must flush TLB before releasing i_mmap_mutex: x86's huge_pmd_unshare + * may have cleared our pud entry and done put_page on the page table: + * once we release i_mmap_mutex, another task can do the final put_page + * and that page table be reused and filled with junk. + */ flush_tlb_range(vma, start, end); + mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex); } int hugetlb_reserve_pages(struct inode *inode, -- GitLab From 74c90d4c3e5ee158cec2f6f32f6fb3cbfc0a2f47 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 16 Jul 2012 15:34:22 -0700 Subject: [PATCH 0220/1799] target: Add range checking to UNMAP emulation commit 2594e29865c291db162313187612cd9f14538f33 upstream. When processing an UNMAP command, we need to make sure that the number of blocks we're asked to UNMAP does not exceed our reported maximum number of blocks per UNMAP, and that the range of blocks we're unmapping doesn't go past the end of the device. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger [bwh: Backported to 3.2: adjust filename, context] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_cdb.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index fa323f8aa171..7e3135120bad 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -1053,6 +1053,18 @@ int target_emulate_unmap(struct se_task *task) pr_debug("UNMAP: Using lba: %llu and range: %u\n", (unsigned long long)lba, range); + if (range > dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count) { + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; + goto err; + } + + if (lba + range > dev->transport->get_blocks(dev) + 1) { + cmd->scsi_sense_reason = TCM_ADDRESS_OUT_OF_RANGE; + ret = -EINVAL; + goto err; + } + ret = dev->transport->do_discard(dev, lba, range); if (ret < 0) { pr_err("blkdev_issue_discard() failed: %d\n", -- GitLab From 6fb6469c601a80a0c883ec0be189ecf1677ecf56 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 16 Jul 2012 15:34:23 -0700 Subject: [PATCH 0221/1799] target: Fix reading of data length fields for UNMAP commands commit 1a5fa4576ec8a462313c7516b31d7453481ddbe8 upstream. The UNMAP DATA LENGTH and UNMAP BLOCK DESCRIPTOR DATA LENGTH fields are in the unmap descriptor (the payload transferred to our data out buffer), not in the CDB itself. Read them from the correct place in target_emulated_unmap. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger [bwh: Backported to 3.2: adjust filename, context] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_cdb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 7e3135120bad..2150d2af3dca 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -1022,7 +1022,6 @@ int target_emulate_unmap(struct se_task *task) struct se_cmd *cmd = task->task_se_cmd; struct se_device *dev = cmd->se_dev; unsigned char *buf, *ptr = NULL; - unsigned char *cdb = &cmd->t_task_cdb[0]; sector_t lba; unsigned int size = cmd->data_length, range; int ret = 0, offset; @@ -1038,11 +1037,12 @@ int target_emulate_unmap(struct se_task *task) /* First UNMAP block descriptor starts at 8 byte offset */ offset = 8; size -= 8; - dl = get_unaligned_be16(&cdb[0]); - bd_dl = get_unaligned_be16(&cdb[2]); buf = transport_kmap_data_sg(cmd); + dl = get_unaligned_be16(&buf[0]); + bd_dl = get_unaligned_be16(&buf[2]); + ptr = &buf[offset]; pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu" " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr); -- GitLab From c329e96ae86fb69c30287a434426f2083fb2430b Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 16 Jul 2012 15:34:24 -0700 Subject: [PATCH 0222/1799] target: Fix possible integer underflow in UNMAP emulation commit b7fc7f3777582dea85156a821d78a522a0c083aa upstream. It's possible for an initiator to send us an UNMAP command with a descriptor that is less than 8 bytes; in that case it's really bad for us to set an unsigned int to that value, subtract 8 from it, and then use that as a limit for our loop (since the value will wrap around to a huge positive value). Fix this by making size be signed and only looping if size >= 16 (ie if we have at least a full descriptor available). Also remove offset as an obfuscated name for the constant 8. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger [bwh: Backported to 3.2: adjust filename, context] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_cdb.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 2150d2af3dca..94d89f2b97d2 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -1023,9 +1023,10 @@ int target_emulate_unmap(struct se_task *task) struct se_device *dev = cmd->se_dev; unsigned char *buf, *ptr = NULL; sector_t lba; - unsigned int size = cmd->data_length, range; - int ret = 0, offset; - unsigned short dl, bd_dl; + int size = cmd->data_length; + u32 range; + int ret = 0; + int dl, bd_dl; if (!dev->transport->do_discard) { pr_err("UNMAP emulation not supported for: %s\n", @@ -1034,20 +1035,19 @@ int target_emulate_unmap(struct se_task *task) return -ENOSYS; } - /* First UNMAP block descriptor starts at 8 byte offset */ - offset = 8; - size -= 8; - buf = transport_kmap_data_sg(cmd); dl = get_unaligned_be16(&buf[0]); bd_dl = get_unaligned_be16(&buf[2]); - ptr = &buf[offset]; - pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu" + size = min(size - 8, bd_dl); + + /* First UNMAP block descriptor starts at 8 byte offset */ + ptr = &buf[8]; + pr_debug("UNMAP: Sub: %s Using dl: %u bd_dl: %u size: %u" " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr); - while (size) { + while (size >= 16) { lba = get_unaligned_be64(&ptr[0]); range = get_unaligned_be32(&ptr[8]); pr_debug("UNMAP: Using lba: %llu and range: %u\n", -- GitLab From 6213566323948ac7ed0aa4eb78058e77d445b0f8 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 16 Jul 2012 15:34:25 -0700 Subject: [PATCH 0223/1799] target: Check number of unmap descriptors against our limit commit 7409a6657aebf8be74c21d0eded80709b27275cb upstream. Fail UNMAP commands that have more than our reported limit on unmap descriptors. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger [bwh: Backported to 3.2: adjust filename] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_cdb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 94d89f2b97d2..52a5f6208acf 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -1041,6 +1041,11 @@ int target_emulate_unmap(struct se_task *task) bd_dl = get_unaligned_be16(&buf[2]); size = min(size - 8, bd_dl); + if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; + goto err; + } /* First UNMAP block descriptor starts at 8 byte offset */ ptr = &buf[8]; -- GitLab From 87a266d5801001c09687fb4d755e336bad733c10 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 3 Aug 2012 20:54:48 +0200 Subject: [PATCH 0224/1799] ARM: mxs: Remove MMAP_MIN_ADDR setting from mxs_defconfig commit 3bed491c8d28329e34f8a31e3fe64d03f3a350f1 upstream. The CONFIG_DEFAULT_MMAP_MIN_ADDR was set to 65536 in mxs_defconfig, this caused severe breakage of userland applications since the upper limit for ARM is 32768. By default CONFIG_DEFAULT_MMAP_MIN_ADDR is set to 4096 and can also be changed via /proc/sys/vm/mmap_min_addr if needed. Quoting Russell King [1]: "4096 is also fine for ARM too. There's not much point in having defconfigs change it - that would just be pure noise in the config files." the CONFIG_DEFAULT_MMAP_MIN_ADDR can be removed from the defconfig altogether. This problem was introduced by commit cde7c41 (ARM: configs: add defconfig for mach-mxs). [1] http://marc.info/?l=linux-arm-kernel&m=134401593807820&w=2 Signed-off-by: Marek Vasut Cc: Russell King Cc: Wolfgang Denk Signed-off-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- arch/arm/configs/mxs_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig index 1ebbf451c48d..70d0bf40c966 100644 --- a/arch/arm/configs/mxs_defconfig +++ b/arch/arm/configs/mxs_defconfig @@ -32,7 +32,6 @@ CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_PREEMPT_VOLUNTARY=y CONFIG_AEABI=y -CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 CONFIG_AUTO_ZRELADDR=y CONFIG_FPE_NWFPE=y CONFIG_NET=y -- GitLab From 0f27ec339c656ab8dc9255ac8a61a1cecd32d599 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 2 Aug 2012 22:48:39 +0800 Subject: [PATCH 0225/1799] ARM: dts: imx53-ard: add regulators for lan9220 commit 1eec0c569523782392b5e6245effddb626213b8c upstream. Since commit c7e963f (net/smsc911x: Add regulator support), the lan9220 device tree probe fails on imx53-ard board, because the commit makes VDD33A and VDDVARIO supplies mandatory for the driver. Add a fixed dummy 3V3 supplying lan9220 to fix the regression. Signed-off-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/dts/imx53-ard.dts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts index 2dccce46ed81..7541a91b8fab 100644 --- a/arch/arm/boot/dts/imx53-ard.dts +++ b/arch/arm/boot/dts/imx53-ard.dts @@ -70,10 +70,30 @@ lan9220@f4000000 { interrupt-parent = <&gpio2>; interrupts = <31>; reg-io-width = <4>; + /* + * VDD33A and VDDVARIO of LAN9220 are supplied by + * SW4_3V3 of LTC3589. Before the regulator driver + * for this PMIC is available, we use a fixed dummy + * 3V3 regulator to get LAN9220 driver probing work. + */ + vdd33a-supply = <®_3p3v>; + vddvario-supply = <®_3p3v>; smsc,irq-push-pull; }; }; + regulators { + compatible = "simple-bus"; + + reg_3p3v: 3p3v { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; + gpio-keys { compatible = "gpio-keys"; -- GitLab From 5784dff6267c788b40a2c9931b13a079e9011936 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sun, 5 Aug 2012 14:58:37 +0000 Subject: [PATCH 0226/1799] ARM: pxa: remove irq_to_gpio from ezx-pcap driver commit 59ee93a528b94ef4e81a08db252b0326feff171f upstream. The irq_to_gpio function was removed from the pxa platform in linux-3.2, and this driver has been broken since. There is actually no in-tree user of this driver that adds this platform device, but the driver can and does get enabled on some platforms. Without this patch, building ezx_defconfig results in: drivers/mfd/ezx-pcap.c: In function 'pcap_isr_work': drivers/mfd/ezx-pcap.c:205:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration] Signed-off-by: Arnd Bergmann Acked-by: Haojian Zhuang Cc: Samuel Ortiz Cc: Daniel Ribeiro Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/ezx-pcap.c | 2 +- include/linux/mfd/ezx-pcap.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 43a76c41cfcc..db662e2dcfa5 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c @@ -202,7 +202,7 @@ static void pcap_isr_work(struct work_struct *work) } local_irq_enable(); ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr); - } while (gpio_get_value(irq_to_gpio(pcap->spi->irq))); + } while (gpio_get_value(pdata->gpio)); } static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc) diff --git a/include/linux/mfd/ezx-pcap.h b/include/linux/mfd/ezx-pcap.h index 40c372165f3e..32a1b5cfeba1 100644 --- a/include/linux/mfd/ezx-pcap.h +++ b/include/linux/mfd/ezx-pcap.h @@ -16,6 +16,7 @@ struct pcap_subdev { struct pcap_platform_data { unsigned int irq_base; unsigned int config; + int gpio; void (*init) (void *); /* board specific init */ int num_subdevs; struct pcap_subdev *subdevs; -- GitLab From 25320e75fe0296dab5ae37c6b59f18899cd1c310 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Thu, 2 Aug 2012 18:41:48 +0100 Subject: [PATCH 0227/1799] cfg80211: process pending events when unregistering net device commit 1f6fc43e621167492ed4b7f3b4269c584c3d6ccc upstream. libertas currently calls cfg80211_disconnected() when it is being brought down. This causes an event to be allocated, but since the wdev is already removed from the rdev by the time that the event processing work executes, the event is never processed or freed. http://article.gmane.org/gmane.linux.kernel.wireless.general/95666 Fix this leak, and other possible situations, by processing the event queue when a device is being unregistered. Thanks to Johannes Berg for the suggestion. Signed-off-by: Daniel Drake Reviewed-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/core.c | 5 +++++ net/wireless/core.h | 1 + net/wireless/util.c | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index ccdfed897651..bb5302dd592d 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -975,6 +975,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, */ synchronize_rcu(); INIT_LIST_HEAD(&wdev->list); + /* + * Ensure that all events have been processed and + * freed. + */ + cfg80211_process_wdev_events(wdev); break; case NETDEV_PRE_UP: if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) diff --git a/net/wireless/core.h b/net/wireless/core.h index 3ac2dd00d714..ce5597c6459f 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -426,6 +426,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, struct net_device *dev, enum nl80211_iftype ntype, u32 *flags, struct vif_params *params); void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); +void cfg80211_process_wdev_events(struct wireless_dev *wdev); int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, diff --git a/net/wireless/util.c b/net/wireless/util.c index 0eb6cc0c77d8..63b37d3f3c06 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -717,7 +717,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev) wdev->connect_keys = NULL; } -static void cfg80211_process_wdev_events(struct wireless_dev *wdev) +void cfg80211_process_wdev_events(struct wireless_dev *wdev) { struct cfg80211_event *ev; unsigned long flags; -- GitLab From 510f1d143b72225df068a31b2b105edaef5f2420 Mon Sep 17 00:00:00 2001 From: Liang Li Date: Thu, 2 Aug 2012 18:55:41 -0400 Subject: [PATCH 0228/1799] cfg80211: fix interface combinations check for ADHOC(IBSS) partial of commit 8e8b41f9d8c8e63fc92f899ace8da91a490ac573 upstream. As part of commit 463454b5dbd8 ("cfg80211: fix interface combinations check"), this extra check was introduced: if ((all_iftypes & used_iftypes) != used_iftypes) goto cont; However, most wireless NIC drivers did not advertise ADHOC in wiphy.iface_combinations[i].limits[] and hence we'll get -EBUSY when we bring up a ADHOC wlan with commands similar to: # iwconfig wlan0 mode ad-hoc && ifconfig wlan0 up In commit 8e8b41f9d8c8e ("cfg80211: enforce lack of interface combinations"), the change below fixes the issue: if (total == 1) return 0; But it also introduces other dependencies for stable. For example, a full cherry pick of 8e8b41f9d8c8e would introduce additional regressions unless we also start cherry picking driver specific fixes like the following: 9b4760e ath5k: add possible wiphy interface combinations 1ae2fc2 mac80211_hwsim: advertise interface combinations 20c8e8d ath9k: add possible wiphy interface combinations And the purpose of the 'if (total == 1)' is to cover the specific use case (IBSS, adhoc) that was mentioned above. So we just pick the specific part out from 8e8b41f9d8c8e here. Doing so gives stable kernels a way to fix the change introduced by 463454b5dbd8, without having to make cherry picks specific to various NIC drivers. Signed-off-by: Liang Li Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman --- net/wireless/util.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/wireless/util.c b/net/wireless/util.c index 63b37d3f3c06..d835377b4da7 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -974,6 +974,9 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, } mutex_unlock(&rdev->devlist_mtx); + if (total == 1) + return 0; + for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { const struct ieee80211_iface_combination *c; struct ieee80211_iface_limit *limits; -- GitLab From c6c0038af718e3c29d5369aa799ea120d8f67112 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Thu, 9 Aug 2012 02:50:40 +0000 Subject: [PATCH 0229/1799] tun: don't zeroize sock->file on detach commit 66d1b9263a371abd15806c53f486f0645ef31a8f upstream. This is a fix for bug, introduced in 3.4 kernel by commit 1ab5ecb90cb6a3df1476e052f76a6e8f6511cb3d ("tun: don't hold network namespace by tun sockets"), which, among other things, replaced simple sock_put() by sk_release_kernel(). Below is sequence, which leads to oops for non-persistent devices: tun_chr_close() tun_detach() <== tun->socket.file = NULL tun_free_netdev() sk_release_sock() sock_release(sock->file == NULL) iput(SOCK_INODE(sock)) <== dereference on NULL pointer This patch just removes zeroing of socket's file from __tun_detach(). sock_release() will do this. Reported-by: Ruan Zhijie Tested-by: Ruan Zhijie Acked-by: Al Viro Acked-by: Eric Dumazet Acked-by: Yuchung Cheng Signed-off-by: Stanislav Kinsbursky Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/tun.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 8f13420dd31a..147b6284d7fa 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -185,7 +185,6 @@ static void __tun_detach(struct tun_struct *tun) netif_tx_lock_bh(tun->dev); netif_carrier_off(tun->dev); tun->tfile = NULL; - tun->socket.file = NULL; netif_tx_unlock_bh(tun->dev); /* Drop read queue */ -- GitLab From 66f3d999759fd703bf43acc0bd58b422701c77b4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 5 Aug 2012 18:31:46 +0200 Subject: [PATCH 0230/1799] iwlwifi: disable greenfield transmissions as a workaround commit 50e2a30cf6fcaeb2d27360ba614dd169a10041c5 upstream. There's a bug that causes the rate scaling to get stuck when it has to use single-stream rates with a peer that can do GF and SGI; the two are incompatible so we can't use them together, but that causes the algorithm to not work at all, it always rejects updates. Disable greenfield for now to prevent that problem. Reviewed-by: Emmanuel Grumbach Tested-by: Cesar Eduardo Barros Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index da2be3e09eeb..7db5d45da237 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -709,11 +709,14 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, */ static bool rs_use_green(struct ieee80211_sta *sta) { - struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; - struct iwl_rxon_context *ctx = sta_priv->ctx; - - return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && - !(ctx->ht.non_gf_sta_present); + /* + * There's a bug somewhere in this code that causes the + * scaling to get stuck because GF+SGI can't be combined + * in SISO rates. Until we find that bug, disable GF, it + * has only limited benefit and we still interoperate with + * GF APs since we can always receive GF transmissions. + */ + return false; } /** -- GitLab From 733e9ad978a1530328ff78aff3186c20000e5b4e Mon Sep 17 00:00:00 2001 From: Tushar Dave Date: Tue, 31 Jul 2012 02:02:43 +0000 Subject: [PATCH 0231/1799] e1000e: NIC goes up and immediately goes down commit b7ec70be01a87f2c85df3ae11046e74f9b67e323 upstream. Found that commit d478eb44 was a bad commit. If the link partner is transmitting codeword (even if NULL codeword), then the RXCW.C bit will be set so check for RXCW.CW is unnecessary. Ref: RH BZ 840642 Reported-by: Fabio Futigami Signed-off-by: Tushar Dave CC: Marcelo Ricardo Leitner Tested-by: Aaron Brown Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/intel/e1000e/82571.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index a9dd6a92cf50..c098b2495b7e 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -1582,10 +1582,8 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) * auto-negotiation in the TXCW register and disable * forced link in the Device Control register in an * attempt to auto-negotiate with our link partner. - * If the partner code word is null, stop forcing - * and restart auto negotiation. */ - if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW)) { + if (rxcw & E1000_RXCW_C) { /* Enable autoneg, and unforce link up */ ew32(TXCW, mac->txcw); ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); -- GitLab From 95c92481f69cf89aa1db689940368c09fb425281 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 30 Apr 2012 16:21:37 +0000 Subject: [PATCH 0232/1799] Input: eeti_ts: pass gpio value instead of IRQ commit 4eef6cbfcc03b294d9d334368a851b35b496ce53 upstream. The EETI touchscreen asserts its IRQ line as soon as it has data in its internal buffers. The line is automatically deasserted once all data has been read via I2C. Hence, the driver has to monitor the GPIO line and cannot simply rely on the interrupt handler reception. In the current implementation of the driver, irq_to_gpio() is used to determine the GPIO number from the i2c_client's IRQ value. As irq_to_gpio() is not available on all platforms, this patch changes this and makes the driver ignore the passed in IRQ. Instead, a GPIO is added to the platform_data struct and gpio_to_irq is used to derive the IRQ from that GPIO. If this fails, bail out. The driver is only able to work in environments where the touchscreen GPIO can be mapped to an IRQ. Without this patch, building raumfeld_defconfig results in: drivers/input/touchscreen/eeti_ts.c: In function 'eeti_ts_irq_active': drivers/input/touchscreen/eeti_ts.c:65:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration] Signed-off-by: Daniel Mack Signed-off-by: Arnd Bergmann Cc: Dmitry Torokhov Cc: Sven Neumann Cc: linux-input@vger.kernel.org Cc: Haojian Zhuang Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-pxa/raumfeld.c | 2 +- drivers/input/touchscreen/eeti_ts.c | 21 +++++++++++++-------- include/linux/input/eeti_ts.h | 1 + 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index 5905ed130e94..d89d87ae144c 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -953,12 +953,12 @@ static struct i2c_board_info raumfeld_connector_i2c_board_info __initdata = { static struct eeti_ts_platform_data eeti_ts_pdata = { .irq_active_high = 1, + .irq_gpio = GPIO_TOUCH_IRQ, }; static struct i2c_board_info raumfeld_controller_i2c_board_info __initdata = { .type = "eeti_ts", .addr = 0x0a, - .irq = PXA_GPIO_TO_IRQ(GPIO_TOUCH_IRQ), .platform_data = &eeti_ts_pdata, }; diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 503c7096ed36..908407efc672 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -48,7 +48,7 @@ struct eeti_ts_priv { struct input_dev *input; struct work_struct work; struct mutex mutex; - int irq, irq_active_high; + int irq_gpio, irq, irq_active_high; }; #define EETI_TS_BITDEPTH (11) @@ -62,7 +62,7 @@ struct eeti_ts_priv { static inline int eeti_ts_irq_active(struct eeti_ts_priv *priv) { - return gpio_get_value(irq_to_gpio(priv->irq)) == priv->irq_active_high; + return gpio_get_value(priv->irq_gpio) == priv->irq_active_high; } static void eeti_ts_read(struct work_struct *work) @@ -157,7 +157,7 @@ static void eeti_ts_close(struct input_dev *dev) static int __devinit eeti_ts_probe(struct i2c_client *client, const struct i2c_device_id *idp) { - struct eeti_ts_platform_data *pdata; + struct eeti_ts_platform_data *pdata = client->dev.platform_data; struct eeti_ts_priv *priv; struct input_dev *input; unsigned int irq_flags; @@ -199,9 +199,12 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, priv->client = client; priv->input = input; - priv->irq = client->irq; + priv->irq_gpio = pdata->irq_gpio; + priv->irq = gpio_to_irq(pdata->irq_gpio); - pdata = client->dev.platform_data; + err = gpio_request_one(pdata->irq_gpio, GPIOF_IN, client->name); + if (err < 0) + goto err1; if (pdata) priv->irq_active_high = pdata->irq_active_high; @@ -215,13 +218,13 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, err = input_register_device(input); if (err) - goto err1; + goto err2; err = request_irq(priv->irq, eeti_ts_isr, irq_flags, client->name, priv); if (err) { dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); - goto err2; + goto err3; } /* @@ -233,9 +236,11 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, device_init_wakeup(&client->dev, 0); return 0; -err2: +err3: input_unregister_device(input); input = NULL; /* so we dont try to free it below */ +err2: + gpio_free(pdata->irq_gpio); err1: input_free_device(input); kfree(priv); diff --git a/include/linux/input/eeti_ts.h b/include/linux/input/eeti_ts.h index f875b316249d..16625d799b6f 100644 --- a/include/linux/input/eeti_ts.h +++ b/include/linux/input/eeti_ts.h @@ -2,6 +2,7 @@ #define LINUX_INPUT_EETI_TS_H struct eeti_ts_platform_data { + int irq_gpio; unsigned int irq_active_high; }; -- GitLab From 117b7f7c36e2e64d36e80d9aeadc2deff5007a3e Mon Sep 17 00:00:00 2001 From: Chris Bagwell Date: Tue, 12 Jun 2012 00:25:48 -0700 Subject: [PATCH 0233/1799] Input: wacom - Bamboo One 1024 pressure fix commit 6dc463511d4a690f01a9248df3b384db717e0b1c upstream. Bamboo One's with ID of 0x6a and 0x6b were added with correct indication of 1024 pressure levels but the Graphire packet routine was only looking at 9 bits. Increased to 10 bits. This bug caused these devices to roll over to zero pressure at half way mark. The other devices using this routine only support 256 or 512 range and look to fix unused bits at zero. Signed-off-by: Chris Bagwell Reported-by: Tushant Mirchandani Reviewed-by: Ping Cheng Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/tablet/wacom_wac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index cecd35c8f0b3..c77032c943ee 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -243,7 +243,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); if (wacom->tool[0] != BTN_TOOL_MOUSE) { - input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); + input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x03) << 8)); input_report_key(input, BTN_TOUCH, data[1] & 0x01); input_report_key(input, BTN_STYLUS, data[1] & 0x02); input_report_key(input, BTN_STYLUS2, data[1] & 0x04); -- GitLab From 8f3ce224466a1cf867c13cb01c3fac799aeab074 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Aug 2012 12:49:14 +0200 Subject: [PATCH 0234/1799] rt61pci: fix NULL pointer dereference in config_lna_gain commit deee0214def5d8a32b8112f11d9c2b1696e9c0cb upstream. We can not pass NULL libconf->conf->channel to rt61pci_config() as it is dereferenced unconditionally in rt61pci_config_lna_gain() subroutine. Resolves: https://bugzilla.kernel.org/show_bug.cgi?id=44361 Reported-and-tested-by: Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt61pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index e0c6d117429d..0f4bf8c23bff 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2243,8 +2243,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) { - struct ieee80211_conf conf = { .flags = 0 }; - struct rt2x00lib_conf libconf = { .conf = &conf }; + struct rt2x00lib_conf libconf = { .conf = &rt2x00dev->hw->conf }; rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); } -- GitLab From 196ad09b956e63131e3d196e490a4dfbb85e875f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 15 Aug 2012 08:17:17 -0700 Subject: [PATCH 0235/1799] Linux 3.4.9 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a3c0c43a71d4..9549547614b2 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 8 +SUBLEVEL = 9 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From bdac2ea27e0237b3c76b1d8a9d7f73a3d6b3ad81 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 7 Aug 2012 09:48:13 +0200 Subject: [PATCH 0236/1799] s390/compat: fix compat wrappers for process_vm system calls commit 82aabdb6f1eb61e0034ec23901480f5dd23db7c4 upstream. The compat wrappers incorrectly called the non compat versions of the system process_vm system calls. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/kernel/compat_wrapper.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index ff605a39cf43..cfe3efda69d1 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1636,7 +1636,7 @@ ENTRY(compat_sys_process_vm_readv_wrapper) llgfr %r6,%r6 # unsigned long llgf %r0,164(%r15) # unsigned long stg %r0,160(%r15) - jg sys_process_vm_readv + jg compat_sys_process_vm_readv ENTRY(compat_sys_process_vm_writev_wrapper) lgfr %r2,%r2 # compat_pid_t @@ -1646,4 +1646,4 @@ ENTRY(compat_sys_process_vm_writev_wrapper) llgfr %r6,%r6 # unsigned long llgf %r0,164(%r15) # unsigned long stg %r0,160(%r15) - jg sys_process_vm_writev + jg compat_sys_process_vm_writev -- GitLab From a87531935d7afc5429944c89511c8acbdf467111 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 8 Aug 2012 09:32:20 +0200 Subject: [PATCH 0237/1799] s390/compat: fix mmap compat system calls commit e85871218513c54f7dfdb6009043cb638f2fecbe upstream. The native 31 bit and the compat behaviour for the mmap system calls differ: In native 31 bit mode the passed in address for the mmap system call will be unmodified passed to sys_mmap_pgoff(). In compat mode however the passed in address will be modified with compat_ptr() which masks out the most significant bit. The result is that in native 31 bit mode each mmap request (with MAP_FIXED) will fail where the most significat bit is set, while in compat mode it may succeed. This odd behaviour was introduced with d3815898 "[S390] mmap: add missing compat_ptr conversion to both mmap compat syscalls". To restore a consistent behaviour accross native and compat mode this patch functionally reverts the above mentioned commit. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/kernel/compat_linux.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index ab64bdbab2ae..36e6c3092e6c 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -612,7 +612,6 @@ asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg) return -EFAULT; if (a.offset & ~PAGE_MASK) return -EINVAL; - a.addr = (unsigned long) compat_ptr(a.addr); return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); } @@ -623,7 +622,6 @@ asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) if (copy_from_user(&a, arg, sizeof(a))) return -EFAULT; - a.addr = (unsigned long) compat_ptr(a.addr); return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); } -- GitLab From 9ea2c02bafe276e97b592a046ac733610a6d57fd Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 3 Jul 2012 15:33:29 -0300 Subject: [PATCH 0238/1799] dma: imx-dma: Fix kernel crash due to missing clock conversion commit a2367db2ec5e7fc6fe93e221e0fcdee81b053daf upstream. With the new i.MX clock infrastructure we need to request the dma clocks seperately: ahb and ipg clocks. This fixes the following kernel crash and make audio to be functional again: root@freescale /home$ aplay audio48k16S.wav Playing WAVE 'audio48k16S.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = c7b74000 [00000000] *pgd=a7bb5831, *pte=00000000, *ppte=00000000 Internal error: Oops: 17 [#1] PREEMPT ARM Modules linked in: CPU: 0 Not tainted (3.5.0-rc5-next-20120702-00007-g3028b64 #1128) PC is at snd_dmaengine_pcm_get_chan+0x8/0x10 LR is at snd_imx_pcm_hw_params+0x18/0xdc pc : [] lr : [] psr: a0000013 sp : c7b45e30 ip : ffffffff fp : c7ae58e0 r10: 00000000 r9 : c7ae981c r8 : c7b88800 r7 : c7ae5a60 r6 : c7ae5b20 r5 : c7ae9810 r4 : c7afa060 r3 : 00000000 r2 : 00000001 r1 : c7b88800 r0 : c7afa060 Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 0005317f Table: a7b74000 DAC: 00000015 Process aplay (pid: 701, stack limit = 0xc7b44270) Stack: (0xc7b45e30 to 0xc7b46000) 5e20: 00100000 00000029 c7b88800 c02db870 5e40: c7ae5a60 c02d4594 00000010 01ae5a60 c7ae5a60 c7ae9810 c7ae9810 c7afa060 5e60: c7ae5b20 c7ae5a60 c7b88800 c02e3ef0 c02e3e08 c7b1e400 c7afa060 c7b88800 5e80: 00000000 c0014da8 c7b44000 00000000 bec566ac c02cd400 c7afa060 c7afa060 5ea0: bec56800 c7b88800 c0014da8 c02cdd7c c04ee710 c04ee7b8 00000003 c005fc74 5ec0: 00000000 7fffffff c7b45f00 c7afa060 c7b67420 c7ba3070 00000004 c0014da8 5ee0: c7b44000 00000000 bec566ac c02ced88 c04e95f8 b6f5ab04 c7b45fb0 0145a468 5f00: 0145a600 bec566bc bec56800 c7b67420 c7ba3070 c00d499c c7b45f18 c7b45f18 5f20: 0000001a 00000004 00000001 c7b44000 c0527f40 00000009 00000008 00000000 5f40: c7b44000 c002c9ec 00000001 c04f0ab0 c04ebec0 00000101 00000000 0000000a 5f60: 60000093 c7b67420 bec56800 c25c4111 00000004 c0014da8 c7b44000 00000000 5f80: bec566ac c00d4f38 b6ffb658 00000000 c0522d80 0145a468 b6fd5000 0145a418 5fa0: 00000036 c0014c00 0145a468 b6fd5000 00000004 c25c4111 bec56800 00020001 5fc0: 0145a468 b6fd5000 0145a418 00000036 0145a468 0145a600 bec566bc bec566ac 5fe0: 0145a468 bec56388 b6f65ce4 b6dcebec 20000010 00000004 00000000 00000000 [] (snd_dmaengine_pcm_get_chan+0x8/0x10) from [] (snd_imx_pcm_hw_params+0x18/0xdc) [] (snd_imx_pcm_hw_params+0x18/0xdc) from [] (soc_pcm_hw_params+0xe8/0x1f0) [] (soc_pcm_hw_params+0xe8/0x1f0) from [] (snd_pcm_hw_params+0x124/0x474) [] (snd_pcm_hw_params+0x124/0x474) from [] (snd_pcm_common_ioctl1+0x4b4/0xf74) [] (snd_pcm_common_ioctl1+0x4b4/0xf74) from [] (snd_pcm_playback_ioctl1+0x30/0x510) [] (snd_pcm_playback_ioctl1+0x30/0x510) from [] (do_vfs_ioctl+0x80/0x5e4) [] (do_vfs_ioctl+0x80/0x5e4) from [] (sys_ioctl+0x38/0x60) [] (sys_ioctl+0x38/0x60) from [] (ret_fast_syscall+0x0/0x2c) Code: e593000c e12fff1e e59030a0 e59330bc (e5930000) ---[ end trace fa518c8ba3a74e97 ]-- Reported-by: Javier Martin Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Signed-off-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/imx-dma.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index bb787d8e1529..2ca8d3f779fe 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -172,7 +172,8 @@ struct imxdma_engine { struct device_dma_parameters dma_parms; struct dma_device dma_device; void __iomem *base; - struct clk *dma_clk; + struct clk *dma_ahb; + struct clk *dma_ipg; spinlock_t lock; struct imx_dma_2d_config slots_2d[IMX_DMA_2D_SLOTS]; struct imxdma_channel channel[IMX_DMA_CHANNELS]; @@ -976,10 +977,20 @@ static int __init imxdma_probe(struct platform_device *pdev) return 0; } - imxdma->dma_clk = clk_get(NULL, "dma"); - if (IS_ERR(imxdma->dma_clk)) - return PTR_ERR(imxdma->dma_clk); - clk_enable(imxdma->dma_clk); + imxdma->dma_ipg = devm_clk_get(&pdev->dev, "ipg"); + if (IS_ERR(imxdma->dma_ipg)) { + ret = PTR_ERR(imxdma->dma_ipg); + goto err_clk; + } + + imxdma->dma_ahb = devm_clk_get(&pdev->dev, "ahb"); + if (IS_ERR(imxdma->dma_ahb)) { + ret = PTR_ERR(imxdma->dma_ahb); + goto err_clk; + } + + clk_prepare_enable(imxdma->dma_ipg); + clk_prepare_enable(imxdma->dma_ahb); /* reset DMA module */ imx_dmav1_writel(imxdma, DCR_DRST, DMA_DCR); @@ -988,16 +999,14 @@ static int __init imxdma_probe(struct platform_device *pdev) ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", imxdma); if (ret) { dev_warn(imxdma->dev, "Can't register IRQ for DMA\n"); - kfree(imxdma); - return ret; + goto err_enable; } ret = request_irq(MX1_DMA_ERR, imxdma_err_handler, 0, "DMA", imxdma); if (ret) { dev_warn(imxdma->dev, "Can't register ERRIRQ for DMA\n"); free_irq(MX1_DMA_INT, NULL); - kfree(imxdma); - return ret; + goto err_enable; } } @@ -1094,7 +1103,10 @@ static int __init imxdma_probe(struct platform_device *pdev) free_irq(MX1_DMA_INT, NULL); free_irq(MX1_DMA_ERR, NULL); } - +err_enable: + clk_disable_unprepare(imxdma->dma_ipg); + clk_disable_unprepare(imxdma->dma_ahb); +err_clk: kfree(imxdma); return ret; } @@ -1114,7 +1126,9 @@ static int __exit imxdma_remove(struct platform_device *pdev) free_irq(MX1_DMA_ERR, NULL); } - kfree(imxdma); + clk_disable_unprepare(imxdma->dma_ipg); + clk_disable_unprepare(imxdma->dma_ahb); + kfree(imxdma); return 0; } -- GitLab From 90f9cb724d38bf4ac4e355d19b1ee697dceea021 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Tue, 24 Jul 2012 12:10:11 -0700 Subject: [PATCH 0239/1799] fuse: verify all ioctl retry iov elements commit fb6ccff667712c46b4501b920ea73a326e49626a upstream. Commit 7572777eef78ebdee1ecb7c258c0ef94d35bad16 attempted to verify that the total iovec from the client doesn't overflow iov_length() but it only checked the first element. The iovec could still overflow by starting with a small element. The obvious fix is to check all the elements. The overflow case doesn't look dangerous to the kernel as the copy is limited by the length after the overflow. This fix restores the intention of returning an error instead of successfully copying less than the iovec represented. I found this by code inspection. I built it but don't have a test case. I'm cc:ing stable because the initial commit did as well. Signed-off-by: Zach Brown Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman --- fs/fuse/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 504e61b7fd75..8e6381a14265 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1698,7 +1698,7 @@ 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++) { + for (n = 0; n < count; n++, iov++) { if (iov->iov_len > (size_t) max) return -ENOMEM; max -= iov->iov_len; -- GitLab From b9247be526627cda981a6901c8db66f03ecb3ea8 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 23 May 2012 18:57:20 +0100 Subject: [PATCH 0240/1799] xen: mark local pages as FOREIGN in the m2p_override commit b9e0d95c041ca2d7ad297ee37c2e9cfab67a188f upstream. When the frontend and the backend reside on the same domain, even if we add pages to the m2p_override, these pages will never be returned by mfn_to_pfn because the check "get_phys_to_machine(pfn) != mfn" will always fail, so the pfn of the frontend will be returned instead (resulting in a deadlock because the frontend pages are already locked). INFO: task qemu-system-i38:1085 blocked for more than 120 seconds. "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. qemu-system-i38 D ffff8800cfc137c0 0 1085 1 0x00000000 ffff8800c47ed898 0000000000000282 ffff8800be4596b0 00000000000137c0 ffff8800c47edfd8 ffff8800c47ec010 00000000000137c0 00000000000137c0 ffff8800c47edfd8 00000000000137c0 ffffffff82213020 ffff8800be4596b0 Call Trace: [] ? __lock_page+0x70/0x70 [] schedule+0x29/0x70 [] io_schedule+0x60/0x80 [] sleep_on_page+0xe/0x20 [] __wait_on_bit_lock+0x5a/0xc0 [] __lock_page+0x67/0x70 [] ? autoremove_wake_function+0x40/0x40 [] ? bio_add_page+0x36/0x40 [] set_page_dirty_lock+0x52/0x60 [] bio_set_pages_dirty+0x51/0x70 [] do_blockdev_direct_IO+0xb24/0xeb0 [] ? ext3_get_blocks_handle+0xe00/0xe00 [] __blockdev_direct_IO+0x55/0x60 [] ? ext3_get_blocks_handle+0xe00/0xe00 [] ext3_direct_IO+0xf8/0x390 [] ? ext3_get_blocks_handle+0xe00/0xe00 [] ? xen_mc_flush+0xb0/0x1b0 [] generic_file_aio_read+0x737/0x780 [] ? gnttab_map_refs+0x15b/0x1e0 [] ? find_get_pages+0x150/0x150 [] aio_rw_vect_retry+0x7c/0x1d0 [] ? lookup_ioctx+0x90/0x90 [] aio_run_iocb+0x66/0x1a0 [] do_io_submit+0x708/0xb90 [] sys_io_submit+0x10/0x20 [] system_call_fastpath+0x16/0x1b The explanation is in the comment within the code: We need to do this because the pages shared by the frontend (xen-blkfront) can be already locked (lock_page, called by do_read_cache_page); when the userspace backend tries to use them with direct_IO, mfn_to_pfn returns the pfn of the frontend, so do_blockdev_direct_IO is going to try to lock the same pages again resulting in a deadlock. A simplified call graph looks like this: pygrub QEMU ----------------------------------------------- do_read_cache_page io_submit | | lock_page ext3_direct_IO | bio_add_page | lock_page Internally the xen-blkback uses m2p_add_override to swizzle (temporarily) a 'struct page' to have a different MFN (so that it can point to another guest). It also can easily find out whether another pfn corresponding to the mfn exists in the m2p, and can set the FOREIGN bit in the p2m, making sure that mfn_to_pfn returns the pfn of the backend. This allows the backend to perform direct_IO on these pages, but as a side effect prevents the frontend from using get_user_pages_fast on them while they are being shared with the backend. Signed-off-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/p2m.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 1b267e75158d..00a038540c8e 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -686,6 +686,7 @@ int m2p_add_override(unsigned long mfn, struct page *page, unsigned long uninitialized_var(address); unsigned level; pte_t *ptep = NULL; + int ret = 0; pfn = page_to_pfn(page); if (!PageHighMem(page)) { @@ -721,6 +722,24 @@ int m2p_add_override(unsigned long mfn, struct page *page, list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); spin_unlock_irqrestore(&m2p_override_lock, flags); + /* p2m(m2p(mfn)) == mfn: the mfn is already present somewhere in + * this domain. Set the FOREIGN_FRAME_BIT in the p2m for the other + * pfn so that the following mfn_to_pfn(mfn) calls will return the + * pfn from the m2p_override (the backend pfn) instead. + * We need to do this because the pages shared by the frontend + * (xen-blkfront) can be already locked (lock_page, called by + * do_read_cache_page); when the userspace backend tries to use them + * with direct_IO, mfn_to_pfn returns the pfn of the frontend, so + * do_blockdev_direct_IO is going to try to lock the same pages + * again resulting in a deadlock. + * As a side effect get_user_pages_fast might not be safe on the + * frontend pages while they are being shared with the backend, + * because mfn_to_pfn (that ends up being called by GUPF) will + * return the backend pfn rather than the frontend pfn. */ + ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); + if (ret == 0 && get_phys_to_machine(pfn) == mfn) + set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)); + return 0; } EXPORT_SYMBOL_GPL(m2p_add_override); @@ -732,6 +751,7 @@ int m2p_remove_override(struct page *page, bool clear_pte) unsigned long uninitialized_var(address); unsigned level; pte_t *ptep = NULL; + int ret = 0; pfn = page_to_pfn(page); mfn = get_phys_to_machine(pfn); @@ -801,6 +821,22 @@ int m2p_remove_override(struct page *page, bool clear_pte) } else set_phys_to_machine(pfn, page->index); + /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present + * somewhere in this domain, even before being added to the + * m2p_override (see comment above in m2p_add_override). + * If there are no other entries in the m2p_override corresponding + * to this mfn, then remove the FOREIGN_FRAME_BIT from the p2m for + * the original pfn (the one shared by the frontend): the backend + * cannot do any IO on this page anymore because it has been + * unshared. Removing the FOREIGN_FRAME_BIT from the p2m entry of + * the original pfn causes mfn_to_pfn(mfn) to return the frontend + * pfn again. */ + mfn &= ~FOREIGN_FRAME_BIT; + ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); + if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) && + m2p_find_override(mfn) == NULL) + set_phys_to_machine(pfn, mfn); + return 0; } EXPORT_SYMBOL_GPL(m2p_remove_override); -- GitLab From 6700eb4d0af877ed46ae2e5d93d6801db7f3b58d Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 21 Jun 2012 15:13:50 -0700 Subject: [PATCH 0241/1799] drm/i915: prefer wide & slow to fast & narrow in DP configs commit 2514bc510d0c3aadcc5204056bb440fa36845147 upstream. High frequency link configurations have the potential to cause trouble with long and/or cheap cables, so prefer slow and wide configurations instead. This patch has the potential to cause trouble for eDP configurations that lie about available lanes, so if we run into that we can make it conditional on eDP. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=45801 Tested-by: peter@colberg.org Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter Cc: Jonathan Nieder Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 68624218d05a..4eedd16bc3d4 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -712,8 +712,8 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; - for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { - for (clock = 0; clock <= max_clock; clock++) { + for (clock = 0; clock <= max_clock; clock++) { + for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); if (intel_dp_link_required(mode->clock, bpp) -- GitLab From 1a475b7af63febbef784d0d2ccb6bdbb119d0245 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Thu, 26 Jul 2012 20:53:19 +0200 Subject: [PATCH 0242/1799] drm/nvd0/disp: mask off high 16 bit of negative cursor x-coordinate commit af5e7d84b0ec45b2b614b0d6e3657cbdceaa21f9 upstream. Signed-off-by: Christoph Bumiller Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nvd0_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 0247250939e8..8a555fb67024 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -790,7 +790,7 @@ nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); int ch = EVO_CURS(nv_crtc->index); - evo_piow(crtc->dev, ch, 0x0084, (y << 16) | x); + evo_piow(crtc->dev, ch, 0x0084, (y << 16) | (x & 0xffff)); evo_piow(crtc->dev, ch, 0x0080, 0x00000000); return 0; } -- GitLab From 57ecc93ce680b1ace1f9e79d588dabe32353202c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 7 Aug 2012 09:54:14 +0200 Subject: [PATCH 0243/1799] drm/i915: correctly order the ring init sequence commit 0d8957c8a90bbb5d34fab9a304459448a5131e06 upstream. We may only start to set up the new register values after having confirmed that the ring is truely off. Otherwise the hw might lose the newly written register values. This is caught later on in the init sequence, when we check whether the register writes have stuck. Reviewed-by: Jani Nikula Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=50522 Tested-by: Yang Guang Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_ringbuffer.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 302d3d54fb41..12a9e5fd9252 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -258,8 +258,6 @@ static int init_ring_common(struct intel_ring_buffer *ring) I915_WRITE_HEAD(ring, 0); ring->write_tail(ring, 0); - /* Initialize the ring. */ - I915_WRITE_START(ring, obj->gtt_offset); head = I915_READ_HEAD(ring) & HEAD_ADDR; /* G45 ring initialization fails to reset head to zero */ @@ -285,6 +283,11 @@ static int init_ring_common(struct intel_ring_buffer *ring) } } + /* Initialize the ring. This must happen _after_ we've cleared the ring + * registers with the above sequence (the readback of the HEAD registers + * also enforces ordering), otherwise the hw might lose the new ring + * register values. */ + I915_WRITE_START(ring, obj->gtt_offset); I915_WRITE_CTL(ring, ((ring->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID); -- GitLab From c02a29650148f353b0fc86b7eba3f99ecafd23dd Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 10 Aug 2012 11:10:20 +0200 Subject: [PATCH 0244/1799] drm/i915: ignore eDP bpc settings from vbt commit 4344b813f105a19f793f1fd93ad775b784648b95 upstream. This has originally been introduced to not oversubscribe the dp links in commit 885a5fb5b120a5c7e0b3baad7b0feb5a89f76c18 Author: Zhenyu Wang Date: Tue Jan 12 05:38:31 2010 +0800 drm/i915: fix pixel color depth setting on eDP Since then we've fixed up the dp link bandwidth calculation code and should now automatically fall back to 6bpc dithering. So this is unnecessary. Furthermore it seems to break the new MacbookPro with retina display, hence let's just rip this out. Reported-by: Benoit Gschwind Cc: Benoit Gschwind Cc: Francois Rigaut Tested-by: Benoit Gschwind Tested-by: Bernhard Froemel Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman -- Testing feedback highgly welcome, and thanks for Benoit for finding out that the bpc computations are busted. -Daniel --- drivers/gpu/drm/i915/intel_display.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d4d162f6babc..3de3d9b670bb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4982,17 +4982,6 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, continue; } - if (intel_encoder->type == INTEL_OUTPUT_EDP) { - /* Use VBT settings if we have an eDP panel */ - unsigned int edp_bpc = dev_priv->edp.bpp / 3; - - if (edp_bpc < display_bpc) { - DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); - display_bpc = edp_bpc; - } - continue; - } - /* Not one of the known troublemakers, check the EDID */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -- GitLab From acafb0231aeeb8648e1f2789e6dd88ea5878f61c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 12 Aug 2012 22:17:14 +0200 Subject: [PATCH 0245/1799] drm/i915: reorder edp disabling to fix ivb MacBook Air commit 35a38556d900b9cb5dfa2529c93944b847f8a8a4 upstream. eDP is tons of fun. It turns out that at least the new MacBook Air 5,1 model absolutely doesn't like the new force vdd dance we've introduced in commit 6cb49835da0426f69a2931bc2a0a8156344b0e41 Author: Daniel Vetter Date: Sun May 20 17:14:50 2012 +0200 drm/i915: enable vdd when switching off the eDP panel But that patch also tried to fix some neat edp sequence issue with the force_vdd timings. Closer inspection reveals that we've raised force_vdd only to do the aux channel communication dp_sink_dpms. If we move the edp_panel_off below that, we don't need any force_vdd for the disable sequence, which makes the Air happy. Unfortunately the reporter of the original bug that the above commit fixed is travelling, so we can't test whether this regresses things. But my theory is that since we don't check for any power-off -> force_vdd-on delays in edp_panel_vdd_on, this was the actual root-cause of this failure. With that force_vdd dance completely eliminated, I'm hopeful the original bug stays fixed, too. For reference the old bug, which hopefully doesn't get broken by this: https://bugzilla.kernel.org/show_bug.cgi?id=43163 In any case, regression fixers win over plain bugfixes, so this needs to go in asap. v2: The crucial pieces seems to be to clear the force_vdd flag uncoditionally, too, in edp_panel_off. Looks like this is left behind by the firmware somehow. v3: The Apple firmware seems to switch off the panel on it's own, hence we still need to keep force_vdd on, but properly clear it when switching the panel off. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45671 Tested-by: Roberto Romer Tested-by: Daniel Wagner Tested-by: Keith Packard Cc: Keith Packard Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_dp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 4eedd16bc3d4..069725c5c1ac 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1156,10 +1156,14 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp) WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); pp = ironlake_get_pp_control(dev_priv); - pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE); + /* We need to switch off panel power _and_ force vdd, for otherwise some + * panels get very unhappy and cease to work. */ + pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); + intel_dp->want_panel_vdd = false; + ironlake_wait_panel_off(intel_dp); } @@ -1269,11 +1273,9 @@ static void intel_dp_prepare(struct drm_encoder *encoder) * ensure that we have vdd while we switch off the panel. */ ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_backlight_off(intel_dp); - ironlake_edp_panel_off(intel_dp); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + ironlake_edp_panel_off(intel_dp); intel_dp_link_down(intel_dp); - ironlake_edp_panel_vdd_off(intel_dp, false); } static void intel_dp_commit(struct drm_encoder *encoder) @@ -1308,11 +1310,9 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) /* Switching the panel off requires vdd. */ ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_backlight_off(intel_dp); - ironlake_edp_panel_off(intel_dp); - intel_dp_sink_dpms(intel_dp, mode); + ironlake_edp_panel_off(intel_dp); intel_dp_link_down(intel_dp); - ironlake_edp_panel_vdd_off(intel_dp, false); if (is_cpu_edp(intel_dp)) ironlake_edp_pll_off(encoder); -- GitLab From b248464f145eee69818dff9945096745988aa3ce Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 26 Jul 2012 13:38:52 -0400 Subject: [PATCH 0246/1799] drm/radeon: properly handle crtc powergating commit 6c0ae2ab85fc4a95cae82047a7db1f688a7737ab upstream. Need to make sure the crtc is gated on before modesetting. Explicitly gate the crtc on in prepare() and set a flag so that the dpms functions don't gate it off during mode set. Noticed by sylware on IRC. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_crtc.c | 14 ++++++++++++-- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 4 ++++ drivers/gpu/drm/radeon/radeon_mode.h | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index af1054f8202a..a53ca30d05e2 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -259,7 +259,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) /* adjust pm to dpms changes BEFORE enabling crtcs */ radeon_pm_compute_clocks(rdev); /* disable crtc pair power gating before programming */ - if (ASIC_IS_DCE6(rdev)) + if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) atombios_powergate_crtc(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_ENABLE); if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) @@ -279,7 +279,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) atombios_enable_crtc(crtc, ATOM_DISABLE); radeon_crtc->enabled = false; /* power gating is per-pair */ - if (ASIC_IS_DCE6(rdev)) { + if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) { struct drm_crtc *other_crtc; struct radeon_crtc *other_radeon_crtc; list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { @@ -1634,18 +1634,28 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, static void atombios_crtc_prepare(struct drm_crtc *crtc) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + radeon_crtc->in_mode_set = true; /* pick pll */ radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); + /* disable crtc pair power gating before programming */ + if (ASIC_IS_DCE6(rdev)) + atombios_powergate_crtc(crtc, ATOM_DISABLE); + atombios_lock_crtc(crtc, ATOM_ENABLE); atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); } static void atombios_crtc_commit(struct drm_crtc *crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON); atombios_lock_crtc(crtc, ATOM_DISABLE); + radeon_crtc->in_mode_set = false; } static void atombios_crtc_disable(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 210317c7045e..9760e5addcc3 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -1025,9 +1025,11 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc, static void radeon_crtc_prepare(struct drm_crtc *crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_crtc *crtci; + radeon_crtc->in_mode_set = true; /* * The hardware wedges sometimes if you reconfigure one CRTC * whilst another is running (see fdo bug #24611). @@ -1038,6 +1040,7 @@ static void radeon_crtc_prepare(struct drm_crtc *crtc) static void radeon_crtc_commit(struct drm_crtc *crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_crtc *crtci; @@ -1048,6 +1051,7 @@ static void radeon_crtc_commit(struct drm_crtc *crtc) if (crtci->enabled) radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON); } + radeon_crtc->in_mode_set = false; } static const struct drm_crtc_helper_funcs legacy_helper_funcs = { diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index f7eb5d8b9fd3..778c1f0d7b81 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -266,6 +266,7 @@ struct radeon_crtc { u16 lut_r[256], lut_g[256], lut_b[256]; bool enabled; bool can_tile; + bool in_mode_set; uint32_t crtc_offset; struct drm_gem_object *cursor_bo; uint64_t cursor_addr; -- GitLab From 3407b51859d0e65ed66ccb0080c495a1f03cda6a Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 27 Jul 2012 16:32:24 -0400 Subject: [PATCH 0247/1799] drm/radeon: do not reenable crtc after moving vram start address commit 81ee8fb6b52ec69eeed37fe7943446af1dccecc5 upstream. It seems we can not update the crtc scanout address. After disabling crtc, update to base address do not take effect after crtc being reenable leading to at least frame being scanout from the old crtc base address. Disabling crtc display request lead to same behavior. So after changing the vram address if we don't keep crtc disabled we will have the GPU trying to read some random system memory address with some iommu this will broke the crtc engine and will lead to broken display and iommu error message. So to avoid this, disable crtc. For flicker less boot we will need to avoid moving the vram start address. This patch should also fix : https://bugs.freedesktop.org/show_bug.cgi?id=42373 Signed-off-by: Jerome Glisse Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen.c | 57 ---------------------------- drivers/gpu/drm/radeon/radeon_asic.h | 8 +--- drivers/gpu/drm/radeon/rv515.c | 13 ------- 3 files changed, 2 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index e72c03ff595d..ba554bf9c8fb 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1117,24 +1117,8 @@ void evergreen_agp_enable(struct radeon_device *rdev) void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) { - save->vga_control[0] = RREG32(D1VGA_CONTROL); - save->vga_control[1] = RREG32(D2VGA_CONTROL); save->vga_render_control = RREG32(VGA_RENDER_CONTROL); save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); - save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); - save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); - if (rdev->num_crtc >= 4) { - save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); - save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); - save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); - save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); - } - if (rdev->num_crtc >= 6) { - save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); - save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); - save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); - save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); - } /* Stop all video */ WREG32(VGA_RENDER_CONTROL, 0); @@ -1245,47 +1229,6 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s /* Unlock host access */ WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); mdelay(1); - /* Restore video state */ - WREG32(D1VGA_CONTROL, save->vga_control[0]); - WREG32(D2VGA_CONTROL, save->vga_control[1]); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); - WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); - WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); - } - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); - } - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); - } - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); - } WREG32(VGA_RENDER_CONTROL, save->vga_render_control); } diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 3d9f9f1d8f90..665df8730c80 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -262,13 +262,10 @@ extern int rs690_mc_wait_for_idle(struct radeon_device *rdev); * rv515 */ struct rv515_mc_save { - u32 d1vga_control; - u32 d2vga_control; u32 vga_render_control; u32 vga_hdp_control; - u32 d1crtc_control; - u32 d2crtc_control; }; + int rv515_init(struct radeon_device *rdev); void rv515_fini(struct radeon_device *rdev); uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); @@ -401,11 +398,10 @@ void r700_cp_fini(struct radeon_device *rdev); * evergreen */ struct evergreen_mc_save { - u32 vga_control[6]; u32 vga_render_control; u32 vga_hdp_control; - u32 crtc_control[6]; }; + void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); int evergreen_init(struct radeon_device *rdev); void evergreen_fini(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index d8d78fe17946..43af363ead37 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -281,12 +281,8 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev) void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save) { - save->d1vga_control = RREG32(R_000330_D1VGA_CONTROL); - save->d2vga_control = RREG32(R_000338_D2VGA_CONTROL); save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL); save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL); - save->d1crtc_control = RREG32(R_006080_D1CRTC_CONTROL); - save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL); /* Stop all video */ WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); @@ -311,15 +307,6 @@ void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) /* Unlock host access */ WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control); mdelay(1); - /* Restore video state */ - WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control); - WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control); - WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1); - WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1); - WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control); - WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control); - WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0); - WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control); } -- GitLab From 844bebfd9d09f92cdf4fac108e5f0d38cd389fff Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 6 Aug 2012 10:03:59 -0400 Subject: [PATCH 0248/1799] drm/radeon: add some new SI pci ids commit 2f292004dd1fb005788dc0a9cdd5559812ed866e upstream. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- include/drm/drm_pciids.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 81368ab6c611..53392e8f9564 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -217,9 +217,12 @@ {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ -- GitLab From e3d7a0f49568353837c51d0dbcd86cca8b7bc622 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 31 Jul 2012 11:05:11 -0400 Subject: [PATCH 0249/1799] drm/radeon: fix bank tiling parameters on cayman commit 5b23c9045a8b61352986270b2d109edf5085e113 upstream. Handle the 16 bank case. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/ni.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index ad0a38007de2..9934c9d9e518 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -880,10 +880,18 @@ static void cayman_gpu_init(struct radeon_device *rdev) if (rdev->flags & RADEON_IS_IGP) rdev->config.cayman.tile_config |= 1 << 4; else { - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - rdev->config.cayman.tile_config |= 1 << 4; - else + switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { + case 0: /* four banks */ rdev->config.cayman.tile_config |= 0 << 4; + break; + case 1: /* eight banks */ + rdev->config.cayman.tile_config |= 1 << 4; + break; + case 2: /* sixteen banks */ + default: + rdev->config.cayman.tile_config |= 2 << 4; + break; + } } rdev->config.cayman.tile_config |= ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; -- GitLab From 75a757189880a31759ed25c23229f085890cddb1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 31 Jul 2012 11:01:10 -0400 Subject: [PATCH 0250/1799] drm/radeon: fix bank tiling parameters on evergreen commit c8d15edc17d836686d1f071e564800e1a2724fa6 upstream. Handle the 16 bank case. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index ba554bf9c8fb..e5328da70f84 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2085,10 +2085,18 @@ static void evergreen_gpu_init(struct radeon_device *rdev) if (rdev->flags & RADEON_IS_IGP) rdev->config.evergreen.tile_config |= 1 << 4; else { - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - rdev->config.evergreen.tile_config |= 1 << 4; - else + switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { + case 0: /* four banks */ rdev->config.evergreen.tile_config |= 0 << 4; + break; + case 1: /* eight banks */ + rdev->config.evergreen.tile_config |= 1 << 4; + break; + case 2: /* sixteen banks */ + default: + rdev->config.evergreen.tile_config |= 2 << 4; + break; + } } rdev->config.evergreen.tile_config |= ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8; -- GitLab From 8b9f3861678e35b18cef66728d0fa896bbda65b6 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 5 Aug 2012 19:04:57 -0400 Subject: [PATCH 0251/1799] ext4: make sure the journal sb is written in ext4_clear_journal_err() commit d796c52ef0b71a988364f6109aeb63d79c5b116b upstream. After we transfer set the EXT4_ERROR_FS bit in the file system superblock, it's not enough to call jbd2_journal_clear_err() to clear the error indication from journal superblock --- we need to call jbd2_journal_update_sb_errno() as well. Otherwise, when the root file system is mounted read-only, the journal is replayed, and the error indicator is transferred to the superblock --- but the s_errno field in the jbd2 superblock is left set (since although we cleared it in memory, we never flushed it out to disk). This can end up confusing e2fsck. We should make e2fsck more robust in this case, but the kernel shouldn't be leaving things in this confused state, either. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 1 + fs/jbd2/journal.c | 3 ++- include/linux/jbd2.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 7fe3869d33d5..78fb7ff3adb8 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -4227,6 +4227,7 @@ static void ext4_clear_journal_err(struct super_block *sb, ext4_commit_super(sb, 1); jbd2_journal_clear_err(journal); + jbd2_journal_update_sb_errno(journal); } } diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 1afb701622b0..9956ac68b72b 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1340,7 +1340,7 @@ static void jbd2_mark_journal_empty(journal_t *journal) * Update a journal's errno. Write updated superblock to disk waiting for IO * to complete. */ -static void jbd2_journal_update_sb_errno(journal_t *journal) +void jbd2_journal_update_sb_errno(journal_t *journal) { journal_superblock_t *sb = journal->j_superblock; @@ -1352,6 +1352,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal) jbd2_write_superblock(journal, WRITE_SYNC); } +EXPORT_SYMBOL(jbd2_journal_update_sb_errno); /* * Read the superblock for a given journal, performing initial diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 912c30a8ddb1..2ed66ef2e68b 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1091,6 +1091,7 @@ extern int jbd2_journal_destroy (journal_t *); extern int jbd2_journal_recover (journal_t *journal); extern int jbd2_journal_wipe (journal_t *, int); extern int jbd2_journal_skip_recovery (journal_t *); +extern void jbd2_journal_update_sb_errno(journal_t *); extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t, unsigned long, int); extern void __jbd2_journal_abort_hard (journal_t *); -- GitLab From 9a321bec4fb122cb2bd60febfd9dc71eed7ee5b2 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 5 Aug 2012 23:28:16 -0400 Subject: [PATCH 0252/1799] ext4: avoid kmemcheck complaint from reading uninitialized memory commit 7e731bc9a12339f344cddf82166b82633d99dd86 upstream. Commit 03179fe923 introduced a kmemcheck complaint in ext4_da_get_block_prep() because we save and restore ei->i_da_metadata_calc_last_lblock even though it is left uninitialized in the case where i_da_metadata_calc_len is zero. This doesn't hurt anything, but silencing the kmemcheck complaint makes it easier for people to find real bugs. Addresses https://bugzilla.kernel.org/show_bug.cgi?id=45631 (which is marked as a regression). Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 78fb7ff3adb8..0eeac284126c 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -932,6 +932,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) ei->i_reserved_meta_blocks = 0; ei->i_allocated_meta_blocks = 0; ei->i_da_metadata_calc_len = 0; + ei->i_da_metadata_calc_last_lblock = 0; spin_lock_init(&(ei->i_block_reservation_lock)); #ifdef CONFIG_QUOTA ei->i_reserved_quota = 0; -- GitLab From e1b5abaa966c9baaaf90c975c4ca377dd7ab4483 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 16 Aug 2012 11:59:04 -0400 Subject: [PATCH 0253/1799] ext4: fix long mount times on very big file systems commit 0548bbb85337e532ca2ed697c3e9b227ff2ed4b4 upstream. Commit 8aeb00ff85a: "ext4: fix overhead calculation used by ext4_statfs()" introduced a O(n**2) calculation which makes very large file systems take forever to mount. Fix this with an optimization for non-bigalloc file systems. (For bigalloc file systems the overhead needs to be set in the the superblock.) Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0eeac284126c..12a278ff82a8 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -2969,6 +2969,10 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp, ext4_group_t i, ngroups = ext4_get_groups_count(sb); int s, j, count = 0; + if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC)) + return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) + + sbi->s_itb_per_group + 2); + first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + (grp * EXT4_BLOCKS_PER_GROUP(sb)); last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; -- GitLab From d8b868fd75825114c23bc28d63ee2b87033df609 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 17 Aug 2012 08:54:52 -0400 Subject: [PATCH 0254/1799] ext4: fix kernel BUG on large-scale rm -rf commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 89a4e48f8479f8145eca9698f39fe188c982212f upstream. Commit 968dee7722: "ext4: fix hole punch failure when depth is greater than 0" introduced a regression in v3.5.1/v3.6-rc1 which caused kernel crashes when users ran run "rm -rf" on large directory hierarchy on ext4 filesystems on RAID devices: BUG: unable to handle kernel NULL pointer dereference at 0000000000000028 Process rm (pid: 18229, threadinfo ffff8801276bc000, task ffff880123631710) Call Trace: [] ? __ext4_handle_dirty_metadata+0x83/0x110 [] ext4_ext_truncate+0x193/0x1d0 [] ? ext4_mark_inode_dirty+0x7f/0x1f0 [] ext4_truncate+0xf5/0x100 [] ext4_evict_inode+0x461/0x490 [] evict+0xa2/0x1a0 [] iput+0x103/0x1f0 [] do_unlinkat+0x154/0x1c0 [] ? sys_newfstatat+0x2a/0x40 [] sys_unlinkat+0x1b/0x50 [] system_call_fastpath+0x16/0x1b Code: 8b 4d 20 0f b7 41 02 48 8d 04 40 48 8d 04 81 49 89 45 18 0f b7 49 02 48 83 c1 01 49 89 4d 00 e9 ae f8 ff ff 0f 1f 00 49 8b 45 28 <48> 8b 40 28 49 89 45 20 e9 85 f8 ff ff 0f 1f 80 00 00 00 RIP [] ext4_ext_remove_space+0xa34/0xdf0 This could be reproduced as follows: The problem in commit 968dee7722 was that caused the variable 'i' to be left uninitialized if the truncate required more space than was available in the journal. This resulted in the function ext4_ext_truncate_extend_restart() returning -EAGAIN, which caused ext4_ext_remove_space() to restart the truncate operation after starting a new jbd2 handle. Reported-by: Maciej Żenczykowski Reported-by: Marti Raudsepp Tested-by: Fengguang Wu Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/extents.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 6b7daa45f6bf..8b384cc3b75a 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2596,6 +2596,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, } path[0].p_depth = depth; path[0].p_hdr = ext_inode_hdr(inode); + i = 0; if (ext4_ext_check(inode, path[0].p_hdr, depth)) { err = -EIO; -- GitLab From 40c293d87cc9a6e4b0b8e54cd8faabf9fa4bbb95 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 2 Jul 2012 13:36:23 -0700 Subject: [PATCH 0255/1799] xhci: Add Etron XHCI_TRUST_TX_LENGTH quirk. commit 5cb7df2b2d3afee7638b3ef23a5bcb89c6f07bd9 upstream. Gary reports that with recent kernels, he notices more xHCI driver warnings: xhci_hcd 0000:03:00.0: WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk? We think his Etron xHCI host controller may have the same buggy behavior as the Fresco Logic xHCI host. When a short transfer is received, the host will mark the transfer as successfully completed when it should be marking it with a short completion. Fix this by turning on the XHCI_TRUST_TX_LENGTH quirk when the Etron host is discovered. Note that Gary has revision 1, but if Etron fixes this bug in future revisions, the quirk will have no effect. This patch should be backported to kernels as old as 2.6.36, that contain a backported version of commit 1530bbc6272d9da1e39ef8e06190d42c13a02733 "xhci: Add new short TX quirk for Fresco Logic host." Signed-off-by: Sarah Sharp Reported-by: Gary E. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 19e89216436e..fccebc05b655 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -95,6 +95,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_ASROCK_P67) { xhci->quirks |= XHCI_RESET_ON_RESUME; xhci_dbg(xhci, "QUIRK: Resetting on resume\n"); + xhci->quirks |= XHCI_TRUST_TX_LENGTH; } if (pdev->vendor == PCI_VENDOR_ID_VIA) xhci->quirks |= XHCI_RESET_ON_RESUME; -- GitLab From ebd311e08218713c46f6894648084c84c48e220d Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 23 Jul 2012 16:06:08 -0700 Subject: [PATCH 0256/1799] xhci: Increase reset timeout for Renesas 720201 host. commit 22ceac191211cf6688b1bf6ecd93c8b6bf80ed9b upstream. The NEC/Renesas 720201 xHCI host controller does not complete its reset within 250 milliseconds. In fact, it takes about 9 seconds to reset the host controller, and 1 second for the host to be ready for doorbell rings. Extend the reset and CNR polling timeout to 10 seconds each. This patch should be backported to kernels as old as 2.6.31, that contain the commit 66d4eadd8d067269ea8fead1a50fe87c2979a80d "USB: xhci: BIOS handoff and HW initialization." Signed-off-by: Sarah Sharp Reported-by: Edwin Klein Mentink Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 9248d496cb8e..4cc855dda4f1 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -166,7 +166,7 @@ int xhci_reset(struct xhci_hcd *xhci) xhci_writel(xhci, command, &xhci->op_regs->command); ret = handshake(xhci, &xhci->op_regs->command, - CMD_RESET, 0, 250 * 1000); + CMD_RESET, 0, 10 * 1000 * 1000); if (ret) return ret; @@ -175,7 +175,8 @@ int xhci_reset(struct xhci_hcd *xhci) * xHCI cannot write to any doorbells or operational registers other * than status until the "Controller Not Ready" flag is cleared. */ - ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); + ret = handshake(xhci, &xhci->op_regs->status, + STS_CNR, 0, 10 * 1000 * 1000); for (i = 0; i < 2; ++i) { xhci->bus_state[i].port_c_suspend = 0; -- GitLab From 0adf7a085fae52b18202a95722fc05d644fa7a42 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 23 Jul 2012 18:59:30 +0300 Subject: [PATCH 0257/1799] xhci: Switch PPT ports to EHCI on shutdown. commit e95829f474f0db3a4d940cae1423783edd966027 upstream. The Intel desktop boards DH77EB and DH77DF have a hardware issue that can be worked around by BIOS. If the USB ports are switched to xHCI on shutdown, the xHCI host will send a spurious interrupt, which will wake the system. Some BIOS will work around this, but not all. The bug can be avoided if the USB ports are switched back to EHCI on shutdown. The Intel Windows driver switches the ports back to EHCI, so change the Linux xHCI driver to do the same. Unfortunately, we can't tell the two effected boards apart from other working motherboards, because the vendors will change the DMI strings for the DH77EB and DH77DF boards to their own custom names. One example is Compulab's mini-desktop, the Intense-PC. Instead, key off the Panther Point xHCI host PCI vendor and device ID, and switch the ports over for all PPT xHCI hosts. The only impact this will have on non-effected boards is to add a couple hundred milliseconds delay on boot when the BIOS has to switch the ports over from EHCI to xHCI. This patch should be backported to kernels as old as 3.0, that contain the commit 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support EHCI/xHCI port switching." Signed-off-by: Sarah Sharp Reported-by: Denis Turischev Tested-by: Denis Turischev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 7 +++++++ drivers/usb/host/pci-quirks.h | 1 + drivers/usb/host/xhci-pci.c | 9 +++++++++ drivers/usb/host/xhci.c | 3 +++ drivers/usb/host/xhci.h | 1 + 5 files changed, 21 insertions(+) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index df0828cb2aa3..c5e9e4a76f14 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -800,6 +800,13 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) } EXPORT_SYMBOL_GPL(usb_enable_xhci_ports); +void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) +{ + pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, 0x0); + pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, 0x0); +} +EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); + /** * PCI Quirks for xHCI. * diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index b1002a8ef96f..ef004a5de20f 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -10,6 +10,7 @@ void usb_amd_quirk_pll_disable(void); void usb_amd_quirk_pll_enable(void); bool usb_is_intel_switchable_xhci(struct pci_dev *pdev); void usb_enable_xhci_ports(struct pci_dev *xhci_pdev); +void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); #else static inline void usb_amd_quirk_pll_disable(void) {} static inline void usb_amd_quirk_pll_enable(void) {} diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index fccebc05b655..f1527404617c 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -90,6 +90,15 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_EP_LIMIT_QUIRK; xhci->limit_active_eps = 64; xhci->quirks |= XHCI_SW_BW_CHECKING; + /* + * PPT desktop boards DH77EB and DH77DF will power back on after + * a few seconds of being shutdown. The fix for this is to + * switch the ports from xHCI to EHCI on shutdown. We can't use + * DMI information to find those particular boards (since each + * vendor will change the board name), so we have to key off all + * PPT chipsets. + */ + xhci->quirks |= XHCI_SPURIOUS_REBOOT; } if (pdev->vendor == PCI_VENDOR_ID_ETRON && pdev->device == PCI_DEVICE_ID_ASROCK_P67) { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 4cc855dda4f1..7beed536e6b9 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -659,6 +659,9 @@ void xhci_shutdown(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); + if (xhci->quirks && XHCI_SPURIOUS_REBOOT) + usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); + spin_lock_irq(&xhci->lock); xhci_halt(xhci); spin_unlock_irq(&xhci->lock); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 59434fe9d7d9..19ae30f1d84a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1486,6 +1486,7 @@ struct xhci_hcd { #define XHCI_SW_BW_CHECKING (1 << 8) #define XHCI_AMD_0x96_HOST (1 << 9) #define XHCI_TRUST_TX_LENGTH (1 << 10) +#define XHCI_SPURIOUS_REBOOT (1 << 13) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ -- GitLab From 1aac2e73a8af6ce1cd6e938967dd17e2c8d38994 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 26 Jul 2012 12:03:59 -0700 Subject: [PATCH 0258/1799] xhci: Fix bug after deq ptr set to link TRB. commit 50d0206fcaea3e736f912fd5b00ec6233fb4ce44 upstream. This patch fixes a particularly nasty bug that was revealed by the ring expansion patches. The bug has been present since the very beginning of the xHCI driver history, and could have caused general protection faults from bad memory accesses. The first thing to note is that a Set TR Dequeue Pointer command can move the dequeue pointer to a link TRB, if the canceled or stalled transfer TD ended just before a link TRB. The function to increment the dequeue pointer, inc_deq, was written before cancellation and stall support was added. It assumed that the dequeue pointer could never point to a link TRB. It would unconditionally increment the dequeue pointer at the start of the function, check if the pointer was now on a link TRB, and move it to the top of the next segment if so. This means that if a Set TR Dequeue Point command moved the dequeue pointer to a link TRB, a subsequent call to inc_deq() would move the pointer off the segment and into la-la-land. It would then read from that memory to determine if it was a link TRB. Other functions would often call inc_deq() until the dequeue pointer matched some other pointer, which means this function would quite happily read all of system memory before wrapping around to the right pointer value. Often, there would be another endpoint segment from a different ring allocated from the same DMA pool, which would be contiguous to the segment inc_deq just stepped off of. inc_deq would eventually find the link TRB in that segment, and blindly move the dequeue pointer back to the top of the correct ring segment. The only reason the original code worked at all is because there was only one ring segment. With the ring expansion patches, the dequeue pointer would eventually wrap into place, but the dequeue segment would be out-of-sync. On the second TD after the dequeue pointer was moved to a link TRB, trb_in_td() would fail (because the dequeue pointer and dequeue segment were out-of-sync), and this message would appear: ERROR Transfer event TRB DMA ptr not part of current TD This fixes bugzilla entry 4333 (option-based modem unhappy on USB 3.0 port: "Transfer event TRB DMA ptr not part of current TD", "rejecting I/O to offline device"), https://bugzilla.kernel.org/show_bug.cgi?id=43333 and possibly other general protection fault bugs as well. This patch should be backported to kernels as old as 2.6.31. A separate patch will be created for kernels older than 3.4, since inc_deq was modified in 3.4 and this patch will not apply. Signed-off-by: Sarah Sharp Tested-by: James Ettle Tested-by: Matthew Hall Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 158175bfecdf..203ba315c72a 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -145,29 +145,37 @@ static void next_trb(struct xhci_hcd *xhci, */ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) { - union xhci_trb *next; unsigned long long addr; ring->deq_updates++; - /* If this is not event ring, there is one more usable TRB */ + /* + * If this is not event ring, and the dequeue pointer + * is not on a link TRB, there is one more usable TRB + */ if (ring->type != TYPE_EVENT && !last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) ring->num_trbs_free++; - next = ++(ring->dequeue); - /* Update the dequeue pointer further if that was a link TRB or we're at - * the end of an event ring segment (which doesn't have link TRBS) - */ - while (last_trb(xhci, ring, ring->deq_seg, next)) { - if (ring->type == TYPE_EVENT && last_trb_on_last_seg(xhci, - ring, ring->deq_seg, next)) { - ring->cycle_state = (ring->cycle_state ? 0 : 1); + do { + /* + * Update the dequeue pointer further if that was a link TRB or + * we're at the end of an event ring segment (which doesn't have + * link TRBS) + */ + if (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) { + if (ring->type == TYPE_EVENT && + last_trb_on_last_seg(xhci, ring, + ring->deq_seg, ring->dequeue)) { + ring->cycle_state = (ring->cycle_state ? 0 : 1); + } + ring->deq_seg = ring->deq_seg->next; + ring->dequeue = ring->deq_seg->trbs; + } else { + ring->dequeue++; } - ring->deq_seg = ring->deq_seg->next; - ring->dequeue = ring->deq_seg->trbs; - next = ring->dequeue; - } + } while (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)); + addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue); } -- GitLab From 952227d5c4d522502b7b815b16be6e991bbaeaed Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Tue, 10 Jul 2012 19:10:06 -0300 Subject: [PATCH 0259/1799] USB: add USB_VENDOR_AND_INTERFACE_INFO() macro commit d81a5d1956731c453b85c141458d4ff5d6cc5366 upstream. A lot of Broadcom Bluetooth devices provides vendor specific interface class and we are getting flooded by patches adding new device support. This change will help us enable support for any other Broadcom with vendor specific device that arrives in the future. Only the product id changes for those devices, so this macro would be perfect for us: { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) } Signed-off-by: Marcel Holtmann Signed-off-by: Gustavo Padovan Acked-by: Henrik Rydberg Signed-off-by: Greg Kroah-Hartman --- include/linux/usb.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/linux/usb.h b/include/linux/usb.h index 26229fd8d617..4e8e6685f513 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -783,6 +783,27 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size) .bInterfaceSubClass = (sc), \ .bInterfaceProtocol = (pr) +/** + * USB_VENDOR_AND_INTERFACE_INFO - describe a specific usb vendor with a class of usb interfaces + * @vend: the 16 bit USB Vendor ID + * @cl: bInterfaceClass value + * @sc: bInterfaceSubClass value + * @pr: bInterfaceProtocol value + * + * This macro is used to create a struct usb_device_id that matches a + * specific vendor with a specific class of interfaces. + * + * This is especially useful when explicitly matching devices that have + * vendor specific bDeviceClass values, but standards-compliant interfaces. + */ +#define USB_VENDOR_AND_INTERFACE_INFO(vend, cl, sc, pr) \ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \ + | USB_DEVICE_ID_MATCH_VENDOR, \ + .idVendor = (vend), \ + .bInterfaceClass = (cl), \ + .bInterfaceSubClass = (sc), \ + .bInterfaceProtocol = (pr) + /* ----------------------------------------------------------------------- */ /* Stuff for dynamic usb ids */ -- GitLab From a8e480349f91581d93eff8728fc41cbcd1c3eca1 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Sun, 12 Aug 2012 07:16:43 -0500 Subject: [PATCH 0260/1799] pmac_zilog,kdb: Fix console poll hook to return instead of loop commit 38f8eefccf3a23c4058a570fa2938a4f553cf8e0 upstream. kdb <-> kgdb transitioning does not work properly with this UART driver because the get character routine loops indefinitely as opposed to returning NO_POLL_CHAR per the expectation of the KDB I/O driver API. The symptom is a kernel hang when trying to switch debug modes. Signed-off-by: Jason Wessel Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pmac_zilog.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index 654755a990df..333c8d012b0e 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -1348,10 +1348,16 @@ static int pmz_verify_port(struct uart_port *port, struct serial_struct *ser) static int pmz_poll_get_char(struct uart_port *port) { struct uart_pmac_port *uap = (struct uart_pmac_port *)port; + int tries = 2; - while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) - udelay(5); - return read_zsdata(uap); + while (tries) { + if ((read_zsreg(uap, R0) & Rx_CH_AV) != 0) + return read_zsdata(uap); + if (tries--) + udelay(5); + } + + return NO_POLL_CHAR; } static void pmz_poll_put_char(struct uart_port *port, unsigned char c) -- GitLab From ddffad3427e2e80fff78d2fc77f21afbba3d11b0 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 14 Aug 2012 13:18:53 +0000 Subject: [PATCH 0261/1799] IB/srp: Fix a race condition commit 220329916c72ee3d54ae7262b215a050f04a18fc upstream. Avoid a crash caused by the scmnd->scsi_done(scmnd) call in srp_process_rsp() being invoked with scsi_done == NULL. This can happen if a reply is received during or after a command abort. Reported-by: Joseph Glanville Reference: http://marc.info/?l=linux-rdma&m=134314367801595 Acked-by: David Dillow Signed-off-by: Bart Van Assche Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/srp/ib_srp.c | 87 +++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 24 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index bcbf22ee0aa7..1b5b0c730054 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -586,24 +586,62 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, scmnd->sc_data_direction); } -static void srp_remove_req(struct srp_target_port *target, - struct srp_request *req, s32 req_lim_delta) +/** + * srp_claim_req - Take ownership of the scmnd associated with a request. + * @target: SRP target port. + * @req: SRP request. + * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take + * ownership of @req->scmnd if it equals @scmnd. + * + * Return value: + * Either NULL or a pointer to the SCSI command the caller became owner of. + */ +static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target, + struct srp_request *req, + struct scsi_cmnd *scmnd) +{ + unsigned long flags; + + spin_lock_irqsave(&target->lock, flags); + if (!scmnd) { + scmnd = req->scmnd; + req->scmnd = NULL; + } else if (req->scmnd == scmnd) { + req->scmnd = NULL; + } else { + scmnd = NULL; + } + spin_unlock_irqrestore(&target->lock, flags); + + return scmnd; +} + +/** + * srp_free_req() - Unmap data and add request to the free request list. + */ +static void srp_free_req(struct srp_target_port *target, + struct srp_request *req, struct scsi_cmnd *scmnd, + s32 req_lim_delta) { unsigned long flags; - srp_unmap_data(req->scmnd, target, req); + srp_unmap_data(scmnd, target, req); + spin_lock_irqsave(&target->lock, flags); target->req_lim += req_lim_delta; - req->scmnd = NULL; list_add_tail(&req->list, &target->free_reqs); spin_unlock_irqrestore(&target->lock, flags); } static void srp_reset_req(struct srp_target_port *target, struct srp_request *req) { - req->scmnd->result = DID_RESET << 16; - req->scmnd->scsi_done(req->scmnd); - srp_remove_req(target, req, 0); + struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL); + + if (scmnd) { + scmnd->result = DID_RESET << 16; + scmnd->scsi_done(scmnd); + srp_free_req(target, req, scmnd, 0); + } } static int srp_reconnect_target(struct srp_target_port *target) @@ -1073,11 +1111,18 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) complete(&target->tsk_mgmt_done); } else { req = &target->req_ring[rsp->tag]; - scmnd = req->scmnd; - if (!scmnd) + scmnd = srp_claim_req(target, req, NULL); + if (!scmnd) { shost_printk(KERN_ERR, target->scsi_host, "Null scmnd for RSP w/tag %016llx\n", (unsigned long long) rsp->tag); + + spin_lock_irqsave(&target->lock, flags); + target->req_lim += be32_to_cpu(rsp->req_lim_delta); + spin_unlock_irqrestore(&target->lock, flags); + + return; + } scmnd->result = rsp->status; if (rsp->flags & SRP_RSP_FLAG_SNSVALID) { @@ -1092,7 +1137,9 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER)) scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt)); - srp_remove_req(target, req, be32_to_cpu(rsp->req_lim_delta)); + srp_free_req(target, req, scmnd, + be32_to_cpu(rsp->req_lim_delta)); + scmnd->host_scribble = NULL; scmnd->scsi_done(scmnd); } @@ -1631,25 +1678,17 @@ static int srp_abort(struct scsi_cmnd *scmnd) { struct srp_target_port *target = host_to_target(scmnd->device->host); struct srp_request *req = (struct srp_request *) scmnd->host_scribble; - int ret = SUCCESS; shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); - if (!req || target->qp_in_error) + if (!req || target->qp_in_error || !srp_claim_req(target, req, scmnd)) return FAILED; - if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, - SRP_TSK_ABORT_TASK)) - return FAILED; - - if (req->scmnd) { - if (!target->tsk_mgmt_status) { - srp_remove_req(target, req, 0); - scmnd->result = DID_ABORT << 16; - } else - ret = FAILED; - } + srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, + SRP_TSK_ABORT_TASK); + srp_free_req(target, req, scmnd, 0); + scmnd->result = DID_ABORT << 16; - return ret; + return SUCCESS; } static int srp_reset_device(struct scsi_cmnd *scmnd) -- GitLab From c638628c4aafdd2c6bb555331e5dcb099df7f59c Mon Sep 17 00:00:00 2001 From: fangxiaozhi Date: Wed, 8 Aug 2012 09:24:45 +0000 Subject: [PATCH 0262/1799] USB: support the new interfaces of Huawei Data Card devices in option driver commit ee6f827df9107139e8960326e49e1376352ced4d upstream. In this patch, we add new declarations into option.c to support the new interfaces of Huawei Data Card devices. And at the same time, remove the redundant declarations from option.c. Signed-off-by: fangxiaozhi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 279 ++++++++++++++---------------------- 1 file changed, 111 insertions(+), 168 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ae1a4b8c6893..87d13546ee8d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -80,85 +80,9 @@ static void option_instat_callback(struct urb *urb); #define OPTION_PRODUCT_GTM380_MODEM 0x7201 #define HUAWEI_VENDOR_ID 0x12D1 -#define HUAWEI_PRODUCT_E600 0x1001 -#define HUAWEI_PRODUCT_E220 0x1003 -#define HUAWEI_PRODUCT_E220BIS 0x1004 -#define HUAWEI_PRODUCT_E1401 0x1401 -#define HUAWEI_PRODUCT_E1402 0x1402 -#define HUAWEI_PRODUCT_E1403 0x1403 -#define HUAWEI_PRODUCT_E1404 0x1404 -#define HUAWEI_PRODUCT_E1405 0x1405 -#define HUAWEI_PRODUCT_E1406 0x1406 -#define HUAWEI_PRODUCT_E1407 0x1407 -#define HUAWEI_PRODUCT_E1408 0x1408 -#define HUAWEI_PRODUCT_E1409 0x1409 -#define HUAWEI_PRODUCT_E140A 0x140A -#define HUAWEI_PRODUCT_E140B 0x140B -#define HUAWEI_PRODUCT_E140C 0x140C -#define HUAWEI_PRODUCT_E140D 0x140D -#define HUAWEI_PRODUCT_E140E 0x140E -#define HUAWEI_PRODUCT_E140F 0x140F -#define HUAWEI_PRODUCT_E1410 0x1410 -#define HUAWEI_PRODUCT_E1411 0x1411 -#define HUAWEI_PRODUCT_E1412 0x1412 -#define HUAWEI_PRODUCT_E1413 0x1413 -#define HUAWEI_PRODUCT_E1414 0x1414 -#define HUAWEI_PRODUCT_E1415 0x1415 -#define HUAWEI_PRODUCT_E1416 0x1416 -#define HUAWEI_PRODUCT_E1417 0x1417 -#define HUAWEI_PRODUCT_E1418 0x1418 -#define HUAWEI_PRODUCT_E1419 0x1419 -#define HUAWEI_PRODUCT_E141A 0x141A -#define HUAWEI_PRODUCT_E141B 0x141B -#define HUAWEI_PRODUCT_E141C 0x141C -#define HUAWEI_PRODUCT_E141D 0x141D -#define HUAWEI_PRODUCT_E141E 0x141E -#define HUAWEI_PRODUCT_E141F 0x141F -#define HUAWEI_PRODUCT_E1420 0x1420 -#define HUAWEI_PRODUCT_E1421 0x1421 -#define HUAWEI_PRODUCT_E1422 0x1422 -#define HUAWEI_PRODUCT_E1423 0x1423 -#define HUAWEI_PRODUCT_E1424 0x1424 -#define HUAWEI_PRODUCT_E1425 0x1425 -#define HUAWEI_PRODUCT_E1426 0x1426 -#define HUAWEI_PRODUCT_E1427 0x1427 -#define HUAWEI_PRODUCT_E1428 0x1428 -#define HUAWEI_PRODUCT_E1429 0x1429 -#define HUAWEI_PRODUCT_E142A 0x142A -#define HUAWEI_PRODUCT_E142B 0x142B -#define HUAWEI_PRODUCT_E142C 0x142C -#define HUAWEI_PRODUCT_E142D 0x142D -#define HUAWEI_PRODUCT_E142E 0x142E -#define HUAWEI_PRODUCT_E142F 0x142F -#define HUAWEI_PRODUCT_E1430 0x1430 -#define HUAWEI_PRODUCT_E1431 0x1431 -#define HUAWEI_PRODUCT_E1432 0x1432 -#define HUAWEI_PRODUCT_E1433 0x1433 -#define HUAWEI_PRODUCT_E1434 0x1434 -#define HUAWEI_PRODUCT_E1435 0x1435 -#define HUAWEI_PRODUCT_E1436 0x1436 -#define HUAWEI_PRODUCT_E1437 0x1437 -#define HUAWEI_PRODUCT_E1438 0x1438 -#define HUAWEI_PRODUCT_E1439 0x1439 -#define HUAWEI_PRODUCT_E143A 0x143A -#define HUAWEI_PRODUCT_E143B 0x143B -#define HUAWEI_PRODUCT_E143C 0x143C -#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_K3806 0x14AE #define HUAWEI_PRODUCT_K4605 0x14C6 -#define HUAWEI_PRODUCT_K5005 0x14C8 -#define HUAWEI_PRODUCT_K3770 0x14C9 -#define HUAWEI_PRODUCT_K3771 0x14CA -#define HUAWEI_PRODUCT_K4510 0x14CB -#define HUAWEI_PRODUCT_K4511 0x14CC -#define HUAWEI_PRODUCT_ETS1220 0x1803 -#define HUAWEI_PRODUCT_E353 0x1506 -#define HUAWEI_PRODUCT_E173S 0x1C05 #define QUANTA_VENDOR_ID 0x0408 #define QUANTA_PRODUCT_Q101 0xEA02 @@ -615,104 +539,123 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) }, - { 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_E173S, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x33) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x10) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x12) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x13) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x01) }, /* E398 3G Modem */ - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x02) }, /* E398 3G PC UI Interface */ - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x03) }, /* E398 3G Application Interface */ + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0xff, 0xff) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) }, + + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, -- GitLab From 7c65b87f22d8a7819879363ef9fc3e6d838925d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 15 Aug 2012 15:43:33 +0200 Subject: [PATCH 0263/1799] USB: option: add ZTE K5006-Z MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f1b5c997e68533df1f96dcd3068a231bca495603 upstream. The ZTE (Vodafone) K5006-Z use the following interface layout: 00 DIAG 01 secondary 02 modem 03 networkcard 04 storage Ignoring interface #3 which is handled by the qmi_wwan driver. Signed-off-by: Bjørn Mork Cc: Thomas Schäfer 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 87d13546ee8d..ee693ccfdeb6 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -886,6 +886,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, -- GitLab From d3d31e57513f7f66fe66accd88837e021a1b96b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ozan=20=C3=87a=C4=9Flayan?= Date: Fri, 10 Aug 2012 17:25:10 +0300 Subject: [PATCH 0264/1799] USB: ftdi_sio: Add VID/PID for Kondo Serial USB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7724a1edbe463b06d4e7831a41149ba095b16c53 upstream. This adds VID/PID for Kondo Kagaku Co. Ltd. Serial USB Adapter interface: http://www.kondo-robot.com/EN/wp/?cat=28 Tested by controlling an RCB3 board using libRCB3. Signed-off-by: Ozan Çağlayan Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 53e3e2c5b337..f5819cb4dcf4 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -811,6 +811,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, { USB_DEVICE(PI_VID, PI_E861_PID) }, + { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) }, { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 5661c7e2d415..5dd96ca6c380 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -794,6 +794,13 @@ #define PI_VID 0x1a72 /* Vendor ID */ #define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */ +/* + * Kondo Kagaku Co.Ltd. + * http://www.kondo-robot.com/EN + */ +#define KONDO_VID 0x165c +#define KONDO_USB_SERIAL_PID 0x0002 + /* * Bayer Ascensia Contour blood glucose meter USB-converter cable. * http://winglucofacts.com/cables/ -- GitLab From 4893ce51af5c2ccdfabf8f7d34dd28cf84a8a06e Mon Sep 17 00:00:00 2001 From: Mark Ferrell Date: Tue, 24 Jul 2012 14:15:13 -0500 Subject: [PATCH 0265/1799] usb: serial: mos7840: Fixup mos7840_chars_in_buffer() commit 5c263b92f828af6a8cf54041db45ceae5af8f2ab upstream. * Use the buffer content length as opposed to the total buffer size. This can be a real problem when using the mos7840 as a usb serial-console as all kernel output is truncated during boot. Signed-off-by: Mark Ferrell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 62739ff58c72..c1505c3c557a 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1189,9 +1189,12 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty) } spin_lock_irqsave(&mos7840_port->pool_lock, flags); - for (i = 0; i < NUM_URBS; ++i) - if (mos7840_port->busy[i]) - chars += URB_TRANSFER_BUFFER_SIZE; + for (i = 0; i < NUM_URBS; ++i) { + if (mos7840_port->busy[i]) { + struct urb *urb = mos7840_port->write_urb_pool[i]; + chars += urb->transfer_buffer_length; + } + } spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); dbg("%s - returns %d", __func__, chars); return chars; -- GitLab From 4cfb77e8eeddabbca1173a0a704c4065c62c4d05 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Wed, 8 Aug 2012 11:48:10 +0200 Subject: [PATCH 0266/1799] usb: gadget: u_ether: fix kworker 100% CPU issue with still used interfaces in eth_stop commit b1b552a69b8805e7e338074a9e8b670b4a795218 upstream. This patch fixes an issue introduced by patch: 72c973d usb: gadget: add usb_endpoint_descriptor to struct usb_ep Without this patch we see a kworker taking 100% CPU, after this sequence: - Connect gadget to a windows host - load g_ether - ifconfig up ; ifconfig down; ifconfig up - ping The "ifconfig down" results in calling eth_stop(), which will call usb_ep_disable() and, if the carrier is still ok, usb_ep_enable(): usb_ep_disable(link->in_ep); usb_ep_disable(link->out_ep); if (netif_carrier_ok(net)) { usb_ep_enable(link->in_ep); usb_ep_enable(link->out_ep); } The ep should stay enabled, but will not, as ep_disable set the desc pointer to NULL, therefore the subsequent ep_enable will fail. This leads to permanent rescheduling of the eth_work() worker as usb_ep_queue() (called by the worker) will fail due to the unconfigured endpoint. We fix this issue by saving the ep descriptors and re-assign them before usb_ep_enable(). Cc: Tatyana Brokhman Signed-off-by: Michael Grzeschik Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/u_ether.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 4e1f0aaafcfe..9a2a1ae9b667 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -669,6 +669,8 @@ static int eth_stop(struct net_device *net) spin_lock_irqsave(&dev->lock, flags); if (dev->port_usb) { struct gether *link = dev->port_usb; + const struct usb_endpoint_descriptor *in; + const struct usb_endpoint_descriptor *out; if (link->close) link->close(link); @@ -682,10 +684,14 @@ static int eth_stop(struct net_device *net) * their own pace; the network stack can handle old packets. * For the moment we leave this here, since it works. */ + in = link->in_ep->desc; + out = link->out_ep->desc; usb_ep_disable(link->in_ep); usb_ep_disable(link->out_ep); if (netif_carrier_ok(net)) { DBG(dev, "host still using in/out endpoints\n"); + link->in_ep->desc = in; + link->out_ep->desc = out; usb_ep_enable(link->in_ep); usb_ep_enable(link->out_ep); } -- GitLab From e19001248f898e24b4ec08f9f853b49e661328fe Mon Sep 17 00:00:00 2001 From: Jeongdo Son Date: Fri, 15 Jun 2012 02:28:01 +0900 Subject: [PATCH 0267/1799] rt2x00: Add support for BUFFALO WLI-UC-GNM2 to rt2800usb. commit a769f9577232afe2c754606a83aad85127e7052a upstream. This is a RT3070 based device. Signed-off-by: Jeongdo Son Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2800usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index f388b65fbe90..7e1a492680c1 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -971,6 +971,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0411, 0x015d) }, { USB_DEVICE(0x0411, 0x016f) }, { USB_DEVICE(0x0411, 0x01a2) }, + { USB_DEVICE(0x0411, 0x01ee) }, /* Corega */ { USB_DEVICE(0x07aa, 0x002f) }, { USB_DEVICE(0x07aa, 0x003c) }, -- GitLab From f95b978981a7d154ba40d14c18e8ed5c694e6124 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 26 Aug 2012 15:02:10 -0700 Subject: [PATCH 0268/1799] Linux 3.4.10 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9549547614b2..a1624b991301 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 9 +SUBLEVEL = 10 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 61fe808721d1b13c811f6d9a2809628e4ef6bf06 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:33 -0700 Subject: [PATCH 0269/1799] USB: vt6656: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4d088876f24887cd15a29db923f5f37db6a99f21 upstream. This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork CC: Forest Bond CC: Marcos Paulo de Souza CC: "David S. Miller" CC: Jesper Juhl CC: Jiri Pirko Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 763e028a5cc5..87394541d715 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -222,7 +222,7 @@ DEVICE_PARAM(b80211hEnable, "802.11h mode"); // Static vars definitions // -static struct usb_device_id vt6656_table[] __devinitdata = { +static struct usb_device_id vt6656_table[] = { {USB_DEVICE(VNT_USB_VENDOR_ID, VNT_USB_PRODUCT_ID)}, {} }; -- GitLab From 7d79cc4869cd9fdc47736a5fe44c195813cef4cd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:41 -0700 Subject: [PATCH 0270/1799] USB: emi62: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 83957df21dd94655d2b026e0944a69ff37b83988 upstream. This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork CC: Paul Gortmaker CC: Andrew Morton CC: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/emi62.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 4e0f167a6c4e..8be96de5f6e7 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -256,7 +256,7 @@ static int emi62_load_firmware (struct usb_device *dev) return err; } -static const struct usb_device_id id_table[] __devinitconst = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) }, { } /* Terminating entry */ }; -- GitLab From 5ed0dc3c88fd7586d5ea0b615007bbcf1c7cf7ea Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Mon, 13 Aug 2012 14:11:10 +0800 Subject: [PATCH 0271/1799] ALSA: hda - fix Copyright debug message commit 088c820b732dbfd515fc66d459d5f5777f79b406 upstream. As spec said, 1 indicates no copyright is asserted. Signed-off-by: Wang Xingchao Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index e59e2f059b6e..0074aee6d393 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -412,7 +412,7 @@ static void print_digital_conv(struct snd_info_buffer *buffer, if (digi1 & AC_DIG1_EMPHASIS) snd_iprintf(buffer, " Preemphasis"); if (digi1 & AC_DIG1_COPYRIGHT) - snd_iprintf(buffer, " Copyright"); + snd_iprintf(buffer, " Non-Copyright"); if (digi1 & AC_DIG1_NONAUDIO) snd_iprintf(buffer, " Non-Audio"); if (digi1 & AC_DIG1_PROFESSIONAL) -- GitLab From 7de4da6fedad1267970c6640e47561c2d38ec0b4 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 3 Aug 2012 17:24:14 +0100 Subject: [PATCH 0272/1799] ARM: 7483/1: vfp: only advertise VFPv4 in hwcaps if CONFIG_VFPv3 is enabled commit 3d9fb0038a9b02febb01efc79a4a5d97f1822a90 upstream. VFPv4 support depends on the VFPv3 context save/restore code, so only advertise support in the hwcaps if the kernel can actually handle it. Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/vfp/vfpmodule.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 1ef803aa7a5c..1f8241da03be 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -719,8 +719,10 @@ static int __init vfp_init(void) if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100) elf_hwcap |= HWCAP_NEON; #endif +#ifdef CONFIG_VFPv3 if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000) elf_hwcap |= HWCAP_VFPv4; +#endif } } return 0; -- GitLab From aa2e66e8fc1a25b9ff6f6f448a025b3599a90662 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 10 Aug 2012 17:51:18 +0100 Subject: [PATCH 0273/1799] ARM: 7487/1: mm: avoid setting nG bit for user mappings that aren't present commit 47f1204329237a0f8655f5a9f14a38ac81946ca1 upstream. Swap entries are encoding in ptes such that !pte_present(pte) and pte_file(pte). The remaining bits of the descriptor are used to identify the swapfile and offset within it to the swap entry. When writing such a pte for a user virtual address, set_pte_at unconditionally sets the nG bit, which (in the case of LPAE) will corrupt the swapfile offset and lead to a BUG: [ 140.494067] swap_free: Unused swap offset entry 000763b4 [ 140.509989] BUG: Bad page map in process rs:main Q:Reg pte:0ec76800 pmd:8f92e003 This patch fixes the problem by only setting the nG bit for user mappings that are actually present. Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/pgtable.h | 34 ++++++++++++++++++---------------- arch/arm/mm/flush.c | 2 -- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index f66626d71e7d..d88f9f049e95 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -195,6 +195,18 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) +#define pte_none(pte) (!pte_val(pte)) +#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) +#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) +#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) +#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) +#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) +#define pte_special(pte) (0) + +#define pte_present_user(pte) \ + ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ + (L_PTE_PRESENT | L_PTE_USER)) + #if __LINUX_ARM_ARCH__ < 6 static inline void __sync_icache_dcache(pte_t pteval) { @@ -206,25 +218,15 @@ extern void __sync_icache_dcache(pte_t pteval); static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval) { - if (addr >= TASK_SIZE) - set_pte_ext(ptep, pteval, 0); - else { + unsigned long ext = 0; + + if (addr < TASK_SIZE && pte_present_user(pteval)) { __sync_icache_dcache(pteval); - set_pte_ext(ptep, pteval, PTE_EXT_NG); + ext |= PTE_EXT_NG; } -} -#define pte_none(pte) (!pte_val(pte)) -#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) -#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) -#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) -#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) -#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) -#define pte_special(pte) (0) - -#define pte_present_user(pte) \ - ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ - (L_PTE_PRESENT | L_PTE_USER)) + set_pte_ext(ptep, pteval, ext); +} #define PTE_BIT_FUNC(fn,op) \ static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 77458548e031..40ca11ed6e5f 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -231,8 +231,6 @@ void __sync_icache_dcache(pte_t pteval) struct page *page; struct address_space *mapping; - if (!pte_present_user(pteval)) - return; if (cache_is_vipt_nonaliasing() && !pte_exec(pteval)) /* only flush non-aliasing VIPT caches for exec mappings */ return; -- GitLab From 635a2a845fb26b32b179d7cb7cfb288c91f39933 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 10 Aug 2012 17:51:19 +0100 Subject: [PATCH 0274/1799] ARM: 7488/1: mm: use 5 bits for swapfile type encoding commit f5f2025ef3e2cdb593707cbf87378761f17befbe upstream. Page migration encodes the pfn in the offset field of a swp_entry_t. For LPAE, we support physical addresses of up to 36 bits (due to sparsemem limitations with the size of page flags), requiring 24 bits to represent a pfn. A further 3 bits are used to encode a swp_entry into a pte, leaving 5 bits for the type field. Furthermore, the core code defines MAX_SWAPFILES_SHIFT as 5, so the additional type bit does not get used. This patch reduces the width of the type field to 5 bits, allowing us to create up to 31 swapfiles of 64GB each. Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/pgtable.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index d88f9f049e95..41dc31f834c3 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -253,13 +253,13 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) * * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * <--------------- offset --------------------> <- type --> 0 0 0 + * <--------------- offset ----------------------> < type -> 0 0 0 * - * This gives us up to 63 swap files and 32GB per swap file. Note that + * This gives us up to 31 swap files and 64GB per swap file. Note that * the offset field is always non-zero. */ #define __SWP_TYPE_SHIFT 3 -#define __SWP_TYPE_BITS 6 +#define __SWP_TYPE_BITS 5 #define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) #define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) -- GitLab From 88b67cb1f21cf5059bfbbc2bca7a597b9c58c312 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 10 Aug 2012 19:13:36 +0100 Subject: [PATCH 0275/1799] ARM: 7489/1: errata: fix workaround for erratum #720789 on UP systems commit 730a8128cd8978467eb1cf546b11014acb57d433 upstream. Commit 5a783cbc4836 ("ARM: 7478/1: errata: extend workaround for erratum #720789") added workarounds for erratum #720789 to the range TLB invalidation functions with the observation that the erratum only affects SMP platforms. However, when running an SMP_ON_UP kernel on a uniprocessor platform we must take care to preserve the ASID as the workaround is not required. This patch ensures that we don't set the ASID to 0 when flushing the TLB on such a system, preserving the original behaviour with the workaround disabled. Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/mm/tlb-v7.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S index c2021139cb56..ea94765acf9a 100644 --- a/arch/arm/mm/tlb-v7.S +++ b/arch/arm/mm/tlb-v7.S @@ -38,10 +38,10 @@ ENTRY(v7wbi_flush_user_tlb_range) dsb mov r0, r0, lsr #PAGE_SHIFT @ align address mov r1, r1, lsr #PAGE_SHIFT -#ifdef CONFIG_ARM_ERRATA_720789 - mov r3, #0 -#else asid r3, r3 @ mask ASID +#ifdef CONFIG_ARM_ERRATA_720789 + ALT_SMP(W(mov) r3, #0 ) + ALT_UP(W(nop) ) #endif orr r0, r3, r0, lsl #PAGE_SHIFT @ Create initial MVA mov r1, r1, lsl #PAGE_SHIFT -- GitLab From 8c17041815762b385631d3a680128dca5a9be31b Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 13 Jul 2012 15:12:03 -0500 Subject: [PATCH 0276/1799] ARM: OMAP2+: Fix dmtimer set source clock failure commit 54f32a35f4d3a653a18a2c8c239f19ae060bd803 upstream. Calling the dmtimer function omap_dm_timer_set_source() fails if following a call to pm_runtime_put() to disable the timer. For example the following sequence would fail to set the parent clock ... omap_dm_timer_stop(gptimer); omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ); The following error message would be seen ... omap_dm_timer_set_source: failed to set timer_32k_ck as parent The problem is that, by design, pm_runtime_put() simply decrements the usage count and returns before the timer has actually been disabled. Therefore, setting the parent clock failed because the timer was still active when the trying to set the parent clock. Setting a parent clock will fail if the clock you are setting the parent of has a non-zero usage count. To ensure that this does not fail use pm_runtime_put_sync() when disabling the timer. Note that this will not be seen on OMAP1 devices, because these devices do not use the clock framework for dmtimers. Signed-off-by: Jon Hunter Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-omap/dmtimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 652139c0339e..7ac301ee283c 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -238,7 +238,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_enable); void omap_dm_timer_disable(struct omap_dm_timer *timer) { - pm_runtime_put(&timer->pdev->dev); + pm_runtime_put_sync(&timer->pdev->dev); } EXPORT_SYMBOL_GPL(omap_dm_timer_disable); -- GitLab From cef2cf5590819d565db994008a6bbb9f27dd9b41 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 7 Aug 2012 19:11:33 +0900 Subject: [PATCH 0277/1799] ARM: S3C24XX: Add missing DMACH_DT_PROP commit e1267371eacf2cbcf580e41f9e64a986cdaf5c1d upstream. Commit 2b90807549 (spi: s3c64xx: add device tree support) requires the DMACH_DT_PROP element in the dma_ch enum. It's not used on non-DT platforms but has to be present nevertheless. So mimic the dummy-add of DMACH_DT_PROP on s3c64xx for s3c24xx machines, to correct the build breakage for the s3c24xx variants using the s3c64xx-spi-driver. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-s3c24xx/include/mach/dma.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-s3c24xx/include/mach/dma.h b/arch/arm/mach-s3c24xx/include/mach/dma.h index acbdfecd4186..ccaaafc65c12 100644 --- a/arch/arm/mach-s3c24xx/include/mach/dma.h +++ b/arch/arm/mach-s3c24xx/include/mach/dma.h @@ -24,7 +24,8 @@ */ enum dma_ch { - DMACH_XD0, + DMACH_DT_PROP = -1, /* not yet supported, do not use */ + DMACH_XD0 = 0, DMACH_XD1, DMACH_SDI, DMACH_SPI0, -- GitLab From 588d6b125faae8f369352dedaa4632071b93e78e Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 7 Aug 2012 19:12:05 +0900 Subject: [PATCH 0278/1799] ARM: S3C24XX: Fix s3c2410_dma_enqueue parameters commit b01858c7806e7e6f6121da2e51c9222fc4d21dc6 upstream. Commit d670ac019f60 (ARM: SAMSUNG: DMA Cleanup as per sparse) changed the prototype of the s3c2410_dma_* functions to use the enum dma_ch instead of an generic unsigned int. In the s3c24xx dma.c s3c2410_dma_enqueue seems to have been forgotten, the other functions there were changed correctly. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-s3c24xx/dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index 28f898f75380..db98e7021f0d 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -430,7 +430,7 @@ s3c2410_dma_canload(struct s3c2410_dma_chan *chan) * when necessary. */ -int s3c2410_dma_enqueue(unsigned int channel, void *id, +int s3c2410_dma_enqueue(enum dma_ch channel, void *id, dma_addr_t data, int size) { struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); -- GitLab From 449daa0ed24c186c7fd014e698f37cbb8aaf7a4c Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 3 Jul 2012 15:33:29 -0300 Subject: [PATCH 0279/1799] Revert dma: imx-dma: Fix kernel crash due to missing clock conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts 9ea2c02bafe276e97b592a046ac733610a6d57fd, which was commit a2367db2ec5e7fc6fe93e221e0fcdee81b053daf upstream. It broke the build on 3.4, and was not needed there. Reported-by: Eric Bénard Cc: Javier Martin Cc: Fabio Estevam Cc: Sascha Hauer Cc: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/imx-dma.c | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 2ca8d3f779fe..bb787d8e1529 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -172,8 +172,7 @@ struct imxdma_engine { struct device_dma_parameters dma_parms; struct dma_device dma_device; void __iomem *base; - struct clk *dma_ahb; - struct clk *dma_ipg; + struct clk *dma_clk; spinlock_t lock; struct imx_dma_2d_config slots_2d[IMX_DMA_2D_SLOTS]; struct imxdma_channel channel[IMX_DMA_CHANNELS]; @@ -977,20 +976,10 @@ static int __init imxdma_probe(struct platform_device *pdev) return 0; } - imxdma->dma_ipg = devm_clk_get(&pdev->dev, "ipg"); - if (IS_ERR(imxdma->dma_ipg)) { - ret = PTR_ERR(imxdma->dma_ipg); - goto err_clk; - } - - imxdma->dma_ahb = devm_clk_get(&pdev->dev, "ahb"); - if (IS_ERR(imxdma->dma_ahb)) { - ret = PTR_ERR(imxdma->dma_ahb); - goto err_clk; - } - - clk_prepare_enable(imxdma->dma_ipg); - clk_prepare_enable(imxdma->dma_ahb); + imxdma->dma_clk = clk_get(NULL, "dma"); + if (IS_ERR(imxdma->dma_clk)) + return PTR_ERR(imxdma->dma_clk); + clk_enable(imxdma->dma_clk); /* reset DMA module */ imx_dmav1_writel(imxdma, DCR_DRST, DMA_DCR); @@ -999,14 +988,16 @@ static int __init imxdma_probe(struct platform_device *pdev) ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", imxdma); if (ret) { dev_warn(imxdma->dev, "Can't register IRQ for DMA\n"); - goto err_enable; + kfree(imxdma); + return ret; } ret = request_irq(MX1_DMA_ERR, imxdma_err_handler, 0, "DMA", imxdma); if (ret) { dev_warn(imxdma->dev, "Can't register ERRIRQ for DMA\n"); free_irq(MX1_DMA_INT, NULL); - goto err_enable; + kfree(imxdma); + return ret; } } @@ -1103,10 +1094,7 @@ static int __init imxdma_probe(struct platform_device *pdev) free_irq(MX1_DMA_INT, NULL); free_irq(MX1_DMA_ERR, NULL); } -err_enable: - clk_disable_unprepare(imxdma->dma_ipg); - clk_disable_unprepare(imxdma->dma_ahb); -err_clk: + kfree(imxdma); return ret; } @@ -1126,9 +1114,7 @@ static int __exit imxdma_remove(struct platform_device *pdev) free_irq(MX1_DMA_ERR, NULL); } - clk_disable_unprepare(imxdma->dma_ipg); - clk_disable_unprepare(imxdma->dma_ahb); - kfree(imxdma); + kfree(imxdma); return 0; } -- GitLab From 47bca6a5021332b17aa5efc2d66af1018af70ba1 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Fri, 17 Aug 2012 16:43:28 -0400 Subject: [PATCH 0280/1799] xen/setup: Fix one-off error when adding for-balloon PFNs to the P2M. commit c96aae1f7f393387d160211f60398d58463a7e65 upstream. When we are finished with return PFNs to the hypervisor, then populate it back, and also mark the E820 MMIO and E820 gaps as IDENTITY_FRAMEs, we then call P2M to set areas that can be used for ballooning. We were off by one, and ended up over-writting a P2M entry that most likely was an IDENTITY_FRAME. For example: 1-1 mapping on 40000->40200 1-1 mapping on bc558->bc5ac 1-1 mapping on bc5b4->bc8c5 1-1 mapping on bc8c6->bcb7c 1-1 mapping on bcd00->100000 Released 614 pages of unused memory Set 277889 page(s) to 1-1 mapping Populating 40200-40466 pfn range: 614 pages added => here we set from 40466 up to bc559 P2M tree to be INVALID_P2M_ENTRY. We should have done it up to bc558. The end result is that if anybody is trying to construct a PTE for PFN bc558 they end up with ~PAGE_PRESENT. Reported-by-and-Tested-by: Andre Przywara Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/setup.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 1ba8dff26753..99de967762a8 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -79,9 +79,16 @@ static void __init xen_add_extra_mem(u64 start, u64 size) memblock_reserve(start, size); xen_max_p2m_pfn = PFN_DOWN(start + size); + for (pfn = PFN_DOWN(start); pfn < xen_max_p2m_pfn; pfn++) { + unsigned long mfn = pfn_to_mfn(pfn); + + if (WARN(mfn == pfn, "Trying to over-write 1-1 mapping (pfn: %lx)\n", pfn)) + continue; + WARN(mfn != INVALID_P2M_ENTRY, "Trying to remove %lx which has %lx mfn!\n", + pfn, mfn); - for (pfn = PFN_DOWN(start); pfn <= xen_max_p2m_pfn; pfn++) __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); + } } static unsigned long __init xen_release_chunk(unsigned long start, -- GitLab From 830cb0da378e5ec143613069faf250b742456021 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 18 Aug 2012 14:27:32 +0800 Subject: [PATCH 0281/1799] ARM: imx6: spin the cpu until hardware takes it down commit c944b0b9354ea06ffb0c8a7178949f1185f9f499 upstream. Though commit 602bf40 (ARM: imx6: exit coherency when shutting down a cpu) improves the stability of imx6q cpu hotplug a lot, there are still hangs seen with a more stressful hotplug testing. It's expected that once imx_enable_cpu(cpu, false) is called, the cpu will be taken down by hardware immediately, and the code after that will not get any chance to execute. However, this is not always the case from the testing. The cpu could possibly be alive for a few cycles before hardware actually takes it down. So rather than letting cpu execute some code that could cause a hang in these cycles, let's make the cpu spin there and wait for hardware to take it down. Signed-off-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-imx/hotplug.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c index 20ed2d56c1af..f8f7437c83b8 100644 --- a/arch/arm/mach-imx/hotplug.c +++ b/arch/arm/mach-imx/hotplug.c @@ -42,22 +42,6 @@ static inline void cpu_enter_lowpower(void) : "cc"); } -static inline void cpu_leave_lowpower(void) -{ - unsigned int v; - - asm volatile( - "mrc p15, 0, %0, c1, c0, 0\n" - " orr %0, %0, %1\n" - " mcr p15, 0, %0, c1, c0, 0\n" - " mrc p15, 0, %0, c1, c0, 1\n" - " orr %0, %0, %2\n" - " mcr p15, 0, %0, c1, c0, 1\n" - : "=&r" (v) - : "Ir" (CR_C), "Ir" (0x40) - : "cc"); -} - /* * platform-specific code to shutdown a CPU * @@ -67,11 +51,10 @@ void platform_cpu_die(unsigned int cpu) { cpu_enter_lowpower(); imx_enable_cpu(cpu, false); - cpu_do_idle(); - cpu_leave_lowpower(); - /* We should never return from idle */ - panic("cpu %d unexpectedly exit from shutdown\n", cpu); + /* spin here until hardware takes it down */ + while (1) + ; } int platform_cpu_disable(unsigned int cpu) -- GitLab From e78e9b4a7848cc1b52678161cbfaa7530efba251 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 16 Aug 2012 10:40:40 +0000 Subject: [PATCH 0282/1799] ARM: imx: select CPU_FREQ_TABLE when needed commit f637c4c9405e21f44cf0045eaf77eddd3a79ca5a upstream. The i.MX cpufreq implementation uses the CPU_FREQ_TABLE helpers, so it needs to select that code to be built. This problem has apparently existed since the i.MX cpufreq code was first merged in v2.6.37. Building IMX without CPU_FREQ_TABLE results in: arch/arm/plat-mxc/built-in.o: In function `mxc_cpufreq_exit': arch/arm/plat-mxc/cpufreq.c:173: undefined reference to `cpufreq_frequency_table_put_attr' arch/arm/plat-mxc/built-in.o: In function `mxc_set_target': arch/arm/plat-mxc/cpufreq.c:84: undefined reference to `cpufreq_frequency_table_target' arch/arm/plat-mxc/built-in.o: In function `mxc_verify_speed': arch/arm/plat-mxc/cpufreq.c:65: undefined reference to `cpufreq_frequency_table_verify' arch/arm/plat-mxc/built-in.o: In function `mxc_cpufreq_init': arch/arm/plat-mxc/cpufreq.c:154: undefined reference to `cpufreq_frequency_table_cpuinfo' arch/arm/plat-mxc/cpufreq.c:162: undefined reference to `cpufreq_frequency_table_get_attr' Signed-off-by: Arnd Bergmann Acked-by: Shawn Guo Cc: Sascha Hauer Cc: Yong Shen Signed-off-by: Greg Kroah-Hartman --- arch/arm/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 7a8660a2f262..352322a67651 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -2113,6 +2113,7 @@ source "drivers/cpufreq/Kconfig" config CPU_FREQ_IMX tristate "CPUfreq driver for i.MX CPUs" depends on ARCH_MXC && CPU_FREQ + select CPU_FREQ_TABLE help This enables the CPUfreq driver for i.MX CPUs. -- GitLab From 73f34fe608cbbba09fa8c74959b7ac5e05973036 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 16 Aug 2012 22:36:04 +0100 Subject: [PATCH 0283/1799] ASoC: wm9712: Fix microphone source selection commit ccf795847a38235ee4a56a24129ce75147d6ba8f upstream. Currently the microphone input source is not selectable as while there is a DAPM widget it's not connected to anything so it won't be properly instantiated. Add something more correct for the input structure to get things going, even though it's not hooked into the rest of the routing map and so won't actually achieve anything except allowing the relevant register bits to be written. Reported-by: Christop Fritz Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm9712.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index b342ae50bcd6..b9567bc16aea 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -272,7 +272,7 @@ SOC_DAPM_ENUM("Route", wm9712_enum[9]); /* Mic select */ static const struct snd_kcontrol_new wm9712_mic_src_controls = -SOC_DAPM_ENUM("Route", wm9712_enum[7]); +SOC_DAPM_ENUM("Mic Source Select", wm9712_enum[7]); /* diff select */ static const struct snd_kcontrol_new wm9712_diff_sel_controls = @@ -291,7 +291,9 @@ SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0, &wm9712_capture_selectl_controls), SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0, &wm9712_capture_selectr_controls), -SND_SOC_DAPM_MUX("Mic Select Source", SND_SOC_NOPM, 0, 0, +SND_SOC_DAPM_MUX("Left Mic Select Source", SND_SOC_NOPM, 0, 0, + &wm9712_mic_src_controls), +SND_SOC_DAPM_MUX("Right Mic Select Source", SND_SOC_NOPM, 0, 0, &wm9712_mic_src_controls), SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0, &wm9712_diff_sel_controls), @@ -319,6 +321,7 @@ SND_SOC_DAPM_PGA("Out 3 PGA", AC97_INT_PAGING, 5, 1, NULL, 0), SND_SOC_DAPM_PGA("Line PGA", AC97_INT_PAGING, 2, 1, NULL, 0), SND_SOC_DAPM_PGA("Phone PGA", AC97_INT_PAGING, 1, 1, NULL, 0), SND_SOC_DAPM_PGA("Mic PGA", AC97_INT_PAGING, 0, 1, NULL, 0), +SND_SOC_DAPM_PGA("Differential Mic", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_INT_PAGING, 10, 1), SND_SOC_DAPM_OUTPUT("MONOOUT"), SND_SOC_DAPM_OUTPUT("HPOUTL"), @@ -379,6 +382,18 @@ static const struct snd_soc_dapm_route wm9712_audio_map[] = { {"Mic PGA", NULL, "MIC1"}, {"Mic PGA", NULL, "MIC2"}, + /* microphones */ + {"Differential Mic", NULL, "MIC1"}, + {"Differential Mic", NULL, "MIC2"}, + {"Left Mic Select Source", "Mic 1", "MIC1"}, + {"Left Mic Select Source", "Mic 2", "MIC2"}, + {"Left Mic Select Source", "Stereo", "MIC1"}, + {"Left Mic Select Source", "Differential", "Differential Mic"}, + {"Right Mic Select Source", "Mic 1", "MIC1"}, + {"Right Mic Select Source", "Mic 2", "MIC2"}, + {"Right Mic Select Source", "Stereo", "MIC2"}, + {"Right Mic Select Source", "Differential", "Differential Mic"}, + /* left capture selector */ {"Left Capture Select", "Mic", "MIC1"}, {"Left Capture Select", "Speaker Mixer", "Speaker Mixer"}, -- GitLab From 7b6d36dda04aaa8a87576ba5752e988448f88043 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 7 Aug 2012 15:37:47 +0300 Subject: [PATCH 0284/1799] ASoC: omap-mcbsp: Fix 6pin mux configuration commit d0db84e713eaaccea2a435e1625fb3150b335f4a upstream. The check for the mux_signal callback was wrong which prevents us to configure the 6pin port's FSR/CLKR signal mux. Reported-by: CF Adad Signed-off-by: Peter Ujfalusi Acked-by: Jarkko Nikula Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/omap/mcbsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index e5f44440d1b9..fb67772130b5 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -691,7 +691,7 @@ int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux) { const char *signal, *src; - if (mcbsp->pdata->mux_signal) + if (!mcbsp->pdata->mux_signal) return -EINVAL; switch (mux) { -- GitLab From 1e6cec2253d5159a5f4e758114fd3c26a98b00a4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Aug 2012 15:28:00 +0100 Subject: [PATCH 0285/1799] vfs: missed source of ->f_pos races commit 0e665d5d1125f9f4ccff56a75e814f10f88861a2 upstream. compat_sys_{read,write}v() need the same "pass a copy of file->f_pos" thing as sys_{read,write}{,v}(). Signed-off-by: Al Viro Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/compat.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/compat.c b/fs/compat.c index f2944ace7a7b..2b371b38911d 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1160,11 +1160,14 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, struct file *file; int fput_needed; ssize_t ret; + loff_t pos; file = fget_light(fd, &fput_needed); if (!file) return -EBADF; - ret = compat_readv(file, vec, vlen, &file->f_pos); + pos = file->f_pos; + ret = compat_readv(file, vec, vlen, &pos); + file->f_pos = pos; fput_light(file, fput_needed); return ret; } @@ -1226,11 +1229,14 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, struct file *file; int fput_needed; ssize_t ret; + loff_t pos; file = fget_light(fd, &fput_needed); if (!file) return -EBADF; - ret = compat_writev(file, vec, vlen, &file->f_pos); + pos = file->f_pos; + ret = compat_writev(file, vec, vlen, &pos); + file->f_pos = pos; fput_light(file, fput_needed); return ret; } -- GitLab From b030a2c4a494ff09a9ca84a3280f6a327dd7a02f Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 15 Aug 2012 13:01:24 +0200 Subject: [PATCH 0286/1799] vfs: canonicalize create mode in build_open_flags() commit e68726ff72cf7ba5e7d789857fcd9a75ca573f03 upstream. Userspace can pass weird create mode in open(2) that we canonicalize to "(mode & S_IALLUGO) | S_IFREG" in vfs_create(). The problem is that we use the uncanonicalized mode before calling vfs_create() with unforseen consequences. So do the canonicalization early in build_open_flags(). Signed-off-by: Miklos Szeredi Tested-by: Richard W.M. Jones Signed-off-by: Greg Kroah-Hartman --- fs/open.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/open.c b/fs/open.c index 3f1108b19143..cf1d34fc5e69 100644 --- a/fs/open.c +++ b/fs/open.c @@ -882,9 +882,10 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o int lookup_flags = 0; int acc_mode; - if (!(flags & O_CREAT)) - mode = 0; - op->mode = mode; + if (flags & O_CREAT) + op->mode = (mode & S_IALLUGO) | S_IFREG; + else + op->mode = 0; /* Must never be set by userspace */ flags &= ~FMODE_NONOTIFY; -- GitLab From f998ff53548d95327b6b1543d7b524db26a54d89 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 19 Aug 2012 14:41:02 +1200 Subject: [PATCH 0287/1799] alpha: fix fpu.h usage in userspace commit 0be421862b857e61964435ffcaa7499cf77a5e5a upstream. After commit ec2212088c42 ("Disintegrate asm/system.h for Alpha"), the fpu.h header which we install for userland started depending on special_insns.h which is not installed. However, fpu.h only uses that for __KERNEL__ code, so protect the inclusion the same way to avoid build breakage in glibc: /usr/include/asm/fpu.h:4:31: fatal error: asm/special_insns.h: No such file or directory Reported-by: Matt Turner Signed-off-by: Mike Frysinger Signed-off-by: Michael Cree Acked-by: Matt Turner Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/alpha/include/asm/fpu.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/alpha/include/asm/fpu.h b/arch/alpha/include/asm/fpu.h index db00f7885faa..e477bcd5b94a 100644 --- a/arch/alpha/include/asm/fpu.h +++ b/arch/alpha/include/asm/fpu.h @@ -1,7 +1,9 @@ #ifndef __ASM_ALPHA_FPU_H #define __ASM_ALPHA_FPU_H +#ifdef __KERNEL__ #include +#endif /* * Alpha floating-point control register defines: -- GitLab From 660345c4411ec182f2b735c3e19106ea468a9184 Mon Sep 17 00:00:00 2001 From: Michael Cree Date: Sun, 19 Aug 2012 14:40:56 +1200 Subject: [PATCH 0288/1799] alpha: Don't export SOCK_NONBLOCK to user space. commit a2fa3ccd7b43665fe14cb562761a6c3d26a1d13f upstream. Currently we export SOCK_NONBLOCK to user space but that conflicts with the definition from glibc leading to compilation errors in user programs (e.g. see Debian bug #658460). The generic socket.h restricts the definition of SOCK_NONBLOCK to the kernel, as does the MIPS specific socket.h, so let's do the same on Alpha. Signed-off-by: Michael Cree Acked-by: Matt Turner Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/alpha/include/asm/socket.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h index dcb221a4b5be..7d2f75be932e 100644 --- a/arch/alpha/include/asm/socket.h +++ b/arch/alpha/include/asm/socket.h @@ -76,9 +76,11 @@ /* Instruct lower device to use last 4-bytes of skb data as FCS */ #define SO_NOFCS 43 +#ifdef __KERNEL__ /* O_NONBLOCK clashes with the bits used for socket types. Therefore we * have to define SOCK_NONBLOCK to a different value here. */ #define SOCK_NONBLOCK 0x40000000 +#endif /* __KERNEL__ */ #endif /* _ASM_SOCKET_H */ -- GitLab From 5be8fc241c52f469cd8f2c9e4ebd66ce4ab9df34 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:37 -0700 Subject: [PATCH 0289/1799] USB: winbond: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 43a34695d9cd79c6659f09da6d3b0624f3dd169f upstream. This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork CC: Pavel Machek CC: Paul Gortmaker CC: "John W. Linville" CC: Eliad Peller CC: Devendra Naga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/winbond/wbusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index c3751a718384..9160049ff546 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c @@ -25,7 +25,7 @@ MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("0.1"); -static const struct usb_device_id wb35_table[] __devinitconst = { +static const struct usb_device_id wb35_table[] = { { USB_DEVICE(0x0416, 0x0035) }, { USB_DEVICE(0x18E8, 0x6201) }, { USB_DEVICE(0x18E8, 0x6206) }, -- GitLab From c3a0afddee7ed8979b8d14346376848e0a306850 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Tue, 21 Aug 2012 16:15:52 -0700 Subject: [PATCH 0290/1799] mm: hugetlbfs: correctly populate shared pmd commit eb48c071464757414538c68a6033c8f8c15196f8 upstream. Each page mapped in a process's address space must be correctly accounted for in _mapcount. Normally the rules for this are straightforward but hugetlbfs page table sharing is different. The page table pages at the PMD level are reference counted while the mapcount remains the same. If this accounting is wrong, it causes bugs like this one reported by Larry Woodman: kernel BUG at mm/filemap.c:135! invalid opcode: 0000 [#1] SMP CPU 22 Modules linked in: bridge stp llc sunrpc binfmt_misc dcdbas microcode pcspkr acpi_pad acpi] Pid: 18001, comm: mpitest Tainted: G W 3.3.0+ #4 Dell Inc. PowerEdge R620/07NDJ2 RIP: 0010:[] [] __delete_from_page_cache+0x15d/0x170 Process mpitest (pid: 18001, threadinfo ffff880428972000, task ffff880428b5cc20) Call Trace: delete_from_page_cache+0x40/0x80 truncate_hugepages+0x115/0x1f0 hugetlbfs_evict_inode+0x18/0x30 evict+0x9f/0x1b0 iput_final+0xe3/0x1e0 iput+0x3e/0x50 d_kill+0xf8/0x110 dput+0xe2/0x1b0 __fput+0x162/0x240 During fork(), copy_hugetlb_page_range() detects if huge_pte_alloc() shared page tables with the check dst_pte == src_pte. The logic is if the PMD page is the same, they must be shared. This assumes that the sharing is between the parent and child. However, if the sharing is with a different process entirely then this check fails as in this diagram: parent | ------------>pmd src_pte----------> data page ^ other--------->pmd--------------------| ^ child-----------| dst_pte For this situation to occur, it must be possible for Parent and Other to have faulted and failed to share page tables with each other. This is possible due to the following style of race. PROC A PROC B copy_hugetlb_page_range copy_hugetlb_page_range src_pte == huge_pte_offset src_pte == huge_pte_offset !src_pte so no sharing !src_pte so no sharing (time passes) hugetlb_fault hugetlb_fault huge_pte_alloc huge_pte_alloc huge_pmd_share huge_pmd_share LOCK(i_mmap_mutex) find nothing, no sharing UNLOCK(i_mmap_mutex) LOCK(i_mmap_mutex) find nothing, no sharing UNLOCK(i_mmap_mutex) pmd_alloc pmd_alloc LOCK(instantiation_mutex) fault UNLOCK(instantiation_mutex) LOCK(instantiation_mutex) fault UNLOCK(instantiation_mutex) These two processes are not poing to the same data page but are not sharing page tables because the opportunity was missed. When either process later forks, the src_pte == dst pte is potentially insufficient. As the check falls through, the wrong PTE information is copied in (harmless but wrong) and the mapcount is bumped for a page mapped by a shared page table leading to the BUG_ON. This patch addresses the issue by moving pmd_alloc into huge_pmd_share which guarantees that the shared pud is populated in the same critical section as pmd. This also means that huge_pte_offset test in huge_pmd_share is serialized correctly now which in turn means that the success of the sharing will be higher as the racing tasks see the pud and pmd populated together. Race identified and changelog written mostly by Mel Gorman. {akpm@linux-foundation.org: attempt to make the huge_pmd_share() comment comprehensible, clean up coding style] Reported-by: Larry Woodman Tested-by: Larry Woodman Reviewed-by: Mel Gorman Signed-off-by: Michal Hocko Reviewed-by: Rik van Riel Cc: David Gibson Cc: Ken Chen Cc: Cong Wang Cc: Hillf Danton Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/hugetlbpage.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index f6679a7fb8ca..b91e48512425 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c @@ -56,9 +56,16 @@ static int vma_shareable(struct vm_area_struct *vma, unsigned long addr) } /* - * search for a shareable pmd page for hugetlb. + * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc() + * and returns the corresponding pte. While this is not necessary for the + * !shared pmd case because we can allocate the pmd later as well, it makes the + * code much cleaner. pmd allocation is essential for the shared case because + * pud has to be populated inside the same i_mmap_mutex section - otherwise + * racing tasks could either miss the sharing (see huge_pte_offset) or select a + * bad pmd for sharing. */ -static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) +static pte_t * +huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) { struct vm_area_struct *vma = find_vma(mm, addr); struct address_space *mapping = vma->vm_file->f_mapping; @@ -68,9 +75,10 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) struct vm_area_struct *svma; unsigned long saddr; pte_t *spte = NULL; + pte_t *pte; if (!vma_shareable(vma, addr)) - return; + return (pte_t *)pmd_alloc(mm, pud, addr); mutex_lock(&mapping->i_mmap_mutex); vma_prio_tree_foreach(svma, &iter, &mapping->i_mmap, idx, idx) { @@ -97,7 +105,9 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) put_page(virt_to_page(spte)); spin_unlock(&mm->page_table_lock); out: + pte = (pte_t *)pmd_alloc(mm, pud, addr); mutex_unlock(&mapping->i_mmap_mutex); + return pte; } /* @@ -142,8 +152,9 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, } else { BUG_ON(sz != PMD_SIZE); if (pud_none(*pud)) - huge_pmd_share(mm, addr, pud); - pte = (pte_t *) pmd_alloc(mm, pud, addr); + pte = huge_pmd_share(mm, addr, pud); + else + pte = (pte_t *)pmd_alloc(mm, pud, addr); } } BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte)); -- GitLab From 69b9b6d1966c9d2a3c610401eee3491b28e8a935 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 20 Aug 2012 11:17:00 +0200 Subject: [PATCH 0291/1799] ALSA: hda - don't create dysfunctional mixer controls for ca0132 commit c41999a23929f30808bae6009d8065052d4d73fd upstream. It's possible that these amps are settable somehow, e g through secret codec verbs, but for now, don't create the controls (as they won't be working anyway, and cause errors in amixer). BugLink: https://bugs.launchpad.net/bugs/1038651 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_ca0132.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 21d91d580da8..70b4f02da2c0 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -276,6 +276,10 @@ static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx, int type = dir ? HDA_INPUT : HDA_OUTPUT; struct snd_kcontrol_new knew = HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type); + if ((query_amp_caps(codec, nid, type) & AC_AMPCAP_MUTE) == 0) { + snd_printdd("Skipping '%s %s Switch' (no mute on node 0x%x)\n", pfx, dirstr[dir], nid); + return 0; + } sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); } @@ -287,6 +291,10 @@ static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx, int type = dir ? HDA_INPUT : HDA_OUTPUT; struct snd_kcontrol_new knew = HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type); + if ((query_amp_caps(codec, nid, type) & AC_AMPCAP_NUM_STEPS) == 0) { + snd_printdd("Skipping '%s %s Volume' (no amp on node 0x%x)\n", pfx, dirstr[dir], nid); + return 0; + } sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]); return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); } -- GitLab From 94a6f1787e1f896585a093aa2f45cefbbef80f24 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Tue, 14 Aug 2012 16:06:43 -0700 Subject: [PATCH 0292/1799] target: fix NULL pointer dereference bug alloc_page() fails to get memory commit d0e27c88d795fb9647153063ec48051fd84e1731 upstream. I am hitting this bug when the target is low in memory that fails the alloc_page() for the newly submitted command. This is a sort of off-by-one bug causing NULL pointer dereference in __free_page() since 'i' here is really the counter of total pages that have been successfully allocated here. Signed-off-by: Yi Zou Cc: Andy Grover Cc: Nicholas Bellinger Cc: Open-FCoE.org Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_transport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 0686d61adeae..222f1c5ff946 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3675,9 +3675,9 @@ transport_generic_get_mem(struct se_cmd *cmd) return 0; out: - while (i >= 0) { - __free_page(sg_page(&cmd->t_data_sg[i])); + while (i > 0) { i--; + __free_page(sg_page(&cmd->t_data_sg[i])); } kfree(cmd->t_data_sg); cmd->t_data_sg = NULL; -- GitLab From 73b8b9f59d61e0c0e2beaada246f1ed41df0c8fd Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Aug 2012 12:42:15 -0400 Subject: [PATCH 0293/1799] NFSv3: Ensure that do_proc_get_root() reports errors correctly commit 086600430493e04b802bee6e5b3ce0458e4eb77f upstream. If the rpc call to NFS3PROC_FSINFO fails, then we need to report that error so that the mount fails. Otherwise we can end up with a superblock with completely unusable values for block sizes, maxfilesize, etc. Reported-by: Yuanming Chen Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs3proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 5242eae6711a..a1e416b7baea 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -69,7 +69,7 @@ do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle, nfs_fattr_init(info->fattr); status = rpc_call_sync(client, &msg, 0); dprintk("%s: reply fsinfo: %d\n", __func__, status); - if (!(info->fattr->valid & NFS_ATTR_FATTR)) { + if (status == 0 && !(info->fattr->valid & NFS_ATTR_FATTR)) { msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; msg.rpc_resp = info->fattr; status = rpc_call_sync(client, &msg, 0); -- GitLab From c2bf322ed7e21107609d44bc914afba3aed35b85 Mon Sep 17 00:00:00 2001 From: Idan Kedar Date: Thu, 2 Aug 2012 11:47:10 +0300 Subject: [PATCH 0294/1799] pnfs: defer release of pages in layoutget commit 8554116e17eef055d9dd58a94b3427cb2ad1c317 upstream. we have encountered a bug whereby reading a lot of files (copying fedora's /bin) from a pNFS mount and hitting Ctrl+C in the middle caused a general protection fault in xdr_shrink_bufhead. this function is called when decoding the response from LAYOUTGET. the decoding is done by a worker thread, and the caller of LAYOUTGET waits for the worker thread to complete. hitting Ctrl+C caused the synchronous wait to end and the next thing the caller does is to free the pages, so when the worker thread calls xdr_shrink_bufhead, the pages are gone. therefore, the cleanup of these pages has been moved to nfs4_layoutget_release. Signed-off-by: Idan Kedar Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++- fs/nfs/pnfs.c | 39 +------------------------------- fs/nfs/pnfs.h | 2 +- 3 files changed, 58 insertions(+), 40 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d60c2d870ab0..4063dc5c176b 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -5966,11 +5966,58 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) dprintk("<-- %s\n", __func__); } +static size_t max_response_pages(struct nfs_server *server) +{ + u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; + return nfs_page_array_len(0, max_resp_sz); +} + +static void nfs4_free_pages(struct page **pages, size_t size) +{ + int i; + + if (!pages) + return; + + for (i = 0; i < size; i++) { + if (!pages[i]) + break; + __free_page(pages[i]); + } + kfree(pages); +} + +static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags) +{ + struct page **pages; + int i; + + pages = kcalloc(size, sizeof(struct page *), gfp_flags); + if (!pages) { + dprintk("%s: can't alloc array of %zu pages\n", __func__, size); + return NULL; + } + + for (i = 0; i < size; i++) { + pages[i] = alloc_page(gfp_flags); + if (!pages[i]) { + dprintk("%s: failed to allocate page\n", __func__); + nfs4_free_pages(pages, size); + return NULL; + } + } + + return pages; +} + static void nfs4_layoutget_release(void *calldata) { struct nfs4_layoutget *lgp = calldata; + struct nfs_server *server = NFS_SERVER(lgp->args.inode); + size_t max_pages = max_response_pages(server); dprintk("--> %s\n", __func__); + nfs4_free_pages(lgp->args.layout.pages, max_pages); put_nfs_open_context(lgp->args.ctx); kfree(calldata); dprintk("<-- %s\n", __func__); @@ -5982,9 +6029,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = { .rpc_release = nfs4_layoutget_release, }; -int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) +int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) { struct nfs_server *server = NFS_SERVER(lgp->args.inode); + size_t max_pages = max_response_pages(server); struct rpc_task *task; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], @@ -6002,6 +6050,13 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) dprintk("--> %s\n", __func__); + lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); + if (!lgp->args.layout.pages) { + nfs4_layoutget_release(lgp); + return -ENOMEM; + } + lgp->args.layout.pglen = max_pages * PAGE_SIZE; + lgp->res.layoutp = &lgp->args.layout; lgp->res.seq_res.sr_slot = NULL; nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 38512bcd2e98..059e2c350ad7 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -574,9 +574,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, struct nfs_server *server = NFS_SERVER(ino); struct nfs4_layoutget *lgp; struct pnfs_layout_segment *lseg = NULL; - struct page **pages = NULL; - int i; - u32 max_resp_sz, max_pages; dprintk("--> %s\n", __func__); @@ -585,20 +582,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, if (lgp == NULL) return NULL; - /* allocate pages for xdr post processing */ - max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; - max_pages = nfs_page_array_len(0, max_resp_sz); - - pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags); - if (!pages) - goto out_err_free; - - for (i = 0; i < max_pages; i++) { - pages[i] = alloc_page(gfp_flags); - if (!pages[i]) - goto out_err_free; - } - lgp->args.minlength = PAGE_CACHE_SIZE; if (lgp->args.minlength > range->length) lgp->args.minlength = range->length; @@ -607,39 +590,19 @@ send_layoutget(struct pnfs_layout_hdr *lo, lgp->args.type = server->pnfs_curr_ld->id; lgp->args.inode = ino; lgp->args.ctx = get_nfs_open_context(ctx); - lgp->args.layout.pages = pages; - lgp->args.layout.pglen = max_pages * PAGE_SIZE; lgp->lsegpp = &lseg; lgp->gfp_flags = gfp_flags; /* Synchronously retrieve layout information from server and * store in lseg. */ - nfs4_proc_layoutget(lgp); + nfs4_proc_layoutget(lgp, gfp_flags); if (!lseg) { /* remember that LAYOUTGET failed and suspend trying */ set_bit(lo_fail_bit(range->iomode), &lo->plh_flags); } - /* free xdr pages */ - for (i = 0; i < max_pages; i++) - __free_page(pages[i]); - kfree(pages); - return lseg; - -out_err_free: - /* free any allocated xdr pages, lgp as it's not used */ - if (pages) { - for (i = 0; i < max_pages; i++) { - if (!pages[i]) - break; - __free_page(pages[i]); - } - kfree(pages); - } - kfree(lgp); - return NULL; } /* Initiates a LAYOUTRETURN(FILE) */ diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 442ebf68eeec..8d95818330cc 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -161,7 +161,7 @@ extern int nfs4_proc_getdevicelist(struct nfs_server *server, struct pnfs_devicelist *devlist); extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *dev); -extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp); +extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); /* pnfs.c */ -- GitLab From f401b102e87f77b81c041a06f37e3f764ed1a8e7 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 8 Aug 2012 16:03:13 -0400 Subject: [PATCH 0295/1799] NFSv4.1: Remove a bogus BUG_ON() in nfs4_layoutreturn_done commit 47fbf7976e0b7d9dcdd799e2a1baba19064d9631 upstream. Ever since commit 0a57cdac3f (NFSv4.1 send layoutreturn to fence disconnected data server) we've been sending layoutreturn calls while there is potentially still outstanding I/O to the data servers. The reason we do this is to avoid races between replayed writes to the MDS and the original writes to the DS. When this happens, the BUG_ON() in nfs4_layoutreturn_done can be triggered because it assumes that we would never call layoutreturn without knowing that all I/O to the DS is finished. The fix is to remove the BUG_ON() now that the assumptions behind the test are obsolete. Reported-by: Boaz Harrosh Reported-by: Tigran Mkrtchyan Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4063dc5c176b..dc573245eea3 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -6102,12 +6102,8 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) return; } spin_lock(&lo->plh_inode->i_lock); - if (task->tk_status == 0) { - if (lrp->res.lrs_present) { - pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); - } else - BUG_ON(!list_empty(&lo->plh_segs)); - } + if (task->tk_status == 0 && lrp->res.lrs_present) + pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); lo->plh_block_lgets--; spin_unlock(&lo->plh_inode->i_lock); dprintk("<-- %s\n", __func__); -- GitLab From 797d03b980a559cd3312f7df3b41bb265cddcd8b Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 9 Aug 2012 14:05:49 -0400 Subject: [PATCH 0296/1799] NFS: Clear key construction data if the idmap upcall fails commit c5066945b7ea346a11424dbeb7830b7d7d00c206 upstream. idmap_pipe_downcall already clears this field if the upcall succeeds, but if it fails (rpc.idmapd isn't running) the field will still be set on the next call triggering a BUG_ON(). This patch tries to handle all possible ways that the upcall could fail and clear the idmap key data for each one. Signed-off-by: Bryan Schumaker Tested-by: William Dauchy Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/idmap.c | 56 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 929ba0111724..98d664349f7e 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -63,6 +63,12 @@ struct idmap { struct mutex idmap_mutex; }; +struct idmap_legacy_upcalldata { + struct rpc_pipe_msg pipe_msg; + struct idmap_msg idmap_msg; + struct idmap *idmap; +}; + /** * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields * @fattr: fully initialised struct nfs_fattr @@ -326,6 +332,7 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, name, namelen, type, data, data_size, idmap); + idmap->idmap_key_cons = NULL; mutex_unlock(&idmap->idmap_mutex); } return ret; @@ -383,11 +390,13 @@ static const match_table_t nfs_idmap_tokens = { static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *); static ssize_t idmap_pipe_downcall(struct file *, const char __user *, size_t); +static void idmap_release_pipe(struct inode *); static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); static const struct rpc_pipe_ops idmap_upcall_ops = { .upcall = rpc_pipe_generic_upcall, .downcall = idmap_pipe_downcall, + .release_pipe = idmap_release_pipe, .destroy_msg = idmap_pipe_destroy_msg, }; @@ -603,7 +612,8 @@ void nfs_idmap_quit(void) nfs_idmap_quit_keyring(); } -static int nfs_idmap_prepare_message(char *desc, struct idmap_msg *im, +static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap, + struct idmap_msg *im, struct rpc_pipe_msg *msg) { substring_t substr; @@ -646,6 +656,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, const char *op, void *aux) { + struct idmap_legacy_upcalldata *data; struct rpc_pipe_msg *msg; struct idmap_msg *im; struct idmap *idmap = (struct idmap *)aux; @@ -653,15 +664,15 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, int ret = -ENOMEM; /* msg and im are freed in idmap_pipe_destroy_msg */ - msg = kmalloc(sizeof(*msg), GFP_KERNEL); - if (!msg) - goto out0; - - im = kmalloc(sizeof(*im), GFP_KERNEL); - if (!im) + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) goto out1; - ret = nfs_idmap_prepare_message(key->description, im, msg); + msg = &data->pipe_msg; + im = &data->idmap_msg; + data->idmap = idmap; + + ret = nfs_idmap_prepare_message(key->description, idmap, im, msg); if (ret < 0) goto out2; @@ -670,15 +681,15 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, ret = rpc_queue_upcall(idmap->idmap_pipe, msg); if (ret < 0) - goto out2; + goto out3; return ret; +out3: + idmap->idmap_key_cons = NULL; out2: - kfree(im); + kfree(data); out1: - kfree(msg); -out0: complete_request_key(cons, ret); return ret; } @@ -762,9 +773,26 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) { + struct idmap_legacy_upcalldata *data = container_of(msg, + struct idmap_legacy_upcalldata, + pipe_msg); + struct idmap *idmap = data->idmap; + struct key_construction *cons; + if (msg->errno) { + cons = ACCESS_ONCE(idmap->idmap_key_cons); + idmap->idmap_key_cons = NULL; + complete_request_key(cons, msg->errno); + } /* Free memory allocated in nfs_idmap_legacy_upcall() */ - kfree(msg->data); - kfree(msg); + kfree(data); +} + +static void +idmap_release_pipe(struct inode *inode) +{ + struct rpc_inode *rpci = RPC_I(inode); + struct idmap *idmap = (struct idmap *)rpci->private; + idmap->idmap_key_cons = NULL; } int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) -- GitLab From d3078898b6f08028ee5ab8f6e8d12216d7f707ee Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 9 Aug 2012 14:05:50 -0400 Subject: [PATCH 0297/1799] NFS: return -ENOKEY when the upcall fails to map the name commit 12dfd080556124088ed61a292184947711b46cbe upstream. This allows the normal error-paths to handle the error, rather than making a special call to complete_request_key() just for this instance. Signed-off-by: Bryan Schumaker Tested-by: William Dauchy Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/idmap.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 98d664349f7e..9131b17f3a72 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -747,9 +747,8 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) } if (!(im.im_status & IDMAP_STATUS_SUCCESS)) { - ret = mlen; - complete_request_key(cons, -ENOKEY); - goto out_incomplete; + ret = -ENOKEY; + goto out; } namelen_in = strnlen(im.im_name, IDMAP_NAMESZ); @@ -766,7 +765,6 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) out: complete_request_key(cons, ret); -out_incomplete: return ret; } -- GitLab From 4c795fe18aa1d2756a82c46ca29d4bfad2704d4d Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 21 Aug 2012 21:50:58 +0300 Subject: [PATCH 0298/1799] UBIFS: fix complaints about too small debug buffer size commit 65b455b123c7e2b835a0b7148f9bae584f95000e upstream. When debugging is enabled, we use a temporary on-stack buffer for formatting the key strings like "(11368871, direntry, 0xcd0750)". The buffer size is 32 bytes and sometimes it is not enough to fit the key string - e.g., when inode numbers are high. This is not fatal, but the key strings are incomplete and UBIFS complains like this: UBIFS assert failed in dbg_snprintf_key at 137 (pid 1) This is a regression caused by "515315a UBIFS: fix key printing". Fix the issue by increasing the buffer to 48 bytes. Reported-by: Michael Hench Signed-off-by: Artem Bityutskiy Tested-by: Michael Hench Signed-off-by: Greg Kroah-Hartman --- fs/ubifs/debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index 9f717655df18..28e3de1892b9 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h @@ -170,7 +170,7 @@ struct ubifs_global_debug_info { #define ubifs_dbg_msg(type, fmt, ...) \ pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__) -#define DBG_KEY_BUF_LEN 32 +#define DBG_KEY_BUF_LEN 48 #define ubifs_dbg_msg_key(type, key, fmt, ...) do { \ char __tmp_key_buf[DBG_KEY_BUF_LEN]; \ pr_debug("UBIFS DBG " type ": " fmt "%s\n", ##__VA_ARGS__, \ -- GitLab From a431bd57a95921188f61096e5ce29d1b769be118 Mon Sep 17 00:00:00 2001 From: Ram Malovany Date: Thu, 19 Jul 2012 10:26:09 +0300 Subject: [PATCH 0299/1799] Bluetooth: Fix using NULL inquiry entry commit c810089c27e48b816181b454fcc493d19fdbc2ba upstream. If entry wasn't found in the hci_inquiry_cache_lookup_resolve do not resolve the name.This will fix a kernel crash when trying to use NULL pointer. Signed-off-by: Ram Malovany Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hci_event.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 1266f78fa8e3..866fc3b22fba 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1357,6 +1357,9 @@ static bool hci_resolve_next_name(struct hci_dev *hdev) return false; e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); + if (!e) + return false; + if (hci_resolve_name(hdev, e) == 0) { e->name_state = NAME_PENDING; return true; -- GitLab From a8b8ad6dcf49c84c7a8633082191c6fd7539c355 Mon Sep 17 00:00:00 2001 From: Ram Malovany Date: Thu, 19 Jul 2012 10:26:10 +0300 Subject: [PATCH 0300/1799] Bluetooth: Fix using a NULL inquiry cache entry commit 7cc8380eb10347016d95bf6f9d842c2ae6d12932 upstream. If the device was not found in a list of found devices names of which are pending.This may happen in a case when HCI Remote Name Request was sent as a part of incoming connection establishment procedure. Hence there is no need to continue resolving a next name as it will be done upon receiving another Remote Name Request Complete Event. This will fix a kernel crash when trying to use this entry to resolve the next name. Signed-off-by: Ram Malovany Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hci_event.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 866fc3b22fba..df2615d59eb0 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1388,12 +1388,18 @@ static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, return; e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); - if (e) { + /* If the device was not found in a list of found devices names of which + * are pending. there is no need to continue resolving a next name as it + * will be done upon receiving another Remote Name Request Complete + * Event */ + if (!e) + return; + + list_del(&e->list); + if (name) { e->name_state = NAME_KNOWN; - list_del(&e->list); - if (name) - mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, - e->data.rssi, name, name_len); + mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, + e->data.rssi, name, name_len); } if (hci_resolve_next_name(hdev)) -- GitLab From 4a20bce04ec14c74f5b77c73d7d8d476ace74cea Mon Sep 17 00:00:00 2001 From: Ram Malovany Date: Thu, 19 Jul 2012 10:26:11 +0300 Subject: [PATCH 0301/1799] Bluetooth: Set name_state to unknown when entry name is empty commit c3e7c0d90b14a3e7ac091d24cef09efb516d587b upstream. When the name of the given entry is empty , the state needs to be updated accordingly. Signed-off-by: Ram Malovany Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hci_event.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index df2615d59eb0..9cdcfd9f907e 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1400,6 +1400,8 @@ static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, e->name_state = NAME_KNOWN; mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, e->data.rssi, name, name_len); + } else { + e->name_state = NAME_NOT_KNOWN; } if (hci_resolve_next_name(hdev)) -- GitLab From 3cf3cfc448c480c86c439ba7c707a7b4f73ba9d9 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 19 Jul 2012 14:46:08 +0200 Subject: [PATCH 0302/1799] Bluetooth: Fix legacy pairing with some devices commit a9ea3ed9b71cc3271dd59e76f65748adcaa76422 upstream. Some devices e.g. some Android based phones don't do SDP search before pairing and cancel legacy pairing when ACL is disconnected. PIN Code Request event which changes ACL timeout to HCI_PAIRING_TIMEOUT is only received after remote user entered PIN. In that case no L2CAP is connected so default HCI_DISCONN_TIMEOUT (2 seconds) is being used to timeout ACL connection. This results in problems with legacy pairing as remote user has only few seconds to enter PIN before ACL is disconnected. Increase disconnect timeout for incomming connection to HCI_PAIRING_TIMEOUT if SSP is disabled and no linkey exists. To avoid keeping ACL alive for too long after SDP search set ACL timeout back to HCI_DISCONN_TIMEOUT when L2CAP is connected. 2012-07-19 13:24:43.413521 < HCI Command: Create Connection (0x01|0x0005) plen 13 bdaddr 00:02:72:D6:6A:3F ptype 0xcc18 rswitch 0x01 clkoffset 0x0000 Packet type: DM1 DM3 DM5 DH1 DH3 DH5 2012-07-19 13:24:43.425224 > HCI Event: Command Status (0x0f) plen 4 Create Connection (0x01|0x0005) status 0x00 ncmd 1 2012-07-19 13:24:43.885222 > HCI Event: Role Change (0x12) plen 8 status 0x00 bdaddr 00:02:72:D6:6A:3F role 0x01 Role: Slave 2012-07-19 13:24:44.054221 > HCI Event: Connect Complete (0x03) plen 11 status 0x00 handle 42 bdaddr 00:02:72:D6:6A:3F type ACL encrypt 0x00 2012-07-19 13:24:44.054313 < HCI Command: Read Remote Supported Features (0x01|0x001b) plen 2 handle 42 2012-07-19 13:24:44.055176 > HCI Event: Page Scan Repetition Mode Change (0x20) plen 7 bdaddr 00:02:72:D6:6A:3F mode 0 2012-07-19 13:24:44.056217 > HCI Event: Max Slots Change (0x1b) plen 3 handle 42 slots 5 2012-07-19 13:24:44.059218 > HCI Event: Command Status (0x0f) plen 4 Read Remote Supported Features (0x01|0x001b) status 0x00 ncmd 0 2012-07-19 13:24:44.062192 > HCI Event: Command Status (0x0f) plen 4 Unknown (0x00|0x0000) status 0x00 ncmd 1 2012-07-19 13:24:44.067219 > HCI Event: Read Remote Supported Features (0x0b) plen 11 status 0x00 handle 42 Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87 2012-07-19 13:24:44.067248 < HCI Command: Read Remote Extended Features (0x01|0x001c) plen 3 handle 42 page 1 2012-07-19 13:24:44.071217 > HCI Event: Command Status (0x0f) plen 4 Read Remote Extended Features (0x01|0x001c) status 0x00 ncmd 1 2012-07-19 13:24:44.076218 > HCI Event: Read Remote Extended Features (0x23) plen 13 status 0x00 handle 42 page 1 max 1 Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 2012-07-19 13:24:44.076249 < HCI Command: Remote Name Request (0x01|0x0019) plen 10 bdaddr 00:02:72:D6:6A:3F mode 2 clkoffset 0x0000 2012-07-19 13:24:44.081218 > HCI Event: Command Status (0x0f) plen 4 Remote Name Request (0x01|0x0019) status 0x00 ncmd 1 2012-07-19 13:24:44.105214 > HCI Event: Remote Name Req Complete (0x07) plen 255 status 0x00 bdaddr 00:02:72:D6:6A:3F name 'uw000951-0' 2012-07-19 13:24:44.105284 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 handle 42 2012-07-19 13:24:44.111207 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) status 0x00 ncmd 1 2012-07-19 13:24:44.112220 > HCI Event: Link Key Request (0x17) plen 6 bdaddr 00:02:72:D6:6A:3F 2012-07-19 13:24:44.112249 < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 bdaddr 00:02:72:D6:6A:3F 2012-07-19 13:24:44.115215 > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 status 0x00 bdaddr 00:02:72:D6:6A:3F 2012-07-19 13:24:44.116215 > HCI Event: PIN Code Request (0x16) plen 6 bdaddr 00:02:72:D6:6A:3F 2012-07-19 13:24:48.099184 > HCI Event: Auth Complete (0x06) plen 3 status 0x13 handle 42 Error: Remote User Terminated Connection 2012-07-19 13:24:48.179182 > HCI Event: Disconn Complete (0x05) plen 4 status 0x00 handle 42 reason 0x13 Reason: Remote User Terminated Connection Signed-off-by: Szymon Janc Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hci_event.c | 7 ++++++- net/bluetooth/l2cap_core.c | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 9cdcfd9f907e..25edda03645e 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1760,7 +1760,12 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s if (conn->type == ACL_LINK) { conn->state = BT_CONFIG; hci_conn_hold(conn); - conn->disc_timeout = HCI_DISCONN_TIMEOUT; + + if (!conn->out && !hci_conn_ssp_enabled(conn) && + !hci_find_link_key(hdev, &ev->bdaddr)) + conn->disc_timeout = HCI_PAIRING_TIMEOUT; + else + conn->disc_timeout = HCI_DISCONN_TIMEOUT; } else conn->state = BT_CONNECTED; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 6f9c25b633a6..9a86759a7e62 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -893,6 +893,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) sk = chan->sk; hci_conn_hold(conn->hcon); + conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; bacpy(&bt_sk(sk)->src, conn->src); bacpy(&bt_sk(sk)->dst, conn->dst); -- GitLab From e5cd679ea475fd731686fa3c632c2d30b9d59a6d Mon Sep 17 00:00:00 2001 From: "bjschuma@gmail.com" Date: Wed, 8 Aug 2012 13:57:10 -0400 Subject: [PATCH 0303/1799] NFS: Alias the nfs module to nfs4 commit 425e776d93a7a5070b77d4f458a5bab0f924652c upstream. This allows distros to remove the line from their modprobe configuration. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- fs/nfs/super.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 4ac7fca7e4bf..7b55f51137e3 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -3146,4 +3146,6 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, return res; } +MODULE_ALIAS("nfs4"); + #endif /* CONFIG_NFS_V4 */ -- GitLab From ae2a5dd19bccd4fa52ee6bb78ad88b960d92c606 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 15 Aug 2012 12:55:22 +0200 Subject: [PATCH 0304/1799] audit: don't free_chunk() after fsnotify_add_mark() commit 0fe33aae0e94b4097dd433c9399e16e17d638cd8 upstream. Don't do free_chunk() after fsnotify_add_mark(). That one does a delayed unref via the destroy list and this results in use-after-free. Signed-off-by: Miklos Szeredi Acked-by: Eric Paris Signed-off-by: Greg Kroah-Hartman --- kernel/audit_tree.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 5bf0790497e7..d52d247b07a5 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -259,7 +259,7 @@ static void untag_chunk(struct node *p) fsnotify_duplicate_mark(&new->mark, entry); if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, NULL, 1)) { - free_chunk(new); + fsnotify_put_mark(&new->mark); goto Fallback; } @@ -322,7 +322,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) entry = &chunk->mark; if (fsnotify_add_mark(entry, audit_tree_group, inode, NULL, 0)) { - free_chunk(chunk); + fsnotify_put_mark(entry); return -ENOSPC; } @@ -396,7 +396,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) fsnotify_duplicate_mark(chunk_entry, old_entry); if (fsnotify_add_mark(chunk_entry, chunk_entry->group, chunk_entry->i.inode, NULL, 1)) { spin_unlock(&old_entry->lock); - free_chunk(chunk); + fsnotify_put_mark(chunk_entry); fsnotify_put_mark(old_entry); return -ENOSPC; } -- GitLab From 47b8bbd6c2aab324fa57f004f89abb40bb8478be Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 15 Aug 2012 12:55:22 +0200 Subject: [PATCH 0305/1799] audit: fix refcounting in audit-tree commit a2140fc0cb0325bb6384e788edd27b9a568714e2 upstream. Refcounting of fsnotify_mark in audit tree is broken. E.g: refcount create_chunk alloc_chunk 1 fsnotify_add_mark 2 untag_chunk fsnotify_get_mark 3 fsnotify_destroy_mark audit_tree_freeing_mark 2 fsnotify_put_mark 1 fsnotify_put_mark 0 via destroy_list fsnotify_mark_destroy -1 This was reported by various people as triggering Oops when stopping auditd. We could just remove the put_mark from audit_tree_freeing_mark() but that would break freeing via inode destruction. So this patch simply omits a put_mark after calling destroy_mark or adds a get_mark before. The additional get_mark is necessary where there's no other put_mark after fsnotify_destroy_mark() since it assumes that the caller is holding a reference (or the inode is keeping the mark pinned, not the case here AFAICS). Signed-off-by: Miklos Szeredi Reported-by: Valentin Avram Reported-by: Peter Moody Acked-by: Eric Paris Signed-off-by: Greg Kroah-Hartman --- kernel/audit_tree.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index d52d247b07a5..31fdc480b5c6 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -250,7 +250,6 @@ static void untag_chunk(struct node *p) spin_unlock(&hash_lock); spin_unlock(&entry->lock); fsnotify_destroy_mark(entry); - fsnotify_put_mark(entry); goto out; } @@ -293,7 +292,6 @@ static void untag_chunk(struct node *p) spin_unlock(&hash_lock); spin_unlock(&entry->lock); fsnotify_destroy_mark(entry); - fsnotify_put_mark(entry); goto out; Fallback: @@ -332,6 +330,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&hash_lock); chunk->dead = 1; spin_unlock(&entry->lock); + fsnotify_get_mark(entry); fsnotify_destroy_mark(entry); fsnotify_put_mark(entry); return 0; @@ -412,6 +411,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&chunk_entry->lock); spin_unlock(&old_entry->lock); + fsnotify_get_mark(chunk_entry); fsnotify_destroy_mark(chunk_entry); fsnotify_put_mark(chunk_entry); @@ -445,7 +445,6 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&old_entry->lock); fsnotify_destroy_mark(old_entry); fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */ - fsnotify_put_mark(old_entry); /* and kill it */ return 0; } -- GitLab From e51f2ce36e978380402105199577cfb807a8ba16 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 20 Aug 2012 14:44:52 +0000 Subject: [PATCH 0306/1799] drm: stop vmgfx driver explosion commit f5869a8308f77e3dfdc2e3640842b285aa788ff8 upstream. If you do a page flip with no flags set then event is NULL. If event is NULL then the vmw_gfx driver likes to go digging into NULL and extracts NULL->base.file_priv. On a modern kernel with NULL mapping protection it's just another oops, without it there are some "intriguing" possibilities. What it should do is an open question but that for the driver owners to sort out. Signed-off-by: Alan Cox Reviewed-by: Jakob Bornecrantz Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 2286d47e5022..00fb5aa2bf77 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1688,15 +1688,19 @@ int vmw_du_page_flip(struct drm_crtc *crtc, struct vmw_private *dev_priv = vmw_priv(crtc->dev); struct drm_framebuffer *old_fb = crtc->fb; struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); - struct drm_file *file_priv = event->base.file_priv; + struct drm_file *file_priv ; struct vmw_fence_obj *fence = NULL; struct drm_clip_rect clips; int ret; + if (event == NULL) + return -EINVAL; + /* require ScreenObject support for page flipping */ if (!dev_priv->sou_priv) return -ENOSYS; + file_priv = event->base.file_priv; if (!vmw_kms_screen_object_flippable(dev_priv, crtc)) return -EINVAL; -- GitLab From cbd3df71bb6563fe9ab2a16dc57937c0b59c3976 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 21 Aug 2012 09:55:01 -0400 Subject: [PATCH 0307/1799] Revert "drm/radeon: fix bo creation retry path" commit 676bc2e1e4f9072f7a640d5b7c99ffdf9709a6e7 upstream. This reverts commit d1c7871ddb1f588b8eb35affd9ee1a3d5e11cd0c. ttm_bo_init() destroys the BO on failure. So this patch makes the retry path work with freed memory. This ends up causing kernel panics when this path is hit. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_object.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 80c6e8bad656..df6a4dbd93f8 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -136,6 +136,7 @@ int radeon_bo_create(struct radeon_device *rdev, acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, sizeof(struct radeon_bo)); +retry: bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; @@ -149,8 +150,6 @@ int radeon_bo_create(struct radeon_device *rdev, bo->surface_reg = -1; INIT_LIST_HEAD(&bo->list); INIT_LIST_HEAD(&bo->va); - -retry: radeon_ttm_placement_from_domain(bo, domain); /* Kernel allocation are uninterruptible */ mutex_lock(&rdev->vram_mutex); -- GitLab From 389aec33837aeaf7e7e3cb31b6f1c6da6b009fb6 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 9 Aug 2012 18:12:28 -0400 Subject: [PATCH 0308/1799] svcrpc: fix BUG() in svc_tcp_clear_pages commit be1e44441a560c43c136a562d49a1c9623c91197 upstream. Examination of svc_tcp_clear_pages shows that it assumes sk_tcplen is consistent with sk_pages[] (in particular, sk_pages[n] can't be NULL if sk_tcplen would lead us to expect n pages of data). svc_tcp_restore_pages zeroes out sk_pages[] while leaving sk_tcplen. This is OK, since both functions are serialized by XPT_BUSY. However, that means the inconsistency must be repaired before dropping XPT_BUSY. Therefore we should be ensuring that svc_tcp_save_pages repairs the problem before exiting svc_tcp_recv_record on error. Symptoms were a BUG() in svc_tcp_clear_pages. Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/svcsock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 824d32fb3121..f190ea96f112 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1137,9 +1137,9 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) if (len >= 0) svsk->sk_tcplen += len; if (len != want) { + svc_tcp_save_pages(svsk, rqstp); if (len < 0 && len != -EAGAIN) goto err_other; - svc_tcp_save_pages(svsk, rqstp); dprintk("svc: incomplete TCP record (%d of %d)\n", svsk->sk_tcplen, svsk->sk_reclen); goto err_noclose; -- GitLab From 973caa9ec69452d87f65e67019429be5265f2534 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 17 Aug 2012 17:31:53 -0400 Subject: [PATCH 0309/1799] svcrpc: fix svc_xprt_enqueue/svc_recv busy-looping commit d10f27a750312ed5638c876e4bd6aa83664cccd8 upstream. The rpc server tries to ensure that there will be room to send a reply before it receives a request. It does this by tracking, in xpt_reserved, an upper bound on the total size of the replies that is has already committed to for the socket. Currently it is adding in the estimate for a new reply *before* it checks whether there is space available. If it finds that there is not space, it then subtracts the estimate back out. This may lead the subsequent svc_xprt_enqueue to decide that there is space after all. The results is a svc_recv() that will repeatedly return -EAGAIN, causing server threads to loop without doing any actual work. Reported-by: Michael Tokarev Tested-by: Michael Tokarev Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/svc_xprt.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 4bda09d7e1a4..9c9131bef48d 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -316,7 +316,6 @@ static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) */ void svc_xprt_enqueue(struct svc_xprt *xprt) { - struct svc_serv *serv = xprt->xpt_server; struct svc_pool *pool; struct svc_rqst *rqstp; int cpu; @@ -362,8 +361,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) rqstp, rqstp->rq_xprt); rqstp->rq_xprt = xprt; svc_xprt_get(xprt); - rqstp->rq_reserved = serv->sv_max_mesg; - atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); pool->sp_stats.threads_woken++; wake_up(&rqstp->rq_wait); } else { @@ -643,8 +640,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) if (xprt) { rqstp->rq_xprt = xprt; svc_xprt_get(xprt); - rqstp->rq_reserved = serv->sv_max_mesg; - atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); /* As there is a shortage of threads and this request * had to be queued, don't allow the thread to wait so @@ -741,6 +736,8 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) else len = xprt->xpt_ops->xpo_recvfrom(rqstp); dprintk("svc: got len=%d\n", len); + rqstp->rq_reserved = serv->sv_max_mesg; + atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); } svc_xprt_received(xprt); -- GitLab From 234c04ccc3c86c1da2f4173fdafb805bb6160380 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 20 Aug 2012 16:04:40 -0400 Subject: [PATCH 0310/1799] svcrpc: sends on closed socket should stop immediately commit f06f00a24d76e168ecb38d352126fd203937b601 upstream. svc_tcp_sendto sets XPT_CLOSE if we fail to transmit the entire reply. However, the XPT_CLOSE won't be acted on immediately. Meanwhile other threads could send further replies before the socket is really shut down. This can manifest as data corruption: for example, if a truncated read reply is followed by another rpc reply, that second reply will look to the client like further read data. Symptoms were data corruption preceded by svc_tcp_sendto logging something like kernel: rpc-srv/tcp: nfsd: sent only 963696 when sending 1048708 bytes - shutting down socket Reported-by: Malahal Naineni Tested-by: Malahal Naineni Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/svc_xprt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 9c9131bef48d..fd9b2889aa94 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -794,7 +794,8 @@ int svc_send(struct svc_rqst *rqstp) /* Grab mutex to serialize outgoing data. */ mutex_lock(&xprt->xpt_mutex); - if (test_bit(XPT_DEAD, &xprt->xpt_flags)) + if (test_bit(XPT_DEAD, &xprt->xpt_flags) + || test_bit(XPT_CLOSE, &xprt->xpt_flags)) len = -ENOTCONN; else len = xprt->xpt_ops->xpo_sendto(rqstp); -- GitLab From 8b340965ad3da83146684a9b68657374c5a8bfa4 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Tue, 21 Aug 2012 16:15:49 -0700 Subject: [PATCH 0311/1799] cciss: fix incorrect scsi status reporting commit b0cf0b118c90477d1a6811f2cd2307f6a5578362 upstream. Delete code which sets SCSI status incorrectly as it's already been set correctly above this incorrect code. The bug was introduced in 2009 by commit b0e15f6db111 ("cciss: fix typo that causes scsi status to be lost.") Signed-off-by: Stephen M. Cameron Reported-by: Roel van Meer Tested-by: Roel van Meer Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/block/cciss_scsi.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index acda773b3720..38aa6dda6b81 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -763,16 +763,7 @@ static void complete_scsi_command(CommandList_struct *c, int timeout, { case CMD_TARGET_STATUS: /* Pass it up to the upper layers... */ - if( ei->ScsiStatus) - { -#if 0 - printk(KERN_WARNING "cciss: cmd %p " - "has SCSI Status = %x\n", - c, ei->ScsiStatus); -#endif - cmd->result |= (ei->ScsiStatus << 1); - } - else { /* scsi status is zero??? How??? */ + if (!ei->ScsiStatus) { /* Ordinarily, this case should never happen, but there is a bug in some released firmware revisions that allows it to happen -- GitLab From 4500d525ad74c4195cdaf270bcc1f96dd0fd95ed Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 20 Aug 2012 10:57:22 -0400 Subject: [PATCH 0312/1799] ACPI: export symbol acpi_get_table_with_size commit 4f81f986761a7663db7d24d24cd6ae68008f1fc2 upstream. We need it in the radeon drm module to fetch and verify the vbios image on UEFI systems. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/acpica/tbxface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index abcc6412c244..33214d778881 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -436,6 +436,7 @@ acpi_get_table_with_size(char *signature, return (AE_NOT_FOUND); } +ACPI_EXPORT_SYMBOL(acpi_get_table_with_size) acpi_status acpi_get_table(char *signature, -- GitLab From 459243191d5ba70a94d74b604b91bf82bb9f0772 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 10 Aug 2012 11:00:24 +0200 Subject: [PATCH 0313/1799] ath9k: fix decrypt_error initialization in ath_rx_tasklet() commit e1352fde5682ab1bdd2a9e5d75c22d1fe210ef77 upstream. ath_rx_tasklet() calls ath9k_rx_skb_preprocess() and ath9k_rx_skb_postprocess() in a loop over the received frames. The decrypt_error flag is initialized to false just outside ath_rx_tasklet() loop. ath9k_rx_accept(), called by ath9k_rx_skb_preprocess(), only sets decrypt_error to true and never to false. Then ath_rx_tasklet() calls ath9k_rx_skb_postprocess() and passes decrypt_error to it. So, after a decryption error, in ath9k_rx_skb_postprocess(), we can have a leftover value from another processed frame. In that case, the frame will not be marked with RX_FLAG_DECRYPTED even if it is decrypted correctly. When using CCMP encryption this issue can lead to connection stuck because of CCMP PN corruption and a waste of CPU time since mac80211 tries to decrypt an already deciphered frame with ieee80211_aes_ccm_decrypt. Fix the issue initializing decrypt_error flag at the begging of the ath_rx_tasklet() loop. Signed-off-by: Lorenzo Bianconi Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/recv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index a2f7ae81a414..90b8527154e3 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1774,7 +1774,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) struct ieee80211_hw *hw = sc->hw; struct ieee80211_hdr *hdr; int retval; - bool decrypt_error = false; struct ath_rx_status rs; enum ath9k_rx_qtype qtype; bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); @@ -1796,6 +1795,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) tsf_lower = tsf & 0xffffffff; do { + bool decrypt_error = false; /* If handling rx interrupt and flush is in progress => exit */ if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) break; -- GitLab From 81d030df8597288a2fd12950aaf0842dbfa0b216 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 12 Aug 2012 23:26:07 +0200 Subject: [PATCH 0314/1799] PCI: EHCI: Fix crash during hibernation on ASUS computers commit 0b68c8e2c3afaf9807eb1ebe0ccfb3b809570aa4 upstream. Commit dbf0e4c (PCI: EHCI: fix crash during suspend on ASUS computers) added a workaround for an ASUS suspend issue related to USB EHCI and a bug in a number of ASUS BIOSes that attempt to shut down the EHCI controller during system suspend if its PCI command register doesn't contain 0 at that time. It turns out that the same workaround is necessary in the analogous hibernation code path, so add it. References: https://bugzilla.kernel.org/show_bug.cgi?id=45811 Reported-and-tested-by: Oleksij Rempel Signed-off-by: Rafael J. Wysocki Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-driver.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 3cd3f4528133..54fc9880e392 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -952,6 +952,13 @@ static int pci_pm_poweroff_noirq(struct device *dev) if (!pci_dev->state_saved && !pci_is_bridge(pci_dev)) pci_prepare_to_sleep(pci_dev); + /* + * The reason for doing this here is the same as for the analogous code + * in pci_pm_suspend_noirq(). + */ + if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) + pci_write_config_word(pci_dev, PCI_COMMAND, 0); + return 0; } -- GitLab From 3465c32ced49e3c04b7e280843f1a93ec8de8aff Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Thu, 23 Aug 2012 12:17:36 +0200 Subject: [PATCH 0315/1799] block: replace __getblk_slow misfix by grow_dev_page fix commit 676ce6d5ca3098339c028d44fe0427d1566a4d2d upstream. Commit 91f68c89d8f3 ("block: fix infinite loop in __getblk_slow") is not good: a successful call to grow_buffers() cannot guarantee that the page won't be reclaimed before the immediate next call to __find_get_block(), which is why there was always a loop there. Yesterday I got "EXT4-fs error (device loop0): __ext4_get_inode_loc:3595: inode #19278: block 664: comm cc1: unable to read itable block" on console, which pointed to this commit. I've been trying to bisect for weeks, why kbuild-on-ext4-on-loop-on-tmpfs sometimes fails from a missing header file, under memory pressure on ppc G5. I've never seen this on x86, and I've never seen it on 3.5-rc7 itself, despite that commit being in there: bisection pointed to an irrelevant pinctrl merge, but hard to tell when failure takes between 18 minutes and 38 hours (but so far it's happened quicker on 3.6-rc2). (I've since found such __ext4_get_inode_loc errors in /var/log/messages from previous weeks: why the message never appeared on console until yesterday morning is a mystery for another day.) Revert 91f68c89d8f3, restoring __getblk_slow() to how it was (plus a checkpatch nitfix). Simplify the interface between grow_buffers() and grow_dev_page(), and avoid the infinite loop beyond end of device by instead checking init_page_buffers()'s end_block there (I presume that's more efficient than a repeated call to blkdev_max_block()), returning -ENXIO to __getblk_slow() in that case. And remove akpm's ten-year-old "__getblk() cannot fail ... weird" comment, but that is worrying: are all users of __getblk() really now prepared for a NULL bh beyond end of device, or will some oops?? Signed-off-by: Hugh Dickins Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- fs/buffer.c | 66 ++++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 0bc1bed6c4e0..18669e92b676 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -914,7 +914,7 @@ link_dev_buffers(struct page *page, struct buffer_head *head) /* * Initialise the state of a blockdev page's buffers. */ -static void +static sector_t init_page_buffers(struct page *page, struct block_device *bdev, sector_t block, int size) { @@ -936,33 +936,41 @@ init_page_buffers(struct page *page, struct block_device *bdev, block++; bh = bh->b_this_page; } while (bh != head); + + /* + * Caller needs to validate requested block against end of device. + */ + return end_block; } /* * Create the page-cache page that contains the requested block. * - * This is user purely for blockdev mappings. + * This is used purely for blockdev mappings. */ -static struct page * +static int grow_dev_page(struct block_device *bdev, sector_t block, - pgoff_t index, int size) + pgoff_t index, int size, int sizebits) { struct inode *inode = bdev->bd_inode; struct page *page; struct buffer_head *bh; + sector_t end_block; + int ret = 0; /* Will call free_more_memory() */ page = find_or_create_page(inode->i_mapping, index, (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE); if (!page) - return NULL; + return ret; BUG_ON(!PageLocked(page)); if (page_has_buffers(page)) { bh = page_buffers(page); if (bh->b_size == size) { - init_page_buffers(page, bdev, block, size); - return page; + end_block = init_page_buffers(page, bdev, + index << sizebits, size); + goto done; } if (!try_to_free_buffers(page)) goto failed; @@ -982,14 +990,14 @@ grow_dev_page(struct block_device *bdev, sector_t block, */ spin_lock(&inode->i_mapping->private_lock); link_dev_buffers(page, bh); - init_page_buffers(page, bdev, block, size); + end_block = init_page_buffers(page, bdev, index << sizebits, size); spin_unlock(&inode->i_mapping->private_lock); - return page; - +done: + ret = (block < end_block) ? 1 : -ENXIO; failed: unlock_page(page); page_cache_release(page); - return NULL; + return ret; } /* @@ -999,7 +1007,6 @@ grow_dev_page(struct block_device *bdev, sector_t block, static int grow_buffers(struct block_device *bdev, sector_t block, int size) { - struct page *page; pgoff_t index; int sizebits; @@ -1023,22 +1030,14 @@ grow_buffers(struct block_device *bdev, sector_t block, int size) bdevname(bdev, b)); return -EIO; } - block = index << sizebits; + /* Create a page with the proper size buffers.. */ - page = grow_dev_page(bdev, block, index, size); - if (!page) - return 0; - unlock_page(page); - page_cache_release(page); - return 1; + return grow_dev_page(bdev, block, index, size, sizebits); } static struct buffer_head * __getblk_slow(struct block_device *bdev, sector_t block, int size) { - int ret; - struct buffer_head *bh; - /* Size must be multiple of hard sectorsize */ if (unlikely(size & (bdev_logical_block_size(bdev)-1) || (size < 512 || size > PAGE_SIZE))) { @@ -1051,21 +1050,20 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size) return NULL; } -retry: - bh = __find_get_block(bdev, block, size); - if (bh) - return bh; + for (;;) { + struct buffer_head *bh; + int ret; - ret = grow_buffers(bdev, block, size); - if (ret == 0) { - free_more_memory(); - goto retry; - } else if (ret > 0) { bh = __find_get_block(bdev, block, size); if (bh) return bh; + + ret = grow_buffers(bdev, block, size); + if (ret < 0) + return NULL; + if (ret == 0) + free_more_memory(); } - return NULL; } /* @@ -1321,10 +1319,6 @@ EXPORT_SYMBOL(__find_get_block); * which corresponds to the passed block_device, block and size. The * returned buffer has its reference count incremented. * - * __getblk() cannot fail - it just keeps trying. If you pass it an - * illegal block number, __getblk() will happily return a buffer_head - * which represents the non-existent block. Very weird. - * * __getblk() will lock up the machine if grow_dev_page's try_to_free_buffers() * attempt is failing. FIXME, perhaps? */ -- GitLab From 0f342b96d471d48fb151ae9073e58e0510e0a58f Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Tue, 7 Aug 2012 05:00:13 +0200 Subject: [PATCH 0316/1799] sched,cgroup: Fix up task_groups list commit 35cf4e50b16331def6cfcbee11e49270b6db07f5 upstream. With multiple instances of task_groups, for_each_rt_rq() is a noop, no task groups having been added to the rt.c list instance. This renders __enable/disable_runtime() and print_rt_stats() noop, the user (non) visible effect being that rt task groups are missing in /proc/sched_debug. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1344308413.6846.7.camel@marge.simpson.net Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/sched/core.c | 1 + kernel/sched/sched.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 817bf7018834..f70b975c85af 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7011,6 +7011,7 @@ int in_sched_functions(unsigned long addr) #ifdef CONFIG_CGROUP_SCHED struct task_group root_task_group; +LIST_HEAD(task_groups); #endif DECLARE_PER_CPU(cpumask_var_t, load_balance_tmpmask); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 116ced06ecc0..d9637f4c43de 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -80,7 +80,7 @@ extern struct mutex sched_domains_mutex; struct cfs_rq; struct rt_rq; -static LIST_HEAD(task_groups); +extern struct list_head task_groups; struct cfs_bandwidth { #ifdef CONFIG_CFS_BANDWIDTH -- GitLab From ebad30a797a5e5093d69e39bc046edab9452fe00 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 8 Aug 2012 11:27:15 +0200 Subject: [PATCH 0317/1799] sched: fix divide by zero at {thread_group,task}_times commit bea6832cc8c4a0a9a65dd17da6aaa657fe27bc3e upstream. On architectures where cputime_t is 64 bit type, is possible to trigger divide by zero on do_div(temp, (__force u32) total) line, if total is a non zero number but has lower 32 bit's zeroed. Removing casting is not a good solution since some do_div() implementations do cast to u32 internally. This problem can be triggered in practice on very long lived processes: PID: 2331 TASK: ffff880472814b00 CPU: 2 COMMAND: "oraagent.bin" #0 [ffff880472a51b70] machine_kexec at ffffffff8103214b #1 [ffff880472a51bd0] crash_kexec at ffffffff810b91c2 #2 [ffff880472a51ca0] oops_end at ffffffff814f0b00 #3 [ffff880472a51cd0] die at ffffffff8100f26b #4 [ffff880472a51d00] do_trap at ffffffff814f03f4 #5 [ffff880472a51d60] do_divide_error at ffffffff8100cfff #6 [ffff880472a51e00] divide_error at ffffffff8100be7b [exception RIP: thread_group_times+0x56] RIP: ffffffff81056a16 RSP: ffff880472a51eb8 RFLAGS: 00010046 RAX: bc3572c9fe12d194 RBX: ffff880874150800 RCX: 0000000110266fad RDX: 0000000000000000 RSI: ffff880472a51eb8 RDI: 001038ae7d9633dc RBP: ffff880472a51ef8 R8: 00000000b10a3a64 R9: ffff880874150800 R10: 00007fcba27ab680 R11: 0000000000000202 R12: ffff880472a51f08 R13: ffff880472a51f10 R14: 0000000000000000 R15: 0000000000000007 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 #7 [ffff880472a51f00] do_sys_times at ffffffff8108845d #8 [ffff880472a51f40] sys_times at ffffffff81088524 #9 [ffff880472a51f80] system_call_fastpath at ffffffff8100b0f2 RIP: 0000003808caac3a RSP: 00007fcba27ab6d8 RFLAGS: 00000202 RAX: 0000000000000064 RBX: ffffffff8100b0f2 RCX: 0000000000000000 RDX: 00007fcba27ab6e0 RSI: 000000000076d58e RDI: 00007fcba27ab6e0 RBP: 00007fcba27ab700 R8: 0000000000000020 R9: 000000000000091b R10: 00007fcba27ab680 R11: 0000000000000202 R12: 00007fff9ca41940 R13: 0000000000000000 R14: 00007fcba27ac9c0 R15: 00007fff9ca41940 ORIG_RAX: 0000000000000064 CS: 0033 SS: 002b Signed-off-by: Stanislaw Gruszka Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20120808092714.GA3580@redhat.com Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/sched/core.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index f70b975c85af..ef6a8f2eeffa 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3084,6 +3084,20 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) # define nsecs_to_cputime(__nsecs) nsecs_to_jiffies(__nsecs) #endif +static cputime_t scale_utime(cputime_t utime, cputime_t rtime, cputime_t total) +{ + u64 temp = (__force u64) rtime; + + temp *= (__force u64) utime; + + if (sizeof(cputime_t) == 4) + temp = div_u64(temp, (__force u32) total); + else + temp = div64_u64(temp, (__force u64) total); + + return (__force cputime_t) temp; +} + void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) { cputime_t rtime, utime = p->utime, total = utime + p->stime; @@ -3093,13 +3107,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 = (__force u64) rtime; - - temp *= (__force u64) utime; - do_div(temp, (__force u32) total); - utime = (__force cputime_t) temp; - } else + if (total) + utime = scale_utime(utime, rtime, total); + else utime = rtime; /* @@ -3126,13 +3136,9 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) total = cputime.utime + cputime.stime; rtime = nsecs_to_cputime(cputime.sum_exec_runtime); - if (total) { - u64 temp = (__force u64) rtime; - - temp *= (__force u64) cputime.utime; - do_div(temp, (__force u32) total); - utime = (__force cputime_t) temp; - } else + if (total) + utime = scale_utime(cputime.utime, rtime, total); + else utime = rtime; sig->prev_utime = max(sig->prev_utime, utime); -- GitLab From 190d60406f1e111bd212e271076bdab9e104ebe6 Mon Sep 17 00:00:00 2001 From: Jayakrishnan Memana Date: Sun, 15 Jul 2012 10:54:03 -0300 Subject: [PATCH 0318/1799] uvcvideo: Reset the bytesused field when recycling an erroneous buffer commit 8a3f0ede2b3f5477122060af1a816c6bbf09fcd2 upstream. Buffers marked as erroneous are recycled immediately by the driver if the nodrop module parameter isn't set. The buffer payload size is reset to 0, but the buffer bytesused field isn't. This results in the buffer being immediately considered as complete, leading to an infinite loop in interrupt context. Fix the problem by resetting the bytesused field when recycling the buffer. Signed-off-by: Jayakrishnan Memana Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/uvc/uvc_queue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 8f54e24e3f35..4261bf231932 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -355,6 +355,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) { buf->error = 0; buf->state = UVC_BUF_STATE_QUEUED; + buf->bytesused = 0; vb2_set_plane_payload(&buf->buf, 0, 0); return buf; } -- GitLab From 8d30b9939e38e55035bad49f964ff6a3f671179e Mon Sep 17 00:00:00 2001 From: Alexandre Bounine Date: Tue, 21 Aug 2012 16:16:11 -0700 Subject: [PATCH 0319/1799] rapidio/tsi721: fix inbound doorbell interrupt handling commit 3670e7e12e582c6d67761275d148171feb7a9004 upstream. Make sure that there is no doorbell messages left behind due to disabled interrupts during inbound doorbell processing. The most common case for this bug is loss of rionet JOIN messages in systems with three or more rionet participants and MSI or MSI-X enabled. As result, requests for packet transfers may finish with "destination unreachable" error message. This patch is applicable to kernel versions starting from v3.2. Signed-off-by: Alexandre Bounine Cc: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rapidio/devices/tsi721.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 30d2072f480b..91e0f316b611 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -439,6 +439,9 @@ static void tsi721_db_dpc(struct work_struct *work) " info %4.4x\n", DBELL_SID(idb.bytes), DBELL_TID(idb.bytes), DBELL_INF(idb.bytes)); } + + wr_ptr = ioread32(priv->regs + + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; } iowrite32(rd_ptr & (IDB_QSIZE - 1), @@ -449,6 +452,10 @@ static void tsi721_db_dpc(struct work_struct *work) regval |= TSI721_SR_CHINT_IDBQRCV; iowrite32(regval, priv->regs + TSI721_SR_CHINTE(IDB_QUEUE)); + + wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; + if (wr_ptr != rd_ptr) + schedule_work(&priv->idb_work); } /** -- GitLab From 3ad3bc52af22aa08b703c57f494e6d7f9beabe7b Mon Sep 17 00:00:00 2001 From: Alexandre Bounine Date: Tue, 21 Aug 2012 16:16:12 -0700 Subject: [PATCH 0320/1799] rapidio/tsi721: fix unused variable compiler warning commit 9a9a9a7adafe62a34de8b4fb48936c1c5f9bafa5 upstream. Fix unused variable compiler warning when built with CONFIG_RAPIDIO_DEBUG option off. This patch is applicable to kernel versions starting from v3.2 Signed-off-by: Alexandre Bounine Cc: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rapidio/devices/tsi721.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 91e0f316b611..33471e11a738 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -2162,7 +2162,7 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct tsi721_device *priv; - int i, cap; + int cap; int err; u32 regval; @@ -2182,12 +2182,15 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, priv->pdev = pdev; #ifdef DEBUG + { + int i; for (i = 0; i <= PCI_STD_RESOURCE_END; i++) { dev_dbg(&pdev->dev, "res[%d] @ 0x%llx (0x%lx, 0x%lx)\n", i, (unsigned long long)pci_resource_start(pdev, i), (unsigned long)pci_resource_len(pdev, i), pci_resource_flags(pdev, i)); } + } #endif /* * Verify BAR configuration -- GitLab From 0522ba5d15022bca061c7c73c811eaed916bb369 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 15 Aug 2012 01:10:04 +0300 Subject: [PATCH 0321/1799] regulator: twl-regulator: fix up VINTANA1/VINTANA2 commit 908d6d52928a7f2a4b317aac47542c5fbef43d88 upstream. It seems commit 2098e95ce9bb039ff2e7bf836df358d18a176139 (regulator: twl: adapt twl-regulator driver to dt) accidentally deleted VINTANA1. Also the same commit defines VINTANA2 twice with TWL4030_ADJUSTABLE_LDO and TWL4030_FIXED_LDO. This patch changes the fixed one to be VINTANA1. I noticed this when auditing my N900 boot logs. I could not notice any change in device behaviour, though, except that the boot logs are now like before: ... [ 0.282928] VDAC: 1800 mV normal standby [ 0.284027] VCSI: 1800 mV normal standby [ 0.285400] VINTANA1: 1500 mV normal standby [ 0.286865] VINTANA2: 2750 mV normal standby [ 0.288208] VINTDIG: 1500 mV normal standby [ 0.289978] VSDI_CSI: 1800 mV normal standby ... Signed-off-by: Aaro Koskinen Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/regulator/twl-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 9cdfc389ca26..1eb7a1510937 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1085,7 +1085,7 @@ TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300); -TWL4030_FIXED_LDO(VINTANA2, 0x3f, 1500, 11, 100, 0x08); +TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08); TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08); TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08); TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08); @@ -1166,7 +1166,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = { TWL6025_OF_MATCH("ti,twl6025-ldo6", LDO6), TWL6025_OF_MATCH("ti,twl6025-ldoln", LDOLN), TWL6025_OF_MATCH("ti,twl6025-ldousb", LDOUSB), - TWLFIXED_OF_MATCH("ti,twl4030-vintana2", VINTANA2), + TWLFIXED_OF_MATCH("ti,twl4030-vintana1", VINTANA1), TWLFIXED_OF_MATCH("ti,twl4030-vintdig", VINTDIG), TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5), TWLFIXED_OF_MATCH("ti,twl4030-vusb1v8", VUSB1V8), -- GitLab From e9497730c0f0b2b15006a869a2d3ed6febce5f1b Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 18 Aug 2012 16:11:37 -0400 Subject: [PATCH 0322/1799] x32: Use compat shims for {g,s}etsockopt commit 515c7af85ed92696c311c53d53cb4898ff32d784 upstream. Some of the arguments to {g,s}etsockopt are passed in userland pointers. If we try to use the 64bit entry point, we end up sometimes failing. For example, dhcpcd doesn't run in x32: # dhcpcd eth0 dhcpcd[1979]: version 5.5.6 starting dhcpcd[1979]: eth0: broadcasting for a lease dhcpcd[1979]: eth0: open_socket: Invalid argument dhcpcd[1979]: eth0: send_raw_packet: Bad file descriptor The code in particular is getting back EINVAL when doing: struct sock_fprog pf; setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)); Diving into the kernel code, we can see: include/linux/filter.h: struct sock_fprog { unsigned short len; struct sock_filter __user *filter; }; net/core/sock.c: case SO_ATTACH_FILTER: ret = -EINVAL; if (optlen == sizeof(struct sock_fprog)) { struct sock_fprog fprog; ret = -EFAULT; if (copy_from_user(&fprog, optval, sizeof(fprog))) break; ret = sk_attach_filter(&fprog, sk); } break; arch/x86/syscalls/syscall_64.tbl: 54 common setsockopt sys_setsockopt 55 common getsockopt sys_getsockopt So for x64, sizeof(sock_fprog) is 16 bytes. For x86/x32, it's 8 bytes. This comes down to the pointer being 32bit for x32, which means we need to do structure size translation. But since x32 comes in directly to sys_setsockopt, it doesn't get translated like x86. After changing the syscall table and rebuilding glibc with the new kernel headers, dhcp runs fine in an x32 userland. Oddly, it seems like Linus noted the same thing during the initial port, but I guess that was missed/lost along the way: https://lkml.org/lkml/2011/8/26/452 [ hpa: tagging for -stable since this is an ABI fix. ] Bugzilla: https://bugs.gentoo.org/423649 Reported-by: Mads Signed-off-by: Mike Frysinger Link: http://lkml.kernel.org/r/1345320697-15713-1-git-send-email-vapier@gentoo.org Cc: H. J. Lu Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/syscalls/syscall_64.tbl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl index dd29a9ea27c5..fd1f10348130 100644 --- a/arch/x86/syscalls/syscall_64.tbl +++ b/arch/x86/syscalls/syscall_64.tbl @@ -60,8 +60,8 @@ 51 common getsockname sys_getsockname 52 common getpeername sys_getpeername 53 common socketpair sys_socketpair -54 common setsockopt sys_setsockopt -55 common getsockopt sys_getsockopt +54 64 setsockopt sys_setsockopt +55 64 getsockopt sys_getsockopt 56 common clone stub_clone 57 common fork stub_fork 58 common vfork stub_vfork @@ -351,3 +351,5 @@ 538 x32 sendmmsg compat_sys_sendmmsg 539 x32 process_vm_readv compat_sys_process_vm_readv 540 x32 process_vm_writev compat_sys_process_vm_writev +541 x32 setsockopt compat_sys_setsockopt +542 x32 getsockopt compat_sys_getsockopt -- GitLab From 3c8ac60ddf5f8efaa1b65466fa357954259e387d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:27 -0700 Subject: [PATCH 0323/1799] USB: spca506: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e694d518886c7afedcdd1732477832b2e32744e4 upstream. This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork CC: Hans de Goede CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/gspca/spca506.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index 54eed87672d2..21e6a37bc7a8 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -685,7 +685,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const struct usb_device_id device_table[] __devinitconst = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x06e1, 0xa190)}, /*fixme: may be IntelPCCameraPro BRIDGE_SPCA505 {USB_DEVICE(0x0733, 0x0430)}, */ -- GitLab From 3ecad65934b8d33eeab93f2230f6418642013d27 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:27 -0700 Subject: [PATCH 0324/1799] USB: jl2005bcd: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit ec063351684298e295dc9444d143ddfd6ab02df8 upstream. This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork CC: Hans de Goede CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/gspca/jl2005bcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/video/gspca/jl2005bcd.c index 53f58ef367cf..3264d878cfde 100644 --- a/drivers/media/video/gspca/jl2005bcd.c +++ b/drivers/media/video/gspca/jl2005bcd.c @@ -510,7 +510,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0979, 0x0227)}, {} }; -- GitLab From 37037e1533d34db1256977fe2363142b8287780b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:28 -0700 Subject: [PATCH 0325/1799] USB: p54usb: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b9c4167cbbafddac3462134013bc15e63e4c53ef upstream. This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork CC: Christian Lamparter CC: "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 f4d28c39aac7..a337a50d4022 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -42,7 +42,7 @@ MODULE_FIRMWARE("isl3887usb"); * whenever you add a new device. */ -static struct usb_device_id p54u_table[] __devinitdata = { +static struct usb_device_id p54u_table[] = { /* Version 1 devices (pci chip + net2280) */ {USB_DEVICE(0x0411, 0x0050)}, /* Buffalo WLI2-USB2-G54 */ {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ -- GitLab From 98ad260d991f75b38ac1fbce0a10b4a45799f97b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:29 -0700 Subject: [PATCH 0326/1799] USB: rtl8187: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a3433179d0822ccfa8e80aa4d1d52843bd2dcc63 upstream. This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork CC: Herton Ronaldo Krzesinski CC: Hin-Tak Leung CC: Larry Finger CC: "John W. Linville" Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtl818x/rtl8187/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index cf53ac9d6f23..86467a20c5b3 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -44,7 +44,7 @@ MODULE_AUTHOR("Larry Finger "); MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); MODULE_LICENSE("GPL"); -static struct usb_device_id rtl8187_table[] __devinitdata = { +static struct usb_device_id rtl8187_table[] = { /* Asus */ {USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187}, /* Belkin */ -- GitLab From 5750abb9208ee301f0ae9c6c6cb231460feddf0e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 17:48:26 -0700 Subject: [PATCH 0327/1799] USB: smsusb: remove __devinit* from the struct usb_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d04dbd1c0ec17a13326c8f2279399c225836a79f upstream. This structure needs to always stick around, even if CONFIG_HOTPLUG is disabled, otherwise we can oops when trying to probe a device that was added after the structure is thrown away. Thanks to Fengguang Wu and Bjørn Mork for tracking this issue down. Reported-by: Fengguang Wu Reported-by: Bjørn Mork CC: Mauro Carvalho Chehab CC: Michael Krufky CC: Paul Gortmaker CC: Doron Cohen Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb/siano/smsusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index 664e460f247b..aac622200e99 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c @@ -481,7 +481,7 @@ static int smsusb_resume(struct usb_interface *intf) return 0; } -static const struct usb_device_id smsusb_id_table[] __devinitconst = { +static const struct usb_device_id smsusb_id_table[] = { { USB_DEVICE(0x187f, 0x0010), .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, { USB_DEVICE(0x187f, 0x0100), -- GitLab From a9959bb7e1510edb3326beb354e59da0a6a0dab1 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Fri, 17 Aug 2012 21:43:43 +0200 Subject: [PATCH 0328/1799] USB: CDC ACM: Fix NULL pointer dereference commit 99f347caa4568cb803862730b3b1f1942639523f upstream. If a device specifies zero endpoints in its interface descriptor, the kernel oopses in acm_probe(). Even though that's clearly an invalid descriptor, we should test wether we have all endpoints. This is especially bad as this oops can be triggered by just plugging a USB device in. Signed-off-by: Sven Schnelle 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 640cf7983b02..1b632cb88acf 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1104,7 +1104,8 @@ static int acm_probe(struct usb_interface *intf, } - if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) + if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 || + control_interface->cur_altsetting->desc.bNumEndpoints == 0) return -EINVAL; epctrl = &control_interface->cur_altsetting->endpoint[0].desc; -- GitLab From 652f43702b224351b790fd9182744d7946d4cdf6 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 3 Sep 2012 16:47:56 +0000 Subject: [PATCH 0329/1799] powerpc: Update DSCR on all CPUs when writing sysfs dscr_default commit 1b6ca2a6fe56e7697d57348646e07df08f43b1bb upstream. Writing to dscr_default in sysfs doesn't actually change the DSCR - we rely on a context switch on each CPU to do the work. There is no guarantee we will get a context switch in a reasonable amount of time so fire off an IPI to force an immediate change. This issue was found with the following test case: http://ozlabs.org/~anton/junkcode/dscr_explicit_test.c Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/sysfs.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 3529446c2abd..d4cbbd1fa75f 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -194,6 +194,12 @@ static ssize_t show_dscr_default(struct device *dev, return sprintf(buf, "%lx\n", dscr_default); } +static void update_dscr(void *dummy) +{ + if (!current->thread.dscr_inherit) + mtspr(SPRN_DSCR, dscr_default); +} + static ssize_t __used store_dscr_default(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -206,6 +212,8 @@ static ssize_t __used store_dscr_default(struct device *dev, return -EINVAL; dscr_default = val; + on_each_cpu(update_dscr, NULL, 1); + return count; } -- GitLab From 59d0622a07571c6344f0e3c71e7a1a71eb8db9e9 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 3 Sep 2012 16:48:46 +0000 Subject: [PATCH 0330/1799] powerpc: Keep thread.dscr and thread.dscr_inherit in sync commit 00ca0de02f80924dfff6b4f630e1dff3db005e35 upstream. When we update the DSCR either via emulation of mtspr(DSCR) or via a change to dscr_default in sysfs we don't update thread.dscr. We will eventually update it at context switch time but there is a period where thread.dscr is incorrect. If we fork at this point we will copy the old value of thread.dscr into the child. To avoid this, always keep thread.dscr in sync with reality. This issue was found with the following testcase: http://ozlabs.org/~anton/junkcode/dscr_inherit_test.c Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/sysfs.c | 4 +++- arch/powerpc/kernel/traps.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index d4cbbd1fa75f..8302af649219 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -196,8 +196,10 @@ static ssize_t show_dscr_default(struct device *dev, static void update_dscr(void *dummy) { - if (!current->thread.dscr_inherit) + if (!current->thread.dscr_inherit) { + current->thread.dscr = dscr_default; mtspr(SPRN_DSCR, dscr_default); + } } static ssize_t __used store_dscr_default(struct device *dev, diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 158972341a2d..ae0843fa7a61 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -972,8 +972,9 @@ static int emulate_instruction(struct pt_regs *regs) cpu_has_feature(CPU_FTR_DSCR)) { PPC_WARN_EMULATED(mtdscr, regs); rd = (instword >> 21) & 0x1f; - mtspr(SPRN_DSCR, regs->gpr[rd]); + current->thread.dscr = regs->gpr[rd]; current->thread.dscr_inherit = 1; + mtspr(SPRN_DSCR, current->thread.dscr); return 0; } #endif -- GitLab From c68ef2b5cb50b54e7be25f53186ebf20220c6476 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 3 Sep 2012 16:49:47 +0000 Subject: [PATCH 0331/1799] powerpc: Fix DSCR inheritance in copy_thread() commit 1021cb268b3025573c4811f1dee4a11260c4507b upstream. If the default DSCR is non zero we set thread.dscr_inherit in copy_thread() meaning the new thread and all its children will ignore future updates to the default DSCR. This is not intended and is a change in behaviour that a number of our users have hit. We just need to inherit thread.dscr and thread.dscr_inherit from the parent which ends up being much simpler. This was found with the following test case: http://ozlabs.org/~anton/junkcode/dscr_default_test.c Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/process.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 4937c9690090..94178e55f49d 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -799,16 +799,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, #endif /* CONFIG_PPC_STD_MMU_64 */ #ifdef CONFIG_PPC64 if (cpu_has_feature(CPU_FTR_DSCR)) { - if (current->thread.dscr_inherit) { - p->thread.dscr_inherit = 1; - p->thread.dscr = current->thread.dscr; - } else if (0 != dscr_default) { - p->thread.dscr_inherit = 1; - p->thread.dscr = dscr_default; - } else { - p->thread.dscr_inherit = 0; - p->thread.dscr = 0; - } + p->thread.dscr_inherit = current->thread.dscr_inherit; + p->thread.dscr = current->thread.dscr; } #endif -- GitLab From fe83a638356c2a7ea4e429ea5ce627d5001757fe Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 3 Sep 2012 16:51:10 +0000 Subject: [PATCH 0332/1799] powerpc: Restore correct DSCR in context switch commit 714332858bfd40dcf8f741498336d93875c23aa7 upstream. During a context switch we always restore the per thread DSCR value. If we aren't doing explicit DSCR management (ie thread.dscr_inherit == 0) and the default DSCR changed while the process has been sleeping we end up with the wrong value. Check thread.dscr_inherit and select the default DSCR or per thread DSCR as required. This was found with the following test case, when running with more threads than CPUs (ie forcing context switching): http://ozlabs.org/~anton/junkcode/dscr_default_test.c With the four patches applied I can run a combination of all test cases successfully at the same time: http://ozlabs.org/~anton/junkcode/dscr_default_test.c http://ozlabs.org/~anton/junkcode/dscr_explicit_test.c http://ozlabs.org/~anton/junkcode/dscr_inherit_test.c Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/asm-offsets.c | 1 + arch/powerpc/kernel/entry_64.S | 23 +++++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 34b8afe94a50..ec0b529c3950 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -76,6 +76,7 @@ int main(void) DEFINE(SIGSEGV, SIGSEGV); DEFINE(NMI_MASK, NMI_MASK); DEFINE(THREAD_DSCR, offsetof(struct thread_struct, dscr)); + DEFINE(THREAD_DSCR_INHERIT, offsetof(struct thread_struct, dscr_inherit)); #else DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); #endif /* CONFIG_PPC64 */ diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index ef2074c3e906..e500969bea0c 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -373,6 +373,12 @@ _GLOBAL(ret_from_fork) li r3,0 b syscall_exit + .section ".toc","aw" +DSCR_DEFAULT: + .tc dscr_default[TC],dscr_default + + .section ".text" + /* * This routine switches between two different tasks. The process * state of one is saved on its kernel stack. Then the state @@ -512,9 +518,6 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) mr r1,r8 /* start using new stack pointer */ std r7,PACAKSAVE(r13) - ld r6,_CCR(r1) - mtcrf 0xFF,r6 - #ifdef CONFIG_ALTIVEC BEGIN_FTR_SECTION ld r0,THREAD_VRSAVE(r4) @@ -523,14 +526,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_PPC64 BEGIN_FTR_SECTION + lwz r6,THREAD_DSCR_INHERIT(r4) + ld r7,DSCR_DEFAULT@toc(2) ld r0,THREAD_DSCR(r4) - cmpd r0,r25 - beq 1f + cmpwi r6,0 + bne 1f + ld r0,0(r7) +1: cmpd r0,r25 + beq 2f mtspr SPRN_DSCR,r0 -1: +2: END_FTR_SECTION_IFSET(CPU_FTR_DSCR) #endif + ld r6,_CCR(r1) + mtcrf 0xFF,r6 + /* r3-r13 are destroyed -- Cort */ REST_8GPRS(14, r1) REST_10GPRS(22, r1) -- GitLab From 242fa18ad8d4665c151bdd5c34ac34a8e701fff7 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 4 Sep 2012 18:33:08 +0000 Subject: [PATCH 0333/1799] powerpc: Make sure IPI handlers see data written by IPI senders commit 9fb1b36ca1234e64a5d1cc573175303395e3354d upstream. We have been observing hangs, both of KVM guest vcpu tasks and more generally, where a process that is woken doesn't properly wake up and continue to run, but instead sticks in TASK_WAKING state. This happens because the update of rq->wake_list in ttwu_queue_remote() is not ordered with the update of ipi_message in smp_muxed_ipi_message_pass(), and the reading of rq->wake_list in scheduler_ipi() is not ordered with the reading of ipi_message in smp_ipi_demux(). Thus it is possible for the IPI receiver not to see the updated rq->wake_list and therefore conclude that there is nothing for it to do. In order to make sure that anything done before smp_send_reschedule() is ordered before anything done in the resulting call to scheduler_ipi(), this adds barriers in smp_muxed_message_pass() and smp_ipi_demux(). The barrier in smp_muxed_message_pass() is a full barrier to ensure that there is a full ordering between the smp_send_reschedule() caller and scheduler_ipi(). In smp_ipi_demux(), we use xchg() rather than xchg_local() because xchg() includes release and acquire barriers. Using xchg() rather than xchg_local() makes sense given that ipi_message is not just accessed locally. This moves the barrier between setting the message and calling the cause_ipi() function into the individual cause_ipi implementations. Most of them -- those that used outb, out_8 or similar -- already had a full barrier because out_8 etc. include a sync before the MMIO store. This adds an explicit barrier in the two remaining cases. These changes made no measurable difference to the speed of IPIs as measured using a simple ping-pong latency test across two CPUs on different cores of a POWER7 machine. The analysis of the reason why processes were not waking up properly is due to Milton Miller. Reported-by: Milton Miller Signed-off-by: Paul Mackerras Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/dbell.c | 2 ++ arch/powerpc/kernel/smp.c | 11 +++++++++-- arch/powerpc/sysdev/xics/icp-hv.c | 6 +++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c index 5b25c8060fd6..a892680668d8 100644 --- a/arch/powerpc/kernel/dbell.c +++ b/arch/powerpc/kernel/dbell.c @@ -28,6 +28,8 @@ void doorbell_setup_this_cpu(void) void doorbell_cause_ipi(int cpu, unsigned long data) { + /* Order previous accesses vs. msgsnd, which is treated as a store */ + mb(); ppc_msgsnd(PPC_DBELL, 0, data); } diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index d9f94410fd7f..ab24aee19bce 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -215,8 +215,15 @@ void smp_muxed_ipi_message_pass(int cpu, int msg) struct cpu_messages *info = &per_cpu(ipi_message, cpu); char *message = (char *)&info->messages; + /* + * Order previous accesses before accesses in the IPI handler. + */ + smp_mb(); message[msg] = 1; - mb(); + /* + * cause_ipi functions are required to include a full barrier + * before doing whatever causes the IPI. + */ smp_ops->cause_ipi(cpu, info->data); } @@ -228,7 +235,7 @@ irqreturn_t smp_ipi_demux(void) mb(); /* order any irq clear */ do { - all = xchg_local(&info->messages, 0); + all = xchg(&info->messages, 0); #ifdef __BIG_ENDIAN if (all & (1 << (24 - 8 * PPC_MSG_CALL_FUNCTION))) diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c index 253dce98c16e..762c5ca37606 100644 --- a/arch/powerpc/sysdev/xics/icp-hv.c +++ b/arch/powerpc/sysdev/xics/icp-hv.c @@ -65,7 +65,11 @@ static inline void icp_hv_set_xirr(unsigned int value) static inline void icp_hv_set_qirr(int n_cpu , u8 value) { int hw_cpu = get_hard_smp_processor_id(n_cpu); - long rc = plpar_hcall_norets(H_IPI, hw_cpu, value); + long rc; + + /* Make sure all previous accesses are ordered before IPI sending */ + mb(); + rc = plpar_hcall_norets(H_IPI, hw_cpu, value); if (rc != H_SUCCESS) { pr_err("%s: bad return code qirr cpu=%d hw_cpu=%d mfrr=0x%x " "returned %ld\n", __func__, n_cpu, hw_cpu, value, rc); -- GitLab From 05d71a5a25da396f76ee942af6682dfaecc73e84 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 6 Sep 2012 12:01:00 -0400 Subject: [PATCH 0334/1799] Remove user-triggerable BUG from mpol_to_str commit 80de7c3138ee9fd86a98696fd2cf7ad89b995d0a upstream. Trivially triggerable, found by trinity: kernel BUG at mm/mempolicy.c:2546! Process trinity-child2 (pid: 23988, threadinfo ffff88010197e000, task ffff88007821a670) Call Trace: show_numa_map+0xd5/0x450 show_pid_numa_map+0x13/0x20 traverse+0xf2/0x230 seq_read+0x34b/0x3e0 vfs_read+0xac/0x180 sys_pread64+0xa2/0xc0 system_call_fastpath+0x1a/0x1f RIP: mpol_to_str+0x156/0x360 Signed-off-by: Dave Jones Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mempolicy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index bf5b485ecd31..9afcbad632ec 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2536,7 +2536,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context) break; default: - BUG(); + return -EINVAL; } l = strlen(policy_modes[mode]); -- GitLab From 43da476d7f734a1b55680668246d0237dde4ea57 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Sat, 1 Sep 2012 12:34:07 -0400 Subject: [PATCH 0335/1799] Fix order of arguments to compat_put_time[spec|val] commit ed6fe9d614fc1bca95eb8c0ccd0e92db00ef9d5d upstream. Commit 644595f89620 ("compat: Handle COMPAT_USE_64BIT_TIME in net/socket.c") introduced a bug where the helper functions to take either a 64-bit or compat time[spec|val] got the arguments in the wrong order, passing the kernel stack pointer off as a user pointer (and vice versa). Because of the user address range check, that in turn then causes an EFAULT due to the user pointer range checking failing for the kernel address. Incorrectly resuling in a failed system call for 32-bit processes with a 64-bit kernel. On odder architectures like HP-PA (with separate user/kernel address spaces), it can be used read kernel memory. Signed-off-by: Mikulas Patocka Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- net/socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/socket.c b/net/socket.c index 573b26152a30..06ffa0f28398 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2605,7 +2605,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock, err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); set_fs(old_fs); if (!err) - err = compat_put_timeval(up, &ktv); + err = compat_put_timeval(&ktv, up); return err; } @@ -2621,7 +2621,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock, err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); set_fs(old_fs); if (!err) - err = compat_put_timespec(up, &kts); + err = compat_put_timespec(&kts, up); return err; } -- GitLab From dc0c0a9fc1f7ce1051f144c749f75921085fc869 Mon Sep 17 00:00:00 2001 From: Kashyap Desai Date: Tue, 17 Jul 2012 18:20:44 -0700 Subject: [PATCH 0336/1799] SCSI: megaraid_sas: Move poll_aen_lock initializer commit bd8d6dd43a77bfd2b8fef5b094b9d6095e169dee upstream. The following patch moves the poll_aen_lock initializer from megasas_probe_one() to megasas_init(). This prevents a crash when a user loads the driver and tries to issue a poll() system call on the ioctl interface with no adapters present. Signed-off-by: Kashyap Desai Signed-off-by: Adam Radford Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/megaraid/megaraid_sas_base.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 8b300be44284..6308a8ddf6ff 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -4066,7 +4066,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&instance->cmd_pool_lock); spin_lock_init(&instance->hba_lock); spin_lock_init(&instance->completion_lock); - spin_lock_init(&poll_aen_lock); mutex_init(&instance->aen_mutex); mutex_init(&instance->reset_mutex); @@ -5392,6 +5391,8 @@ static int __init megasas_init(void) printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, MEGASAS_EXT_VERSION); + spin_lock_init(&poll_aen_lock); + support_poll_for_event = 2; support_device_change = 1; -- GitLab From 797efad403c63c9a94a8f78e06ccb3aa5b4980a9 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Thu, 31 May 2012 15:05:33 -0400 Subject: [PATCH 0337/1799] SCSI: scsi_lib: fix scsi_io_completion's SG_IO error propagation commit 27c419739b67decced4650440829b8d51bef954b upstream. The following v3.4-rc1 commit unmasked an existing bug in scsi_io_completion's SG_IO error handling: 47ac56d [SCSI] scsi_error: classify some ILLEGAL_REQUEST sense as a permanent TARGET_ERROR Given that certain ILLEGAL_REQUEST are now properly categorized as TARGET_ERROR the host_byte is being set (before host_byte wasn't ever set for these ILLEGAL_REQUEST). In scsi_io_completion, initialize req->errors with cmd->result _after_ the SG_IO block that calls __scsi_error_from_host_byte (which may modify the host_byte). Before this fix: cdb to send: 12 01 01 00 00 00 ioctl(3, SG_IO, {'S', SG_DXFER_NONE, cmd[6]=[12, 01, 01, 00, 00, 00], mx_sb_len=32, iovec_count=0, dxfer_len=0, timeout=20000, flags=0, status=02, masked_status=01, sb[19]=[70, 00, 05, 00, 00, 00, 00, 0b, 00, 00, 00, 00, 24, 00, 00, 00, 00, 00, 00], host_status=0x10, driver_status=0x8, resid=0, duration=0, info=0x1}) = 0 SCSI Status: Check Condition Sense Information: sense buffer empty After: cdb to send: 12 01 01 00 00 00 ioctl(3, SG_IO, {'S', SG_DXFER_NONE, cmd[6]=[12, 01, 01, 00, 00, 00], mx_sb_len=32, iovec_count=0, dxfer_len=0, timeout=20000, flags=0, status=02, masked_status=01, sb[19]=[70, 00, 05, 00, 00, 00, 00, 0b, 00, 00, 00, 00, 24, 00, 00, 00, 00, 00, 00], host_status=0, driver_status=0x8, resid=0, duration=0, info=0x1}) = 0 SCSI Status: Check Condition Sense Information: Fixed format, current; Sense key: Illegal Request Additional sense: Invalid field in cdb Raw sense data (in hex): 70 00 05 00 00 00 00 0b 00 00 00 00 24 00 00 00 00 00 00 Reported-by: Paolo Bonzini Tested-by: Paolo Bonzini Signed-off-by: Mike Snitzer Reviewed-by: Babu Moger Signed-off-by: Greg Kroah-Hartman Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 19291463c554..2bc036292d9d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -760,7 +760,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) } if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */ - req->errors = result; if (result) { if (sense_valid && req->sense) { /* @@ -776,6 +775,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) if (!sense_deferred) error = __scsi_error_from_host_byte(cmd, result); } + /* + * __scsi_error_from_host_byte may have reset the host_byte + */ + req->errors = cmd->result; req->resid_len = scsi_get_resid(cmd); -- GitLab From 7a4601c0bfde4ed50c54f30c32c5677e3daec4f9 Mon Sep 17 00:00:00 2001 From: "sreekanth.reddy@lsi.com" Date: Tue, 17 Jul 2012 15:57:05 +0530 Subject: [PATCH 0338/1799] SCSI: mpt2sas: Fix for Driver oops, when loading driver with max_queue_depth command line option to a very small value commit 338b131a3269881c7431234855c93c219b0979b6 upstream. If the specified max_queue_depth setting is less than the expected number of internal commands, then driver will calculate the queue depth size to a negitive number. This negitive number is actually a very large number because variable is unsigned 16bit integer. So, the driver will ask for a very large amount of memory for message frames and resulting into oops as memory allocation routines will not able to handle such a large request. So, in order to limit this kind of oops, The driver need to set the max_queue_depth to a scsi mid layer's can_queue value. Then the overall message frames required for IO is minimum of either (max_queue_depth plus internal commands) or the IOC global credits. Signed-off-by: Sreekanth Reddy Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/mpt2sas/mpt2sas_base.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 3f03342b3030..c4cef569540b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -2417,10 +2417,13 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) } /* command line tunables for max controller queue depth */ - if (max_queue_depth != -1) - max_request_credit = (max_queue_depth < facts->RequestCredit) - ? max_queue_depth : facts->RequestCredit; - else + if (max_queue_depth != -1 && max_queue_depth != 0) { + max_request_credit = min_t(u16, max_queue_depth + + ioc->hi_priority_depth + ioc->internal_depth, + facts->RequestCredit); + if (max_request_credit > MAX_HBA_QUEUE_DEPTH) + max_request_credit = MAX_HBA_QUEUE_DEPTH; + } else max_request_credit = min_t(u16, facts->RequestCredit, MAX_HBA_QUEUE_DEPTH); @@ -2495,7 +2498,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) /* set the scsi host can_queue depth * with some internal commands that could be outstanding */ - ioc->shost->can_queue = ioc->scsiio_depth - (2); + ioc->shost->can_queue = ioc->scsiio_depth; dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: " "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue)); -- GitLab From d3ed1731ba6bca32ac0ac96377cae8fd735e16e6 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 25 Jul 2012 23:55:55 +0400 Subject: [PATCH 0339/1799] SCSI: Fix 'Device not ready' issue on mpt2sas commit 14216561e164671ce147458653b1fea06a4ada1e upstream. This is a particularly nasty SCSI ATA Translation Layer (SATL) problem. SAT-2 says (section 8.12.2) if the device is in the stopped state as the result of processing a START STOP UNIT command (see 9.11), then the SATL shall terminate the TEST UNIT READY command with CHECK CONDITION status with the sense key set to NOT READY and the additional sense code of LOGICAL UNIT NOT READY, INITIALIZING COMMAND REQUIRED; mpt2sas internal SATL seems to implement this. The result is very confusing standby behaviour (using hdparm -y). If you suspend a drive and then send another command, usually it wakes up. However, if the next command is a TEST UNIT READY, the SATL sees that the drive is suspended and proceeds to follow the SATL rules for this, returning NOT READY to all subsequent commands. This means that the ordering of TEST UNIT READY is crucial: if you send TUR and then a command, you get a NOT READY to both back. If you send a command and then a TUR, you get GOOD status because the preceeding command woke the drive. This bit us badly because commit 85ef06d1d252f6a2e73b678591ab71caad4667bb Author: Tejun Heo Date: Fri Jul 1 16:17:47 2011 +0200 block: flush MEDIA_CHANGE from drivers on close(2) Changed our ordering on TEST UNIT READY commands meaning that SATA drives connected to an mpt2sas now suspend and refuse to wake (because the mpt2sas SATL sees the suspend *before* the drives get awoken by the next ATA command) resulting in lots of failed commands. The standard is completely nuts forcing this inconsistent behaviour, but we have to work around it. The fix for this is twofold: 1. Set the allow_restart flag so we wake the drive when we see it has been suspended 2. Return all TEST UNIT READY status directly to the mid layer without any further error handling which prevents us causing error handling which may offline the device just because of a media check TUR. Reported-by: Matthias Prager Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_error.c | 10 ++++++++++ drivers/scsi/scsi_scan.c | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index cc8dc8cc6d6f..b3f0b0f6d44b 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -42,6 +42,8 @@ #include +static void scsi_eh_done(struct scsi_cmnd *scmd); + #define SENSE_TIMEOUT (10*HZ) /* @@ -241,6 +243,14 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) if (! scsi_command_normalize_sense(scmd, &sshdr)) return FAILED; /* no valid sense data */ + if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done) + /* + * nasty: for mid-layer issued TURs, we need to return the + * actual sense data without any recovery attempt. For eh + * issued ones, we need to try to recover and interpret + */ + return SUCCESS; + if (scsi_sense_is_deferred(&sshdr)) return NEEDS_RETRY; diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 8906557d2a24..348840e80921 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -776,6 +776,16 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, sdev->model = (char *) (sdev->inquiry + 16); sdev->rev = (char *) (sdev->inquiry + 32); + if (strncmp(sdev->vendor, "ATA ", 8) == 0) { + /* + * sata emulation layer device. This is a hack to work around + * the SATL power management specifications which state that + * when the SATL detects the device has gone into standby + * mode, it shall respond with NOT READY. + */ + sdev->allow_restart = 1; + } + if (*bflags & BLIST_ISROM) { sdev->type = TYPE_ROM; sdev->removable = 1; -- GitLab From d027dffcc66f749ee34c74edbd77efaaea573e4d Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 5 Sep 2012 15:48:23 +0200 Subject: [PATCH 0340/1799] udf: Fix data corruption for files in ICB commit 9c2fc0de1a6e638fe58c354a463f544f42a90a09 upstream. When a file is stored in ICB (inode), we overwrite part of the file, and the page containing file's data is not in page cache, we end up corrupting file's data by overwriting them with zeros. The problem is we use simple_write_begin() which simply zeroes parts of the page which are not written to. The problem has been introduced by be021ee4 (udf: convert to new aops). Fix the problem by providing a ->write_begin function which makes the page properly uptodate. Reported-by: Ian Abbott Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/udf/file.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/fs/udf/file.c b/fs/udf/file.c index 7f3f7ba3df6e..d1c6093fd3d3 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -39,20 +39,24 @@ #include "udf_i.h" #include "udf_sb.h" -static int udf_adinicb_readpage(struct file *file, struct page *page) +static void __udf_adinicb_readpage(struct page *page) { struct inode *inode = page->mapping->host; char *kaddr; struct udf_inode_info *iinfo = UDF_I(inode); - BUG_ON(!PageLocked(page)); - kaddr = kmap(page); - memset(kaddr, 0, PAGE_CACHE_SIZE); memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, inode->i_size); + memset(kaddr + inode->i_size, 0, PAGE_CACHE_SIZE - inode->i_size); flush_dcache_page(page); SetPageUptodate(page); kunmap(page); +} + +static int udf_adinicb_readpage(struct file *file, struct page *page) +{ + BUG_ON(!PageLocked(page)); + __udf_adinicb_readpage(page); unlock_page(page); return 0; @@ -77,6 +81,25 @@ static int udf_adinicb_writepage(struct page *page, return 0; } +static int udf_adinicb_write_begin(struct file *file, + struct address_space *mapping, loff_t pos, + unsigned len, unsigned flags, struct page **pagep, + void **fsdata) +{ + struct page *page; + + if (WARN_ON_ONCE(pos >= PAGE_CACHE_SIZE)) + return -EIO; + page = grab_cache_page_write_begin(mapping, 0, flags); + if (!page) + return -ENOMEM; + *pagep = page; + + if (!PageUptodate(page) && len != PAGE_CACHE_SIZE) + __udf_adinicb_readpage(page); + return 0; +} + static int udf_adinicb_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, @@ -98,8 +121,8 @@ static int udf_adinicb_write_end(struct file *file, const struct address_space_operations udf_adinicb_aops = { .readpage = udf_adinicb_readpage, .writepage = udf_adinicb_writepage, - .write_begin = simple_write_begin, - .write_end = udf_adinicb_write_end, + .write_begin = udf_adinicb_write_begin, + .write_end = udf_adinicb_write_end, }; static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, -- GitLab From 6cbe67f990c723facaeed94e29a1d854dc5930ec Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 3 Sep 2012 16:50:42 +0200 Subject: [PATCH 0341/1799] ext3: Fix fdatasync() for files with only i_size changes commit 156bddd8e505b295540f3ca0e27dda68cb0d49aa upstream. Code tracking when transaction needs to be committed on fdatasync(2) forgets to handle a situation when only inode's i_size is changed. Thus in such situations fdatasync(2) doesn't force transaction with new i_size to disk and that can result in wrong i_size after a crash. Fix the issue by updating inode's i_datasync_tid whenever its size is updated. Reported-by: Kristian Nielsen Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/ext3/inode.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 10d7812f6021..075281734fcb 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -3068,6 +3068,8 @@ static int ext3_do_update_inode(handle_t *handle, struct ext3_inode_info *ei = EXT3_I(inode); struct buffer_head *bh = iloc->bh; int err = 0, rc, block; + int need_datasync = 0; + __le32 disksize; again: /* we can't allow multiple procs in here at once, its a bit racey */ @@ -3105,7 +3107,11 @@ static int ext3_do_update_inode(handle_t *handle, raw_inode->i_gid_high = 0; } raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); - raw_inode->i_size = cpu_to_le32(ei->i_disksize); + disksize = cpu_to_le32(ei->i_disksize); + if (disksize != raw_inode->i_size) { + need_datasync = 1; + raw_inode->i_size = disksize; + } raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec); raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec); raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec); @@ -3121,8 +3127,11 @@ static int ext3_do_update_inode(handle_t *handle, if (!S_ISREG(inode->i_mode)) { raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl); } else { - raw_inode->i_size_high = - cpu_to_le32(ei->i_disksize >> 32); + disksize = cpu_to_le32(ei->i_disksize >> 32); + if (disksize != raw_inode->i_size_high) { + raw_inode->i_size_high = disksize; + need_datasync = 1; + } if (ei->i_disksize > 0x7fffffffULL) { struct super_block *sb = inode->i_sb; if (!EXT3_HAS_RO_COMPAT_FEATURE(sb, @@ -3175,6 +3184,8 @@ static int ext3_do_update_inode(handle_t *handle, ext3_clear_inode_state(inode, EXT3_STATE_NEW); atomic_set(&ei->i_sync_tid, handle->h_transaction->t_tid); + if (need_datasync) + atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid); out_brelse: brelse (bh); ext3_std_error(inode->i_sb, err); -- GitLab From b4b55ff702c3551ba39ccec0b1dda9e3b57429be Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 4 Sep 2012 18:45:54 +0200 Subject: [PATCH 0342/1799] fuse: fix retrieve length commit c9e67d483776d8d2a5f3f70491161b205930ffe1 upstream. In some cases fuse_retrieve() would return a short byte count if offset was non-zero. The data returned was correct, though. Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman --- fs/fuse/dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 7df2b5e8fbe1..f4246cfc8d87 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1576,6 +1576,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, req->pages[req->num_pages] = page; req->num_pages++; + offset = 0; num -= this_num; total_len += this_num; index++; -- GitLab From f313f5b440c874dbee75922e30736b9069f0a1d1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 10 Sep 2012 10:14:02 +0200 Subject: [PATCH 0343/1799] i2c-designware: Fix build error if CONFIG_I2C_DESIGNWARE_PLATFORM=y && CONFIG_I2C_DESIGNWARE_PCI=y commit e68bb91baa0bb9817567bd45d560919e8e26373b upstream. This patch adds config I2C_DESIGNWARE_CORE in Kconfig, and let I2C_DESIGNWARE_PLATFORM and I2C_DESIGNWARE_PCI select I2C_DESIGNWARE_CORE. Because both I2C_DESIGNWARE_PLATFORM and I2C_DESIGNWARE_PCI can be built as built-in or module, we also need to export the functions in i2c-designware-core. This fixes below build error when CONFIG_I2C_DESIGNWARE_PLATFORM=y && CONFIG_I2C_DESIGNWARE_PCI=y: LD drivers/i2c/busses/built-in.o drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_clear_int': i2c-designware-core.c:(.text+0xa10): multiple definition of `i2c_dw_clear_int' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x928): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_init': i2c-designware-core.c:(.text+0x178): multiple definition of `i2c_dw_init' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x90): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `dw_readl': i2c-designware-core.c:(.text+0xe8): multiple definition of `dw_readl' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x0): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_isr': i2c-designware-core.c:(.text+0x724): multiple definition of `i2c_dw_isr' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x63c): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_xfer': i2c-designware-core.c:(.text+0x4b0): multiple definition of `i2c_dw_xfer' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x3c8): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_is_enabled': i2c-designware-core.c:(.text+0x9d4): multiple definition of `i2c_dw_is_enabled' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x8ec): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `dw_writel': i2c-designware-core.c:(.text+0x124): multiple definition of `dw_writel' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x3c): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_xfer_msg': i2c-designware-core.c:(.text+0x2e8): multiple definition of `i2c_dw_xfer_msg' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x200): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_enable': i2c-designware-core.c:(.text+0x9c8): multiple definition of `i2c_dw_enable' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x8e0): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_read_comp_param': i2c-designware-core.c:(.text+0xa24): multiple definition of `i2c_dw_read_comp_param' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x93c): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_disable': i2c-designware-core.c:(.text+0x9dc): multiple definition of `i2c_dw_disable' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x8f4): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_func': i2c-designware-core.c:(.text+0x710): multiple definition of `i2c_dw_func' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x628): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_disable_int': i2c-designware-core.c:(.text+0xa18): multiple definition of `i2c_dw_disable_int' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x930): first defined here make[3]: *** [drivers/i2c/busses/built-in.o] Error 1 make[2]: *** [drivers/i2c/busses] Error 2 make[1]: *** [drivers/i2c] Error 2 make: *** [drivers] Error 2 Signed-off-by: Axel Lin Signed-off-by: Jean Delvare Tested-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/Kconfig | 5 +++++ drivers/i2c/busses/Makefile | 5 +++-- drivers/i2c/busses/i2c-designware-core.c | 11 +++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index d2c5095deeac..489a2a7bf2f7 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -350,9 +350,13 @@ config I2C_DAVINCI devices such as DaVinci NIC. For details please see http://www.ti.com/davinci +config I2C_DESIGNWARE_CORE + tristate + config I2C_DESIGNWARE_PLATFORM tristate "Synopsys DesignWare Platfrom" depends on HAVE_CLK + select I2C_DESIGNWARE_CORE help If you say yes to this option, support will be included for the Synopsys DesignWare I2C adapter. Only master mode is supported. @@ -363,6 +367,7 @@ config I2C_DESIGNWARE_PLATFORM config I2C_DESIGNWARE_PCI tristate "Synopsys DesignWare PCI" depends on PCI + select I2C_DESIGNWARE_CORE help If you say yes to this option, support will be included for the Synopsys DesignWare I2C adapter. Only master mode is supported. diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 569567b0d027..2f05d7b6c414 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -33,10 +33,11 @@ obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o +obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o -i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o +i2c-designware-platform-objs := i2c-designware-platdrv.o obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o -i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o +i2c-designware-pci-objs := i2c-designware-pcidrv.o obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index df8799241009..619334994df9 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -25,6 +25,7 @@ * ---------------------------------------------------------------------------- * */ +#include #include #include #include @@ -305,6 +306,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev) dw_writel(dev, dev->master_cfg , DW_IC_CON); return 0; } +EXPORT_SYMBOL_GPL(i2c_dw_init); /* * Waiting for bus not busy @@ -557,12 +559,14 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) return ret; } +EXPORT_SYMBOL_GPL(i2c_dw_xfer); u32 i2c_dw_func(struct i2c_adapter *adap) { struct dw_i2c_dev *dev = i2c_get_adapdata(adap); return dev->functionality; } +EXPORT_SYMBOL_GPL(i2c_dw_func); static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) { @@ -667,17 +671,20 @@ irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) return IRQ_HANDLED; } +EXPORT_SYMBOL_GPL(i2c_dw_isr); void i2c_dw_enable(struct dw_i2c_dev *dev) { /* Enable the adapter */ dw_writel(dev, 1, DW_IC_ENABLE); } +EXPORT_SYMBOL_GPL(i2c_dw_enable); u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev) { return dw_readl(dev, DW_IC_ENABLE); } +EXPORT_SYMBOL_GPL(i2c_dw_is_enabled); void i2c_dw_disable(struct dw_i2c_dev *dev) { @@ -688,18 +695,22 @@ void i2c_dw_disable(struct dw_i2c_dev *dev) dw_writel(dev, 0, DW_IC_INTR_MASK); dw_readl(dev, DW_IC_CLR_INTR); } +EXPORT_SYMBOL_GPL(i2c_dw_disable); void i2c_dw_clear_int(struct dw_i2c_dev *dev) { dw_readl(dev, DW_IC_CLR_INTR); } +EXPORT_SYMBOL_GPL(i2c_dw_clear_int); void i2c_dw_disable_int(struct dw_i2c_dev *dev) { dw_writel(dev, 0, DW_IC_INTR_MASK); } +EXPORT_SYMBOL_GPL(i2c_dw_disable_int); u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev) { return dw_readl(dev, DW_IC_COMP_PARAM_1); } +EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); -- GitLab From 7db3f56f37640c88387dfda6fad1e930d589d0e3 Mon Sep 17 00:00:00 2001 From: James Ralston Date: Mon, 10 Sep 2012 10:14:02 +0200 Subject: [PATCH 0344/1799] i2c-i801: Add Device IDs for Intel Lynx Point-LP PCH commit 4a8f1ddde942e232387e6129ce4f4c412e43802f upstream. Add the SMBus Device IDs for the Intel Lynx Point-LP PCH. Signed-off-by: James Ralston Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/i2c-i801 | 1 + drivers/i2c/busses/Kconfig | 1 + drivers/i2c/busses/i2c-i801.c | 3 +++ 3 files changed, 5 insertions(+) diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801 index 71f55bbcefc8..99d4e442b77d 100644 --- a/Documentation/i2c/busses/i2c-i801 +++ b/Documentation/i2c/busses/i2c-i801 @@ -21,6 +21,7 @@ Supported adapters: * Intel DH89xxCC (PCH) * Intel Panther Point (PCH) * Intel Lynx Point (PCH) + * Intel Lynx Point-LP (PCH) Datasheets: Publicly available at the Intel website On Intel Patsburg and later chipsets, both the normal host SMBus controller diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 489a2a7bf2f7..ea8736bc257d 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -104,6 +104,7 @@ config I2C_I801 DH89xxCC (PCH) Panther Point (PCH) Lynx Point (PCH) + Lynx Point-LP (PCH) This driver can also be built as a module. If so, the module will be called i2c-i801. diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index ae2945a5e007..d88ec812160e 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -52,6 +52,7 @@ DH89xxCC (PCH) 0x2330 32 hard yes yes yes Panther Point (PCH) 0x1e22 32 hard yes yes yes Lynx Point (PCH) 0x8c22 32 hard yes yes yes + Lynx Point-LP (PCH) 0x9c22 32 hard yes yes yes Features supported by this driver: Software PEC no @@ -147,6 +148,7 @@ #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 +#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 struct i801_priv { struct i2c_adapter adapter; @@ -636,6 +638,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) }, { 0, } }; -- GitLab From 7d60f877b38866c5b46162256207891c45057b39 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Aug 2012 10:51:55 -0400 Subject: [PATCH 0345/1799] HID: add NOGET quirk for Eaton Ellipse MAX UPS commit 67ddbb3e6568fb1820b2cc45b00c50702b114801 upstream. This patch (as1603) adds a NOGET quirk for the Eaton Ellipse MAX UPS device. (The USB IDs were already present in hid-ids.h, apparently under a different name.) Signed-off-by: Alan Stern Reported-by: Laurent Bigonville Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/usbhid/hid-quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 82f61ee632b5..dc9697c2764f 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -70,6 +70,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS }, -- GitLab From ae2e2906541827de51f896e3b035bf3b1c660e73 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 21 Aug 2012 21:57:15 -0700 Subject: [PATCH 0346/1799] Input: i8042 - add Gigabyte T1005 series netbooks to noloop table commit 7b125b94ca16b7e618c6241cb02c4c8060cea5e3 upstream. They all define their chassis type as "Other" and therefore are not categorized as "laptops" by the driver, which tries to perform AUX IRQ delivery test which fails and causes touchpad not working. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=42620 Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/serio/i8042-x86ia64io.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 5ec774d6c82b..6918773ce024 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -176,6 +176,20 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"), }, }, + { + /* Gigabyte T1005 - defines wrong chassis type ("Other") */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), + DMI_MATCH(DMI_PRODUCT_NAME, "T1005"), + }, + }, + { + /* Gigabyte T1005M/P - defines wrong chassis type ("Other") */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), + DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"), + }, + }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), -- GitLab From df0b962e0900ec0b2b93eac2795e3e65cc18052f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 28 Aug 2012 21:40:51 -0400 Subject: [PATCH 0347/1799] drm/vmwgfx: add MODULE_DEVICE_TABLE so vmwgfx loads at boot commit c4903429a92be60e6fe59868924a65eca4cd1a38 upstream. This will cause udev to load vmwgfx instead of waiting for X to do it. Reviewed-by: Jakob Bornecrantz Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index ee24d216aa85..7279b3ec0124 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -182,6 +182,7 @@ static struct pci_device_id vmw_pci_id_list[] = { {0x15ad, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VMWGFX_CHIP_SVGAII}, {0, 0, 0} }; +MODULE_DEVICE_TABLE(pci, vmw_pci_id_list); static int enable_fbdev; -- GitLab From 9db2bc1e0363bb9401e6407b198463c01f32dd84 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 23 Jul 2012 12:16:19 +0100 Subject: [PATCH 0348/1799] PARISC: Redefine ATOMIC_INIT and ATOMIC64_INIT to drop the casts commit bba3d8c3b3c0f2123be5bc687d1cddc13437c923 upstream. The following build error occured during a parisc build with swap-over-NFS patches applied. net/core/sock.c:274:36: error: initializer element is not constant net/core/sock.c:274:36: error: (near initialization for 'memalloc_socks') net/core/sock.c:274:36: error: initializer element is not constant Dave Anglin says: > Here is the line in sock.i: > > struct static_key memalloc_socks = ((struct static_key) { .enabled = > ((atomic_t) { (0) }) }); The above line contains two compound literals. It also uses a designated initializer to initialize the field enabled. A compound literal is not a constant expression. The location of the above statement isn't fully clear, but if a compound literal occurs outside the body of a function, the initializer list must consist of constant expressions. Reported-by: Fengguang Wu Signed-off-by: Mel Gorman Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- arch/parisc/include/asm/atomic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index 6c6defc24619..af9cf30ed474 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h @@ -141,7 +141,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) #define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0) -#define ATOMIC_INIT(i) ((atomic_t) { (i) }) +#define ATOMIC_INIT(i) { (i) } #define smp_mb__before_atomic_dec() smp_mb() #define smp_mb__after_atomic_dec() smp_mb() @@ -150,7 +150,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) #ifdef CONFIG_64BIT -#define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) +#define ATOMIC64_INIT(i) { (i) } static __inline__ s64 __atomic64_add_return(s64 i, atomic64_t *v) -- GitLab From 095ac020be339cad6f158508cc3b9f740c60b53a Mon Sep 17 00:00:00 2001 From: Ronny Hegewald Date: Fri, 31 Aug 2012 09:57:52 +0000 Subject: [PATCH 0349/1799] xen: Use correct masking in xen_swiotlb_alloc_coherent. commit b5031ed1be0aa419250557123633453753181643 upstream. When running 32-bit pvops-dom0 and a driver tries to allocate a coherent DMA-memory the xen swiotlb-implementation returned memory beyond 4GB. The underlaying reason is that if the supplied driver passes in a DMA_BIT_MASK(64) ( hwdev->coherent_dma_mask is set to 0xffffffffffffffff) our dma_mask will be u64 set to 0xffffffffffffffff even if we set it to DMA_BIT_MASK(32) previously. Meaning we do not reset the upper bits. By using the dma_alloc_coherent_mask function - it does the proper casting and we get 0xfffffffff. This caused not working sound on a system with 4 GB and a 64-bit compatible sound-card with sets the DMA-mask to 64bit. On bare-metal and the forward-ported xen-dom0 patches from OpenSuse a coherent DMA-memory is always allocated inside the 32-bit address-range by calling dma_alloc_coherent_mask. This patch adds the same functionality to xen swiotlb and is a rebase of the original patch from Ronny Hegewald which never got upstream b/c the underlaying reason was not understood until now. The original email with the original patch is in: http://old-list-archives.xen.org/archives/html/xen-devel/2010-02/msg00038.html the original thread from where the discussion started is in: http://old-list-archives.xen.org/archives/html/xen-devel/2010-01/msg00928.html Signed-off-by: Ronny Hegewald Signed-off-by: Stefano Panella Acked-By: David Vrabel Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/xen/swiotlb-xen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 1afb4fba11b4..4d519488d304 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -232,7 +232,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, return ret; if (hwdev && hwdev->coherent_dma_mask) - dma_mask = hwdev->coherent_dma_mask; + dma_mask = dma_alloc_coherent_mask(hwdev, flags); phys = virt_to_phys(ret); dev_addr = xen_phys_to_bus(phys); -- GitLab From bbebafa0d9507206793a05fbeb010eafb1fdb0d0 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 5 Sep 2012 16:35:20 -0400 Subject: [PATCH 0350/1799] xen/pciback: Fix proper FLR steps. commit 80ba77dfbce85f2d1be54847de3c866de1b18a9a upstream. When we do FLR and save PCI config we did it in the wrong order. The end result was that if a PCI device was unbind from its driver, then binded to xen-pciback, and then back to its driver we would get: > lspci -s 04:00.0 04:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection 13:42:12 # 4 :~/ > echo "0000:04:00.0" > /sys/bus/pci/drivers/pciback/unbind > modprobe e1000e e1000e: Intel(R) PRO/1000 Network Driver - 2.0.0-k e1000e: Copyright(c) 1999 - 2012 Intel Corporation. e1000e 0000:04:00.0: Disabling ASPM L0s L1 e1000e 0000:04:00.0: enabling device (0000 -> 0002) xen: registering gsi 48 triggering 0 polarity 1 Already setup the GSI :48 e1000e 0000:04:00.0: Interrupt Throttling Rate (ints/sec) set to dynamic conservative mode e1000e: probe of 0000:04:00.0 failed with error -2 This fixes it by first saving the PCI configuration space, then doing the FLR. Reported-by: Ren, Yongjie Reported-and-Tested-by: Tobias Geiger Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/xen/xen-pciback/pci_stub.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 097e536e8672..03342728bf23 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -353,16 +353,16 @@ static int __devinit pcistub_init_device(struct pci_dev *dev) if (err) goto config_release; - dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); - __pci_reset_function_locked(dev); - /* We need the device active to save the state. */ dev_dbg(&dev->dev, "save state of device\n"); pci_save_state(dev); dev_data->pci_saved_state = pci_store_saved_state(dev); if (!dev_data->pci_saved_state) dev_err(&dev->dev, "Could not store PCI conf saved state!\n"); - + else { + dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); + __pci_reset_function_locked(dev); + } /* Now disable the device (this also ensures some private device * data is setup before we export) */ -- GitLab From 72961d91696071841fa013f11f686eaa7e2d0996 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Tue, 31 Jul 2012 15:41:45 +0200 Subject: [PATCH 0351/1799] x86, microcode, AMD: Fix broken ucode patch size check commit 36bf50d7697be18c6bfd0401e037df10bff1e573 upstream. This issue was recently observed on an AMD C-50 CPU where a patch of maximum size was applied. Commit be62adb49294 ("x86, microcode, AMD: Simplify ucode verification") added current_size in get_matching_microcode(). This is calculated as size of the ucode patch + 8 (ie. size of the header). Later this is compared against the maximum possible ucode patch size for a CPU family. And of course this fails if the patch has already maximum size. Signed-off-by: Andreas Herrmann Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1344361461-10076-1-git-send-email-bp@amd64.org Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/microcode_amd.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 8a2ce8fd41c0..82746f942cd8 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -143,11 +143,12 @@ static int get_matching_microcode(int cpu, const u8 *ucode_ptr, unsigned int *current_size) { struct microcode_header_amd *mc_hdr; - unsigned int actual_size; + unsigned int actual_size, patch_size; u16 equiv_cpu_id; /* size of the current patch we're staring at */ - *current_size = *(u32 *)(ucode_ptr + 4) + SECTION_HDR_SIZE; + patch_size = *(u32 *)(ucode_ptr + 4); + *current_size = patch_size + SECTION_HDR_SIZE; equiv_cpu_id = find_equiv_id(); if (!equiv_cpu_id) @@ -174,7 +175,7 @@ static int get_matching_microcode(int cpu, const u8 *ucode_ptr, /* * now that the header looks sane, verify its size */ - actual_size = verify_ucode_size(cpu, *current_size, leftover_size); + actual_size = verify_ucode_size(cpu, patch_size, leftover_size); if (!actual_size) return 0; -- GitLab From af843972724e172827266e91ba326c069c8c088c Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:54 +0000 Subject: [PATCH 0352/1799] dccp: check ccid before dereferencing commit 276bdb82dedb290511467a5a4fdbe9f0b52dce6f upstream. ccid_hc_rx_getsockopt() and ccid_hc_tx_getsockopt() might be called with a NULL ccid pointer leading to a NULL pointer dereference. This could lead to a privilege escalation if the attacker is able to map page 0 and prepare it with a fake ccid_ops pointer. Signed-off-by: Mathias Krause Cc: Gerrit Renker Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/dccp/ccid.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 75c3582a7678..fb85d371a8de 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -246,7 +246,7 @@ static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, u32 __user *optval, int __user *optlen) { int rc = -ENOPROTOOPT; - if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL) + if (ccid != NULL && ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL) rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len, optval, optlen); return rc; @@ -257,7 +257,7 @@ static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk, u32 __user *optval, int __user *optlen) { int rc = -ENOPROTOOPT; - if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL) + if (ccid != NULL && ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL) rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len, optval, optlen); return rc; -- GitLab From e18625cacb8e252e3e4a9dea3db4dbca523276bc Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Tue, 21 Aug 2012 17:36:28 +0200 Subject: [PATCH 0353/1799] hwmon: (asus_atk0110) Add quirk for Asus M5A78L MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 43ca6cb28c871f2fbad10117b0648e5ae3b0f638 upstream. The old interface is bugged and reads the wrong sensor when retrieving the reading for the chassis fan (it reads the CPU sensor); the new interface works fine. Reported-by: Göran Uddeborg Tested-by: Göran Uddeborg Signed-off-by: Luca Tettamanti Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/asus_atk0110.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 351d1f4593e7..4ee578948723 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -34,6 +34,12 @@ static const struct dmi_system_id __initconst atk_force_new_if[] = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "SABERTOOTH X58") } + }, { + /* Old interface reads the same sensor for fan0 and fan1 */ + .ident = "Asus M5A78L", + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "M5A78L") + } }, { } }; -- GitLab From 00709f7f01c3a10252f030f0bdacecbb349d7be4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 15:18:55 -0700 Subject: [PATCH 0354/1799] Linux 3.4.11 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a1624b991301..22345c016221 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 10 +SUBLEVEL = 11 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 2dc3b21fbca98bd3c8d9e53acf5d966add3c7606 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 30 Jul 2012 15:57:00 +0000 Subject: [PATCH 0355/1799] net: Allow driver to limit number of GSO segments per skb [ Upstream commit 30b678d844af3305cda5953467005cebb5d7b687 ] A peer (or local user) may cause TCP to use a nominal MSS of as little as 88 (actual MSS of 76 with timestamps). Given that we have a sufficiently prodigious local sender and the peer ACKs quickly enough, it is nevertheless possible to grow the window for such a connection to the point that we will try to send just under 64K at once. This results in a single skb that expands to 861 segments. In some drivers with TSO support, such an skb will require hundreds of DMA descriptors; a substantial fraction of a TX ring or even more than a full ring. The TX queue selected for the skb may stall and trigger the TX watchdog repeatedly (since the problem skb will be retried after the TX reset). This particularly affects sfc, for which the issue is designated as CVE-2012-3412. Therefore: 1. Add the field net_device::gso_max_segs holding the device-specific limit. 2. In netif_skb_features(), if the number of segments is too high then mask out GSO features to force fall back to software GSO. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/netdevice.h | 2 ++ net/core/dev.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 33900a53c990..79596d6dd853 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1279,6 +1279,8 @@ struct net_device { /* for setting kernel sock attribute on TCP connection setup */ #define GSO_MAX_SIZE 65536 unsigned int gso_max_size; +#define GSO_MAX_SEGS 65535 + u16 gso_max_segs; #ifdef CONFIG_DCB /* Data Center Bridging netlink ops */ diff --git a/net/core/dev.c b/net/core/dev.c index c299416d0e89..665730f06f30 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2121,6 +2121,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) __be16 protocol = skb->protocol; netdev_features_t features = skb->dev->features; + if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) + features &= ~NETIF_F_GSO_MASK; + if (protocol == htons(ETH_P_8021Q)) { struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; protocol = veh->h_vlan_encapsulated_proto; @@ -5909,6 +5912,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, dev_net_set(dev, &init_net); dev->gso_max_size = GSO_MAX_SIZE; + dev->gso_max_segs = GSO_MAX_SEGS; INIT_LIST_HEAD(&dev->napi_list); INIT_LIST_HEAD(&dev->unreg_list); -- GitLab From 0a1f711681e0d7068b69c0697c4ba284fbf1b2bf Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 30 Jul 2012 15:57:44 +0000 Subject: [PATCH 0356/1799] sfc: Fix maximum number of TSO segments and minimum TX queue size [ Upstream commit 7e6d06f0de3f74ca929441add094518ae332257c ] Currently an skb requiring TSO may not fit within a minimum-size TX queue. The TX queue selected for the skb may stall and trigger the TX watchdog repeatedly (since the problem skb will be retried after the TX reset). This issue is designated as CVE-2012-3412. Set the maximum number of TSO segments for our devices to 100. This should make no difference to behaviour unless the actual MSS is less than about 700. Increase the minimum TX queue size accordingly to allow for 2 worst-case skbs, so that there will definitely be space to add an skb after we wake a queue. To avoid invalidating existing configurations, change efx_ethtool_set_ringparam() to fix up values that are too small rather than returning -EINVAL. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/sfc/efx.c | 6 ++++++ drivers/net/ethernet/sfc/efx.h | 14 ++++++++++---- drivers/net/ethernet/sfc/ethtool.c | 16 +++++++++++----- drivers/net/ethernet/sfc/tx.c | 19 +++++++++++++++++++ 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 4a0005342e65..954b8854b25a 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1498,6 +1498,11 @@ static int efx_probe_all(struct efx_nic *efx) goto fail2; } + BUILD_BUG_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_RXQ_MIN_ENT); + if (WARN_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_TXQ_MIN_ENT(efx))) { + rc = -EINVAL; + goto fail3; + } efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE; rc = efx_probe_filters(efx); @@ -2065,6 +2070,7 @@ static int efx_register_netdev(struct efx_nic *efx) net_dev->irq = efx->pci_dev->irq; net_dev->netdev_ops = &efx_netdev_ops; SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops); + net_dev->gso_max_segs = EFX_TSO_MAX_SEGS; rtnl_lock(); diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index be8f9158a714..70755c97251a 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -30,6 +30,7 @@ extern netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb); extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index); extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc); +extern unsigned int efx_tx_max_skb_descs(struct efx_nic *efx); /* RX */ extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue); @@ -52,10 +53,15 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue); #define EFX_MAX_EVQ_SIZE 16384UL #define EFX_MIN_EVQ_SIZE 512UL -/* The smallest [rt]xq_entries that the driver supports. Callers of - * efx_wake_queue() assume that they can subsequently send at least one - * skb. Falcon/A1 may require up to three descriptors per skb_frag. */ -#define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS)) +/* Maximum number of TCP segments we support for soft-TSO */ +#define EFX_TSO_MAX_SEGS 100 + +/* The smallest [rt]xq_entries that the driver supports. RX minimum + * is a bit arbitrary. For TX, we must have space for at least 2 + * TSO skbs. + */ +#define EFX_RXQ_MIN_ENT 128U +#define EFX_TXQ_MIN_ENT(efx) (2 * efx_tx_max_skb_descs(efx)) /* Filters */ extern int efx_probe_filters(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index f22f45f515a8..b7b37d46a605 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -680,21 +680,27 @@ static int efx_ethtool_set_ringparam(struct net_device *net_dev, struct ethtool_ringparam *ring) { struct efx_nic *efx = netdev_priv(net_dev); + u32 txq_entries; if (ring->rx_mini_pending || ring->rx_jumbo_pending || ring->rx_pending > EFX_MAX_DMAQ_SIZE || ring->tx_pending > EFX_MAX_DMAQ_SIZE) return -EINVAL; - if (ring->rx_pending < EFX_MIN_RING_SIZE || - ring->tx_pending < EFX_MIN_RING_SIZE) { + if (ring->rx_pending < EFX_RXQ_MIN_ENT) { netif_err(efx, drv, efx->net_dev, - "TX and RX queues cannot be smaller than %ld\n", - EFX_MIN_RING_SIZE); + "RX queues cannot be smaller than %u\n", + EFX_RXQ_MIN_ENT); return -EINVAL; } - return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending); + txq_entries = max(ring->tx_pending, EFX_TXQ_MIN_ENT(efx)); + if (txq_entries != ring->tx_pending) + netif_warn(efx, drv, efx->net_dev, + "increasing TX queue size to minimum of %u\n", + txq_entries); + + return efx_realloc_channels(efx, ring->rx_pending, txq_entries); } static int efx_ethtool_set_pauseparam(struct net_device *net_dev, diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 94d0365b31cd..305430da48fb 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -119,6 +119,25 @@ efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr) return len; } +unsigned int efx_tx_max_skb_descs(struct efx_nic *efx) +{ + /* Header and payload descriptor for each output segment, plus + * one for every input fragment boundary within a segment + */ + unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS; + + /* Possibly one more per segment for the alignment workaround */ + if (EFX_WORKAROUND_5391(efx)) + max_descs += EFX_TSO_MAX_SEGS; + + /* Possibly more for PCIe page boundaries within input fragments */ + if (PAGE_SIZE > EFX_PAGE_SIZE) + max_descs += max_t(unsigned int, MAX_SKB_FRAGS, + DIV_ROUND_UP(GSO_MAX_SIZE, EFX_PAGE_SIZE)); + + return max_descs; +} + /* * Add a socket buffer to a TX queue * -- GitLab From 4658b24b2dd0e4c6215db2203743fa999765e8a0 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 30 Jul 2012 16:11:42 +0000 Subject: [PATCH 0357/1799] tcp: Apply device TSO segment limit earlier [ Upstream commit 1485348d2424e1131ea42efc033cbd9366462b01 ] Cache the device gso_max_segs in sock::sk_gso_max_segs and use it to limit the size of TSO skbs. This avoids the need to fall back to software GSO for local TCP senders. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/sock.h | 2 ++ net/core/sock.c | 1 + net/ipv4/tcp.c | 4 +++- net/ipv4/tcp_cong.c | 3 ++- net/ipv4/tcp_output.c | 21 ++++++++++++--------- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 5a0a58ac4126..5878118e3ce6 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -216,6 +216,7 @@ struct cg_proto; * @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK) * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) * @sk_gso_max_size: Maximum GSO segment size to build + * @sk_gso_max_segs: Maximum number of GSO segments * @sk_lingertime: %SO_LINGER l_linger setting * @sk_backlog: always used with the per-socket spinlock held * @sk_callback_lock: used with the callbacks in the end of this struct @@ -335,6 +336,7 @@ struct sock { netdev_features_t sk_route_nocaps; int sk_gso_type; unsigned int sk_gso_max_size; + u16 sk_gso_max_segs; int sk_rcvlowat; unsigned long sk_lingertime; struct sk_buff_head sk_error_queue; diff --git a/net/core/sock.c b/net/core/sock.c index 0f8402ea434b..d3e0a5201d47 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1411,6 +1411,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst) } else { sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; sk->sk_gso_max_size = dst->dev->gso_max_size; + sk->sk_gso_max_segs = dst->dev->gso_max_segs; } } } diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index d6feb1ef4f2a..367bdaf9a56f 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -740,7 +740,9 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, old_size_goal + mss_now > xmit_size_goal)) { xmit_size_goal = old_size_goal; } else { - tp->xmit_size_goal_segs = xmit_size_goal / mss_now; + tp->xmit_size_goal_segs = + min_t(u16, xmit_size_goal / mss_now, + sk->sk_gso_max_segs); xmit_size_goal = tp->xmit_size_goal_segs * mss_now; } } diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 272a84593c85..69251dde7501 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -291,7 +291,8 @@ int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight) left = tp->snd_cwnd - in_flight; if (sk_can_gso(sk) && left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && - left * tp->mss_cache < sk->sk_gso_max_size) + left * tp->mss_cache < sk->sk_gso_max_size && + left < sk->sk_gso_max_segs) return 1; return left <= tcp_max_tso_deferred_mss(tp); } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 7ac6423117ad..2d27e1af9303 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1318,21 +1318,21 @@ static void tcp_cwnd_validate(struct sock *sk) * when we would be allowed to send the split-due-to-Nagle skb fully. */ static unsigned int tcp_mss_split_point(const struct sock *sk, const struct sk_buff *skb, - unsigned int mss_now, unsigned int cwnd) + unsigned int mss_now, unsigned int max_segs) { const struct tcp_sock *tp = tcp_sk(sk); - u32 needed, window, cwnd_len; + u32 needed, window, max_len; window = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq; - cwnd_len = mss_now * cwnd; + max_len = mss_now * max_segs; - if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk))) - return cwnd_len; + if (likely(max_len <= window && skb != tcp_write_queue_tail(sk))) + return max_len; needed = min(skb->len, window); - if (cwnd_len <= needed) - return cwnd_len; + if (max_len <= needed) + return max_len; return needed - needed % mss_now; } @@ -1560,7 +1560,8 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) limit = min(send_win, cong_win); /* If a full-sized TSO skb can be sent, do it. */ - if (limit >= sk->sk_gso_max_size) + if (limit >= min_t(unsigned int, sk->sk_gso_max_size, + sk->sk_gso_max_segs * tp->mss_cache)) goto send_now; /* Middle in queue won't get any more data, full sendable already? */ @@ -1786,7 +1787,9 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, limit = mss_now; if (tso_segs > 1 && !tcp_urg_mode(tp)) limit = tcp_mss_split_point(sk, skb, mss_now, - cwnd_quota); + min_t(unsigned int, + cwnd_quota, + sk->sk_gso_max_segs)); if (skb->len > limit && unlikely(tso_fragment(sk, skb, limit, mss_now, gfp))) -- GitLab From 7e0c71a9a5a23f9433eac1d0aabbc9d54da3428b Mon Sep 17 00:00:00 2001 From: Hiroaki SHIMODA Date: Fri, 3 Aug 2012 19:57:52 +0900 Subject: [PATCH 0358/1799] net_sched: gact: Fix potential panic in tcf_gact(). [ Upstream commit 696ecdc10622d86541f2e35cc16e15b6b3b1b67e ] gact_rand array is accessed by gact->tcfg_ptype whose value is assumed to less than MAX_RAND, but any range checks are not performed. So add a check in tcf_gact_init(). And in tcf_gact(), we can reduce a branch. Signed-off-by: Hiroaki SHIMODA Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/act_gact.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index b77f5a06a658..bdacd8df318c 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c @@ -67,6 +67,9 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, struct tcf_common *pc; int ret = 0; int err; +#ifdef CONFIG_GACT_PROB + struct tc_gact_p *p_parm = NULL; +#endif if (nla == NULL) return -EINVAL; @@ -82,6 +85,12 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, #ifndef CONFIG_GACT_PROB if (tb[TCA_GACT_PROB] != NULL) return -EOPNOTSUPP; +#else + if (tb[TCA_GACT_PROB]) { + p_parm = nla_data(tb[TCA_GACT_PROB]); + if (p_parm->ptype >= MAX_RAND) + return -EINVAL; + } #endif pc = tcf_hash_check(parm->index, a, bind, &gact_hash_info); @@ -103,8 +112,7 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, spin_lock_bh(&gact->tcf_lock); gact->tcf_action = parm->action; #ifdef CONFIG_GACT_PROB - if (tb[TCA_GACT_PROB] != NULL) { - struct tc_gact_p *p_parm = nla_data(tb[TCA_GACT_PROB]); + if (p_parm) { gact->tcfg_paction = p_parm->paction; gact->tcfg_pval = p_parm->pval; gact->tcfg_ptype = p_parm->ptype; @@ -133,7 +141,7 @@ static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, spin_lock(&gact->tcf_lock); #ifdef CONFIG_GACT_PROB - if (gact->tcfg_ptype && gact_rand[gact->tcfg_ptype] != NULL) + if (gact->tcfg_ptype) action = gact_rand[gact->tcfg_ptype](gact); else action = gact->tcf_action; -- GitLab From bc3f72433351e278a92a38c2090aacff982ce558 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Thu, 2 Aug 2012 23:10:01 +0000 Subject: [PATCH 0359/1799] isdnloop: fix and simplify isdnloop_init() [ Upstream commit 77f00f6324cb97cf1df6f9c4aaeea6ada23abdb2 ] Fix a buffer overflow bug by removing the revision and printk. [ 22.016214] isdnloop-ISDN-driver Rev 1.11.6.7 [ 22.097508] isdnloop: (loop0) virtual card added [ 22.174400] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff83244972 [ 22.174400] [ 22.436157] Pid: 1, comm: swapper Not tainted 3.5.0-bisect-00018-gfa8bbb1-dirty #129 [ 22.624071] Call Trace: [ 22.720558] [] ? CallcNew+0x56/0x56 [ 22.815248] [] panic+0x110/0x329 [ 22.914330] [] ? isdnloop_init+0xaf/0xb1 [ 23.014800] [] ? CallcNew+0x56/0x56 [ 23.090763] [] __stack_chk_fail+0x2b/0x30 [ 23.185748] [] isdnloop_init+0xaf/0xb1 Signed-off-by: Fengguang Wu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/isdnloop/isdnloop.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index 5405ec644db3..baf2686aa8eb 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -16,7 +16,6 @@ #include #include "isdnloop.h" -static char *revision = "$Revision: 1.11.6.7 $"; static char *isdnloop_id = "loop0"; MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card"); @@ -1494,17 +1493,6 @@ isdnloop_addcard(char *id1) static int __init isdnloop_init(void) { - char *p; - char rev[10]; - - if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 1); - p = strchr(rev, '$'); - *p = 0; - } else - strcpy(rev, " ??? "); - printk(KERN_NOTICE "isdnloop-ISDN-driver Rev%s\n", rev); - if (isdnloop_id) return (isdnloop_addcard(isdnloop_id)); -- GitLab From a348ed02b367a8a8307444724db5c8e96c90ac78 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Tue, 7 Aug 2012 00:23:11 +0000 Subject: [PATCH 0360/1799] pptp: lookup route with the proper net namespace [ Upstream commit 08252b32311c3fa84219ad794d640af7399b5485 ] pptp always use init_net as the net namespace to lookup route, this will cause route lookup failed in container. because we already set the correct net namespace to struct sock in pptp_create,so fix this by using sock_net(sk) to replace &init_net. Signed-off-by: Gao feng Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ppp/pptp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 885dbdd9c39e..f617566bbbae 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -189,7 +189,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) if (sk_pppox(po)->sk_state & PPPOX_DEAD) goto tx_error; - rt = ip_route_output_ports(&init_net, &fl4, NULL, + rt = ip_route_output_ports(sock_net(sk), &fl4, NULL, opt->dst_addr.sin_addr.s_addr, opt->src_addr.sin_addr.s_addr, 0, 0, IPPROTO_GRE, @@ -468,7 +468,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, po->chan.private = sk; po->chan.ops = &pptp_chan_ops; - rt = ip_route_output_ports(&init_net, &fl4, sk, + rt = ip_route_output_ports(sock_net(sk), &fl4, sk, opt->dst_addr.sin_addr.s_addr, opt->src_addr.sin_addr.s_addr, 0, 0, -- GitLab From caf2630c41a183b72e5d6211e5efd1457ac0c463 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Wed, 8 Aug 2012 00:33:25 +0000 Subject: [PATCH 0361/1799] net/core: Fix potential memory leak in dev_set_alias() [ Upstream commit 7364e445f62825758fa61195d237a5b8ecdd06ec ] Do not leak memory by updating pointer with potentially NULL realloc return value. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 665730f06f30..a1e0355908ef 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1056,6 +1056,8 @@ int dev_change_name(struct net_device *dev, const char *newname) */ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) { + char *new_ifalias; + ASSERT_RTNL(); if (len >= IFALIASZ) @@ -1069,9 +1071,10 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) return 0; } - dev->ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL); - if (!dev->ifalias) + new_ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL); + if (!new_ifalias) return -ENOMEM; + dev->ifalias = new_ifalias; strlcpy(dev->ifalias, alias, len+1); return len; -- GitLab From c8cca9d90b953a0a2b5d0edab789f5c52ae983f5 Mon Sep 17 00:00:00 2001 From: "danborkmann@iogearbox.net" Date: Fri, 10 Aug 2012 22:48:54 +0000 Subject: [PATCH 0362/1799] af_packet: remove BUG statement in tpacket_destruct_skb [ Upstream commit 7f5c3e3a80e6654cf48dfba7cf94f88c6b505467 ] Here's a quote of the comment about the BUG macro from asm-generic/bug.h: Don't use BUG() or BUG_ON() unless there's really no way out; one example might be detecting data structure corruption in the middle of an operation that can't be backed out of. If the (sub)system can somehow continue operating, perhaps with reduced functionality, it's probably not BUG-worthy. If you're tempted to BUG(), think again: is completely giving up really the *only* solution? There are usually better options, where users don't need to reboot ASAP and can mostly shut down cleanly. In our case, the status flag of a ring buffer slot is managed from both sides, the kernel space and the user space. This means that even though the kernel side might work as expected, the user space screws up and changes this flag right between the send(2) is triggered when the flag is changed to TP_STATUS_SENDING and a given skb is destructed after some time. Then, this will hit the BUG macro. As David suggested, the best solution is to simply remove this statement since it cannot be used for kernel side internal consistency checks. I've tested it and the system still behaves /stable/ in this case, so in accordance with the above comment, we should rather remove it. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/packet/af_packet.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 4f2c0df79563..cd0d9bb20910 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1943,7 +1943,6 @@ static void tpacket_destruct_skb(struct sk_buff *skb) if (likely(po->tx_ring.pg_vec)) { ph = skb_shinfo(skb)->destructor_arg; - BUG_ON(__packet_get_status(po, ph) != TP_STATUS_SENDING); BUG_ON(atomic_read(&po->tx_ring.pending) == 0); atomic_dec(&po->tx_ring.pending); __packet_set_status(po, ph, TP_STATUS_AVAILABLE); -- GitLab From 84a2d3c44cce71152f3555af83bafea6ec5ef23c Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 14 Aug 2012 08:54:51 +0000 Subject: [PATCH 0363/1799] ipv6: addrconf: Avoid calling netdevice notifiers with RCU read-side lock [ Upstream commit 4acd4945cd1e1f92b20d14e349c6c6a52acbd42d ] Cong Wang reports that lockdep detected suspicious RCU usage while enabling IPV6 forwarding: [ 1123.310275] =============================== [ 1123.442202] [ INFO: suspicious RCU usage. ] [ 1123.558207] 3.6.0-rc1+ #109 Not tainted [ 1123.665204] ------------------------------- [ 1123.768254] include/linux/rcupdate.h:430 Illegal context switch in RCU read-side critical section! [ 1123.992320] [ 1123.992320] other info that might help us debug this: [ 1123.992320] [ 1124.307382] [ 1124.307382] rcu_scheduler_active = 1, debug_locks = 0 [ 1124.522220] 2 locks held by sysctl/5710: [ 1124.648364] #0: (rtnl_mutex){+.+.+.}, at: [] rtnl_trylock+0x15/0x17 [ 1124.882211] #1: (rcu_read_lock){.+.+.+}, at: [] rcu_lock_acquire+0x0/0x29 [ 1125.085209] [ 1125.085209] stack backtrace: [ 1125.332213] Pid: 5710, comm: sysctl Not tainted 3.6.0-rc1+ #109 [ 1125.441291] Call Trace: [ 1125.545281] [] lockdep_rcu_suspicious+0x109/0x112 [ 1125.667212] [] rcu_preempt_sleep_check+0x45/0x47 [ 1125.781838] [] __might_sleep+0x1e/0x19b [...] [ 1127.445223] [] call_netdevice_notifiers+0x4a/0x4f [...] [ 1127.772188] [] dev_disable_lro+0x32/0x6b [ 1127.885174] [] dev_forward_change+0x30/0xcb [ 1128.013214] [] addrconf_forward_change+0x85/0xc5 [...] addrconf_forward_change() uses RCU iteration over the netdev list, which is unnecessary since it already holds the RTNL lock. We also cannot reasonably require netdevice notifier functions not to sleep. Reported-by: Cong Wang Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/addrconf.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 7d5cb975cc6f..2c69eca4b61a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -493,8 +493,7 @@ static void addrconf_forward_change(struct net *net, __s32 newf) struct net_device *dev; struct inet6_dev *idev; - rcu_read_lock(); - for_each_netdev_rcu(net, dev) { + for_each_netdev(net, dev) { idev = __in6_dev_get(dev); if (idev) { int changed = (!idev->cnf.forwarding) ^ (!newf); @@ -503,7 +502,6 @@ static void addrconf_forward_change(struct net *net, __s32 newf) dev_forward_change(idev); } } - rcu_read_unlock(); } static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) -- GitLab From 5b26dbdd5f22871c21fc2ea4afedfe4ecad62d72 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:44 +0000 Subject: [PATCH 0364/1799] atm: fix info leak in getsockopt(SO_ATMPVC) [ Upstream commit e862f1a9b7df4e8196ebec45ac62295138aa3fc2 ] The ATM code fails to initialize the two padding bytes of struct sockaddr_atmpvc inserted for alignment. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/atm/common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/atm/common.c b/net/atm/common.c index b4b44dbed645..0c0ad930a632 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -812,6 +812,7 @@ int vcc_getsockopt(struct socket *sock, int level, int optname, if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags)) return -ENOTCONN; + memset(&pvc, 0, sizeof(pvc)); pvc.sap_family = AF_ATMPVC; pvc.sap_addr.itf = vcc->dev->number; pvc.sap_addr.vpi = vcc->vpi; -- GitLab From 458ed5622e976848aacdea07d4bfcb84a350c460 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:45 +0000 Subject: [PATCH 0365/1799] atm: fix info leak via getsockname() [ Upstream commit 3c0c5cfdcd4d69ffc4b9c0907cec99039f30a50a ] The ATM code fails to initialize the two padding bytes of struct sockaddr_atmpvc inserted for alignment. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/atm/pvc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/atm/pvc.c b/net/atm/pvc.c index 3a734919c36c..ae0324021407 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c @@ -95,6 +95,7 @@ static int pvc_getname(struct socket *sock, struct sockaddr *sockaddr, return -ENOTCONN; *sockaddr_len = sizeof(struct sockaddr_atmpvc); addr = (struct sockaddr_atmpvc *)sockaddr; + memset(addr, 0, sizeof(*addr)); addr->sap_family = AF_ATMPVC; addr->sap_addr.itf = vcc->dev->number; addr->sap_addr.vpi = vcc->vpi; -- GitLab From 87c42a1dfd5939d0a24795cd99b3d63daa4e1eff Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:46 +0000 Subject: [PATCH 0366/1799] Bluetooth: HCI - Fix info leak in getsockopt(HCI_FILTER) [ Upstream commit e15ca9a0ef9a86f0477530b0f44a725d67f889ee ] The HCI code fails to initialize the two padding bytes of struct hci_ufilter before copying it to userland -- that for leaking two bytes kernel stack. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Cc: Marcel Holtmann Cc: Gustavo Padovan Cc: Johan Hedberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hci_sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 5914623f426a..2f6ab5b8f214 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -1016,6 +1016,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char { struct hci_filter *f = &hci_pi(sk)->filter; + memset(&uf, 0, sizeof(uf)); uf.type_mask = f->type_mask; uf.opcode = f->opcode; uf.event_mask[0] = *((u32 *) f->event_mask + 0); -- GitLab From 639edee79eb2035b6fe3976f50a1c5364acc7352 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:47 +0000 Subject: [PATCH 0367/1799] Bluetooth: HCI - Fix info leak via getsockname() [ Upstream commit 3f68ba07b1da811bf383b4b701b129bfcb2e4988 ] The HCI code fails to initialize the hci_channel member of struct sockaddr_hci and that for leaks two bytes kernel stack via the getsockname() syscall. Initialize hci_channel with 0 to avoid the info leak. Signed-off-by: Mathias Krause Cc: Marcel Holtmann Cc: Gustavo Padovan Cc: Johan Hedberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hci_sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 2f6ab5b8f214..bedc768c8cdf 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -706,6 +706,7 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *add *addr_len = sizeof(*haddr); haddr->hci_family = AF_BLUETOOTH; haddr->hci_dev = hdev->id; + haddr->hci_channel= 0; release_sock(sk); return 0; -- GitLab From 745dcdb0fd330f0cc984bd8a7764a81f04e44780 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:48 +0000 Subject: [PATCH 0368/1799] Bluetooth: RFCOMM - Fix info leak in getsockopt(BT_SECURITY) [ Upstream commit 9ad2de43f1aee7e7274a4e0d41465489299e344b ] The RFCOMM code fails to initialize the key_size member of struct bt_security before copying it to userland -- that for leaking one byte kernel stack. Initialize key_size with 0 to avoid the info leak. Signed-off-by: Mathias Krause Cc: Marcel Holtmann Cc: Gustavo Padovan Cc: Johan Hedberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/rfcomm/sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index a55a43e9f70e..dfa3dd96106b 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -836,6 +836,7 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c } sec.level = rfcomm_pi(sk)->sec_level; + sec.key_size = 0; len = min_t(unsigned int, len, sizeof(sec)); if (copy_to_user(optval, (char *) &sec, len)) -- GitLab From 279d3f5b2d402034dee1a81b7f5e3f678aa46d21 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:49 +0000 Subject: [PATCH 0369/1799] Bluetooth: RFCOMM - Fix info leak in ioctl(RFCOMMGETDEVLIST) [ Upstream commit f9432c5ec8b1e9a09b9b0e5569e3c73db8de432a ] The RFCOMM code fails to initialize the two padding bytes of struct rfcomm_dev_list_req inserted for alignment before copying it to userland. Additionally there are two padding bytes in each instance of struct rfcomm_dev_info. The ioctl() that for disclosures two bytes plus dev_num times two bytes uninitialized kernel heap memory. Allocate the memory using kzalloc() to fix this issue. Signed-off-by: Mathias Krause Cc: Marcel Holtmann Cc: Gustavo Padovan Cc: Johan Hedberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/rfcomm/tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 4bf54b377255..95a0f60fc6e0 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -467,7 +467,7 @@ static int rfcomm_get_dev_list(void __user *arg) size = sizeof(*dl) + dev_num * sizeof(*di); - dl = kmalloc(size, GFP_KERNEL); + dl = kzalloc(size, GFP_KERNEL); if (!dl) return -ENOMEM; -- GitLab From 8717cd3d63233ee5591bf8e8d6e5960a1f6252b1 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:50 +0000 Subject: [PATCH 0370/1799] Bluetooth: RFCOMM - Fix info leak via getsockname() [ Upstream commit 9344a972961d1a6d2c04d9008b13617bcb6ec2ef ] The RFCOMM code fails to initialize the trailing padding byte of struct sockaddr_rc added for alignment. It that for leaks one byte kernel stack via the getsockname() syscall. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Cc: Marcel Holtmann Cc: Gustavo Padovan Cc: Johan Hedberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/rfcomm/sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index dfa3dd96106b..717c43ac0c78 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -546,6 +546,7 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int * BT_DBG("sock %p, sk %p", sock, sk); + memset(sa, 0, sizeof(*sa)); sa->rc_family = AF_BLUETOOTH; sa->rc_channel = rfcomm_pi(sk)->channel; if (peer) -- GitLab From dbcba7a54a0327f0ef6d6a3ec53b67d0969109b6 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:51 +0000 Subject: [PATCH 0371/1799] Bluetooth: L2CAP - Fix info leak via getsockname() [ Upstream commit 792039c73cf176c8e39a6e8beef2c94ff46522ed ] The L2CAP code fails to initialize the l2_bdaddr_type member of struct sockaddr_l2 and the padding byte added for alignment. It that for leaks two bytes kernel stack via the getsockname() syscall. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Cc: Marcel Holtmann Cc: Gustavo Padovan Cc: Johan Hedberg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/l2cap_sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 04e7c172d49c..615b26e0650f 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -242,6 +242,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l BT_DBG("sock %p, sk %p", sock, sk); + memset(la, 0, sizeof(struct sockaddr_l2)); addr->sa_family = AF_BLUETOOTH; *len = sizeof(struct sockaddr_l2); -- GitLab From 00ed5b8f397447a944a3305274b74049bfcd633f Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:53 +0000 Subject: [PATCH 0372/1799] llc: fix info leak via getsockname() [ Upstream commit 3592aaeb80290bda0f2cf0b5456c97bfc638b192 ] The LLC code wrongly returns 0, i.e. "success", when the socket is zapped. Together with the uninitialized uaddrlen pointer argument from sys_getsockname this leads to an arbitrary memory leak of up to 128 bytes kernel stack via the getsockname() syscall. Return an error instead when the socket is zapped to prevent the info leak. Also remove the unnecessary memset(0). We don't directly write to the memory pointed by uaddr but memcpy() a local structure at the end of the function that is properly initialized. Signed-off-by: Mathias Krause Cc: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/llc/af_llc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index b9bef2c75026..df08d7779e1d 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -971,14 +971,13 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr, struct sockaddr_llc sllc; struct sock *sk = sock->sk; struct llc_sock *llc = llc_sk(sk); - int rc = 0; + int rc = -EBADF; memset(&sllc, 0, sizeof(sllc)); lock_sock(sk); if (sock_flag(sk, SOCK_ZAPPED)) goto out; *uaddrlen = sizeof(sllc); - memset(uaddr, 0, *uaddrlen); if (peer) { rc = -ENOTCONN; if (sk->sk_state != TCP_ESTABLISHED) -- GitLab From 59039dc90bb7879bd4c8c959109d27131f0ce40f Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:55 +0000 Subject: [PATCH 0373/1799] dccp: fix info leak via getsockopt(DCCP_SOCKOPT_CCID_TX_INFO) [ Upstream commit 7b07f8eb75aa3097cdfd4f6eac3da49db787381d ] The CCID3 code fails to initialize the trailing padding bytes of struct tfrc_tx_info added for alignment on 64 bit architectures. It that for potentially leaks four bytes kernel stack via the getsockopt() syscall. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Cc: Gerrit Renker Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/dccp/ccids/ccid3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 70bfaf2d1965..b658f3b8a23c 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -531,6 +531,7 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, case DCCP_SOCKOPT_CCID_TX_INFO: if (len < sizeof(tfrc)) return -EINVAL; + memset(&tfrc, 0, sizeof(tfrc)); tfrc.tfrctx_x = hc->tx_x; tfrc.tfrctx_x_recv = hc->tx_x_recv; tfrc.tfrctx_x_calc = hc->tx_x_calc; -- GitLab From 62b4d90b525c6c11e467a2eadb12fcf64a6f0829 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:56 +0000 Subject: [PATCH 0374/1799] ipvs: fix info leak in getsockopt(IP_VS_SO_GET_TIMEOUT) [ Upstream commit 2d8a041b7bfe1097af21441cb77d6af95f4f4680 ] If at least one of CONFIG_IP_VS_PROTO_TCP or CONFIG_IP_VS_PROTO_UDP is not set, __ip_vs_get_timeouts() does not fully initialize the structure that gets copied to userland and that for leaks up to 12 bytes of kernel stack. Add an explicit memset(0) before passing the structure to __ip_vs_get_timeouts() to avoid the info leak. Signed-off-by: Mathias Krause Cc: Wensong Zhang Cc: Simon Horman Cc: Julian Anastasov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/netfilter/ipvs/ip_vs_ctl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index f5589987fc80..97e73806bacc 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2713,6 +2713,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) { struct ip_vs_timeout_user t; + memset(&t, 0, sizeof(t)); __ip_vs_get_timeouts(net, &t); if (copy_to_user(user, &t, sizeof(t)) != 0) ret = -EFAULT; -- GitLab From d09b3b2b1183848e287bc0b6397f8d05945becc4 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Aug 2012 11:31:57 +0000 Subject: [PATCH 0375/1799] net: fix info leak in compat dev_ifconf() [ Upstream commit 43da5f2e0d0c69ded3d51907d9552310a6b545e8 ] The implementation of dev_ifconf() for the compat ioctl interface uses an intermediate ifc structure allocated in userland for the duration of the syscall. Though, it fails to initialize the padding bytes inserted for alignment and that for leaks four bytes of kernel stack. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Mathias Krause Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/socket.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/socket.c b/net/socket.c index 06ffa0f28398..dab317686ad3 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2658,6 +2658,7 @@ static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) return -EFAULT; + memset(&ifc, 0, sizeof(ifc)); if (ifc32.ifcbuf == 0) { ifc32.ifc_len = 0; ifc.ifc_len = 0; -- GitLab From 9e296becde8a8da5bcc1a8e22f27bdf9bd8636fe Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Thu, 16 Aug 2012 22:02:58 +0000 Subject: [PATCH 0376/1799] af_packet: don't emit packet on orig fanout group [ Upstream commit c0de08d04215031d68fa13af36f347a6cfa252ca ] If a packet is emitted on one socket in one group of fanout sockets, it is transmitted again. It is thus read again on one of the sockets of the fanout group. This result in a loop for software which generate packets when receiving one. This retransmission is not the intended behavior: a fanout group must behave like a single socket. The packet should not be transmitted on a socket if it originates from a socket belonging to the same fanout group. This patch fixes the issue by changing the transmission check to take fanout group info account. Reported-by: Aleksandr Kotov Signed-off-by: Eric Leblond Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/netdevice.h | 2 ++ net/core/dev.c | 16 ++++++++++++++-- net/packet/af_packet.c | 9 +++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 79596d6dd853..e517695704cc 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1496,6 +1496,8 @@ struct packet_type { struct sk_buff **(*gro_receive)(struct sk_buff **head, struct sk_buff *skb); int (*gro_complete)(struct sk_buff *skb); + bool (*id_match)(struct packet_type *ptype, + struct sock *sk); void *af_packet_priv; struct list_head list; }; diff --git a/net/core/dev.c b/net/core/dev.c index a1e0355908ef..40d5ab15befa 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1641,6 +1641,19 @@ static inline int deliver_skb(struct sk_buff *skb, return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); } +static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb) +{ + if (ptype->af_packet_priv == NULL) + return false; + + if (ptype->id_match) + return ptype->id_match(ptype, skb->sk); + else if ((struct sock *)ptype->af_packet_priv == skb->sk) + return true; + + return false; +} + /* * Support routine. Sends outgoing frames to any network * taps currently in use. @@ -1658,8 +1671,7 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) * they originated from - MvS (miquels@drinkel.ow.org) */ if ((ptype->dev == dev || !ptype->dev) && - (ptype->af_packet_priv == NULL || - (struct sock *)ptype->af_packet_priv != skb->sk)) { + (!skb_loop_sk(ptype, skb))) { if (pt_prev) { deliver_skb(skb2, pt_prev, skb->dev); pt_prev = ptype; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index cd0d9bb20910..078fdffcd556 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1280,6 +1280,14 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po) spin_unlock(&f->lock); } +bool match_fanout_group(struct packet_type *ptype, struct sock * sk) +{ + if (ptype->af_packet_priv == (void*)((struct packet_sock *)sk)->fanout) + return true; + + return false; +} + static int fanout_add(struct sock *sk, u16 id, u16 type_flags) { struct packet_sock *po = pkt_sk(sk); @@ -1332,6 +1340,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) match->prot_hook.dev = po->prot_hook.dev; match->prot_hook.func = packet_rcv_fanout; match->prot_hook.af_packet_priv = match; + match->prot_hook.id_match = match_fanout_group; dev_add_pack(&match->prot_hook); list_add(&match->list, &fanout_list); } -- GitLab From 7c799a1e1ca2bc766574078b684c14474da9f704 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 21 Aug 2012 06:21:17 +0000 Subject: [PATCH 0377/1799] af_netlink: force credentials passing [CVE-2012-3520] [ Upstream commit e0e3cea46d31d23dc40df0a49a7a2c04fe8edfea ] Pablo Neira Ayuso discovered that avahi and potentially NetworkManager accept spoofed Netlink messages because of a kernel bug. The kernel passes all-zero SCM_CREDENTIALS ancillary data to the receiver if the sender did not provide such data, instead of not including any such data at all or including the correct data from the peer (as it is the case with AF_UNIX). This bug was introduced in commit 16e572626961 (af_unix: dont send SCM_CREDENTIALS by default) This patch forces passing credentials for netlink, as before the regression. Another fix would be to not add SCM_CREDENTIALS in netlink messages if not provided by the sender, but it might break some programs. With help from Florian Weimer & Petr Matousek This issue is designated as CVE-2012-3520 Signed-off-by: Eric Dumazet Cc: Petr Matousek Cc: Florian Weimer Cc: Pablo Neira Ayuso Signed-off-by: David S. Miller --- include/net/scm.h | 4 +++- net/netlink/af_netlink.c | 2 +- net/unix/af_unix.c | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/net/scm.h b/include/net/scm.h index d456f4c71a32..0c0017ce23bb 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -71,9 +71,11 @@ 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 scm_cookie *scm, bool forcecreds) { memset(scm, 0, sizeof(*scm)); + if (forcecreds) + scm_set_cred(scm, task_tgid(current), current_cred()); unix_get_peersec_dgram(sock, scm); if (msg->msg_controllen <= 0) return 0; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index faa48f70b7c9..59debb73ba75 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1329,7 +1329,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, if (NULL == siocb->scm) siocb->scm = &scm; - err = scm_send(sock, msg, siocb->scm); + err = scm_send(sock, msg, siocb->scm, true); if (err < 0) return err; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index d510353ef431..109e30beaa69 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1446,7 +1446,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, if (NULL == siocb->scm) siocb->scm = &tmp_scm; wait_for_unix_gc(); - err = scm_send(sock, msg, siocb->scm); + err = scm_send(sock, msg, siocb->scm, false); if (err < 0) return err; @@ -1607,7 +1607,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, if (NULL == siocb->scm) siocb->scm = &tmp_scm; wait_for_unix_gc(); - err = scm_send(sock, msg, siocb->scm); + err = scm_send(sock, msg, siocb->scm, false); if (err < 0) return err; -- GitLab From 912af4d4433a29aa51bcbc33c4275541d8ccc4b1 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 23 Aug 2012 02:09:11 +0000 Subject: [PATCH 0378/1799] netlink: fix possible spoofing from non-root processes [ Upstream commit 20e1db19db5d6b9e4e83021595eab0dc8f107bef ] Non-root user-space processes can send Netlink messages to other processes that are well-known for being subscribed to Netlink asynchronous notifications. This allows ilegitimate non-root process to send forged messages to Netlink subscribers. The userspace process usually verifies the legitimate origin in two ways: a) Socket credentials. If UID != 0, then the message comes from some ilegitimate process and the message needs to be dropped. b) Netlink portID. In general, portID == 0 means that the origin of the messages comes from the kernel. Thus, discarding any message not coming from the kernel. However, ctnetlink sets the portID in event messages that has been triggered by some user-space process, eg. conntrack utility. So other processes subscribed to ctnetlink events, eg. conntrackd, know that the event was triggered by some user-space action. Neither of the two ways to discard ilegitimate messages coming from non-root processes can help for ctnetlink. This patch adds capability validation in case that dst_pid is set in netlink_sendmsg(). This approach is aggressive since existing applications using any Netlink bus to deliver messages between two user-space processes will break. Note that the exception is NETLINK_USERSOCK, since it is reserved for netlink-to-netlink userspace communication. Still, if anyone wants that his Netlink bus allows netlink-to-netlink userspace, then they can set NL_NONROOT_SEND. However, by default, I don't think it makes sense to allow to use NETLINK_ROUTE to communicate two processes that are sending no matter what information that is not related to link/neighbouring/routing. They should be using NETLINK_USERSOCK instead for that. Signed-off-by: Pablo Neira Ayuso Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 59debb73ba75..bba6ba176abd 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1340,7 +1340,8 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, dst_pid = addr->nl_pid; dst_group = ffs(addr->nl_groups); err = -EPERM; - if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND)) + if ((dst_group || dst_pid) && + !netlink_capable(sock, NL_NONROOT_SEND)) goto out; } else { dst_pid = nlk->dst_pid; @@ -2115,6 +2116,7 @@ static void __init netlink_add_usersock_entry(void) rcu_assign_pointer(nl_table[NETLINK_USERSOCK].listeners, listeners); nl_table[NETLINK_USERSOCK].module = THIS_MODULE; nl_table[NETLINK_USERSOCK].registered = 1; + nl_table[NETLINK_USERSOCK].nl_nonroot = NL_NONROOT_SEND; netlink_table_ungrab(); } -- GitLab From fbc350126994de9682e0400b969ab84437768894 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Thu, 23 Aug 2012 07:05:17 +0000 Subject: [PATCH 0379/1799] tcp: fix cwnd reduction for non-sack recovery [ Upstream commit 7c4a56fec379ac0d7754e0d4da6a7361f1a4fe64 ] The cwnd reduction in fast recovery is based on the number of packets newly delivered per ACK. For non-sack connections every DUPACK signifies a packet has been delivered, but the sender mistakenly skips counting them for cwnd reduction. The fix is to compute newly_acked_sacked after DUPACKs are accounted in sacked_out for non-sack connections. Signed-off-by: Yuchung Cheng Acked-by: Nandita Dukkipati Acked-by: Neal Cardwell Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 56a9c8d0bef1..3acebbd15ba0 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3037,13 +3037,14 @@ static void tcp_update_cwnd_in_recovery(struct sock *sk, int newly_acked_sacked, * tcp_xmit_retransmit_queue(). */ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, - int newly_acked_sacked, bool is_dupack, + int prior_sacked, bool is_dupack, int flag) { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); int do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) && (tcp_fackets_out(tp) > tp->reordering)); + int newly_acked_sacked = 0; int fast_rexmit = 0, mib_idx; if (WARN_ON(!tp->packets_out && tp->sacked_out)) @@ -3103,6 +3104,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, tcp_add_reno_sack(sk); } else do_lost = tcp_try_undo_partial(sk, pkts_acked); + newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; break; case TCP_CA_Loss: if (flag & FLAG_DATA_ACKED) @@ -3124,6 +3126,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, if (is_dupack) tcp_add_reno_sack(sk); } + newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; if (icsk->icsk_ca_state <= TCP_CA_Disorder) tcp_try_undo_dsack(sk); @@ -3695,7 +3698,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) int prior_packets; int prior_sacked = tp->sacked_out; int pkts_acked = 0; - int newly_acked_sacked = 0; int frto_cwnd = 0; /* If the ack is older than previous acks @@ -3768,8 +3770,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una); pkts_acked = prior_packets - tp->packets_out; - newly_acked_sacked = (prior_packets - prior_sacked) - - (tp->packets_out - tp->sacked_out); if (tp->frto_counter) frto_cwnd = tcp_process_frto(sk, flag); @@ -3783,7 +3783,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) tcp_may_raise_cwnd(sk, flag)) tcp_cong_avoid(sk, ack, prior_in_flight); is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); - tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, + tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, is_dupack, flag); } else { if ((flag & FLAG_DATA_ACKED) && !frto_cwnd) @@ -3798,7 +3798,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) no_queue: /* If data was DSACKed, see if we can undo a cwnd reduction. */ if (flag & FLAG_DSACKING_ACK) - tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, + tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, is_dupack, flag); /* If this ack opens up a zero window, clear backoff. It was * being used to time the probes, and is probably far higher than @@ -3818,8 +3818,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) */ if (TCP_SKB_CB(skb)->sacked) { flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una); - newly_acked_sacked = tp->sacked_out - prior_sacked; - tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, + tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, is_dupack, flag); } -- GitLab From fa1dcb6f0d338629cf1e3939227135ce0ea17b50 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 15 Aug 2012 18:09:15 +0100 Subject: [PATCH 0380/1799] sfc: Fix reporting of IPv4 full filters through ethtool [ Upstream commit ac70b2e9a13423b5efa0178e081936ce6979aea5 ] ETHTOOL_GRXCLSRULE returns filters for a TCP/IPv4 or UDP/IPv4 4-tuple with source and destination swapped. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index b7b37d46a605..ff64def0ffd7 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -863,8 +863,8 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx, &ip_entry->ip4dst, &ip_entry->pdst); if (rc != 0) { rc = efx_filter_get_ipv4_full( - &spec, &proto, &ip_entry->ip4src, &ip_entry->psrc, - &ip_entry->ip4dst, &ip_entry->pdst); + &spec, &proto, &ip_entry->ip4dst, &ip_entry->pdst, + &ip_entry->ip4src, &ip_entry->psrc); EFX_WARN_ON_PARANOID(rc); ip_mask->ip4src = ~0; ip_mask->psrc = ~0; -- GitLab From c5ca1d03c29df5dc550f71bd1669af8bc30e32f8 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Thu, 23 Aug 2012 21:46:25 +0000 Subject: [PATCH 0381/1799] gianfar: fix default tx vlan offload feature flag [ Upstream commit e2c53be223aca36cf93eb6a0f6bafa079e78f52b ] Commit - "b852b72 gianfar: fix bug caused by 87c288c6e9aa31720b72e2bc2d665e24e1653c3e" disables by default (on mac init) the hw vlan tag insertion. The "features" flags were not updated to reflect this, and "ethtool -K" shows tx-vlan-offload to be "on" by default. Cc: Sebastian Poehn Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 24381e1298e2..0819a7403847 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1037,7 +1037,7 @@ static int gfar_probe(struct platform_device *ofdev) if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->features |= NETIF_F_HW_VLAN_RX; } if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) { -- GitLab From fae286b0e547ed0379d93ace7664ea6f55cce0e0 Mon Sep 17 00:00:00 2001 From: "xeb@mail.ru" Date: Fri, 24 Aug 2012 01:07:38 +0000 Subject: [PATCH 0382/1799] l2tp: avoid to use synchronize_rcu in tunnel free function [ Upstream commit 99469c32f79a32d8481f87be0d3c66dad286f4ec ] Avoid to use synchronize_rcu in l2tp_tunnel_free because context may be atomic. Signed-off-by: Dmitry Kozlov Signed-off-by: David S. Miller --- net/l2tp/l2tp_core.c | 3 +-- net/l2tp/l2tp_core.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 89ff8c67943e..7501b22b9c59 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1253,11 +1253,10 @@ static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel) /* Remove from tunnel list */ spin_lock_bh(&pn->l2tp_tunnel_list_lock); list_del_rcu(&tunnel->list); + kfree_rcu(tunnel, rcu); spin_unlock_bh(&pn->l2tp_tunnel_list_lock); - synchronize_rcu(); atomic_dec(&l2tp_tunnel_count); - kfree(tunnel); } /* Create a socket for the tunnel, if one isn't set up by diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index a16a48e79fab..439379484bfc 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -157,6 +157,7 @@ struct l2tp_tunnel_cfg { struct l2tp_tunnel { int magic; /* Should be L2TP_TUNNEL_MAGIC */ + struct rcu_head rcu; rwlock_t hlist_lock; /* protect session_hlist */ struct hlist_head session_hlist[L2TP_HASH_SIZE]; /* hashed list of sessions, -- GitLab From b9d798a996cddfc4c1045e9af97ee434ccab4956 Mon Sep 17 00:00:00 2001 From: Francesco Ruggeri Date: Fri, 24 Aug 2012 07:38:35 +0000 Subject: [PATCH 0383/1799] net: ipv4: ipmr_expire_timer causes crash when removing net namespace [ Upstream commit acbb219d5f53821b2d0080d047800410c0420ea1 ] When tearing down a net namespace, ipv4 mr_table structures are freed without first deactivating their timers. This can result in a crash in run_timer_softirq. This patch mimics the corresponding behaviour in ipv6. Locking and synchronization seem to be adequate. We are about to kfree mrt, so existing code should already make sure that no other references to mrt are pending or can be created by incoming traffic. The functions invoked here do not cause new references to mrt or other race conditions to be created. Invoking del_timer_sync guarantees that ipmr_expire_timer is inactive. Both ipmr_expire_process (whose completion we may have to wait in del_timer_sync) and mroute_clean_tables internally use mfc_unres_lock or other synchronizations when needed, and they both only modify mrt. Tested in Linux 3.4.8. Signed-off-by: Francesco Ruggeri Signed-off-by: David S. Miller --- net/ipv4/ipmr.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 960fbfc3e976..8626b645ec62 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -124,6 +124,8 @@ static DEFINE_SPINLOCK(mfc_unres_lock); static struct kmem_cache *mrt_cachep __read_mostly; static struct mr_table *ipmr_new_table(struct net *net, u32 id); +static void ipmr_free_table(struct mr_table *mrt); + static int ip_mr_forward(struct net *net, struct mr_table *mrt, struct sk_buff *skb, struct mfc_cache *cache, int local); @@ -131,6 +133,7 @@ static int ipmr_cache_report(struct mr_table *mrt, struct sk_buff *pkt, vifi_t vifi, int assert); static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm); +static void mroute_clean_tables(struct mr_table *mrt); static void ipmr_expire_process(unsigned long arg); #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES @@ -271,7 +274,7 @@ static void __net_exit ipmr_rules_exit(struct net *net) list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) { list_del(&mrt->list); - kfree(mrt); + ipmr_free_table(mrt); } fib_rules_unregister(net->ipv4.mr_rules_ops); } @@ -299,7 +302,7 @@ static int __net_init ipmr_rules_init(struct net *net) static void __net_exit ipmr_rules_exit(struct net *net) { - kfree(net->ipv4.mrt); + ipmr_free_table(net->ipv4.mrt); } #endif @@ -336,6 +339,13 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id) return mrt; } +static void ipmr_free_table(struct mr_table *mrt) +{ + del_timer_sync(&mrt->ipmr_expire_timer); + mroute_clean_tables(mrt); + kfree(mrt); +} + /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */ static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) -- GitLab From 6cacd608448898cf0b7bb4353e1a92c6dc7d5dd9 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Sun, 26 Aug 2012 00:35:45 +0000 Subject: [PATCH 0384/1799] bnx2x: fix 57840_MF pci id [ Upstream commit 5c879d2094946081af934739850c7260e8b25d3c ] Commit c3def943c7117d42caaed3478731ea7c3c87190e have added support for new pci ids of the 57840 board, while failing to change the obsolete value in 'pci_ids.h'. This patch does so, allowing the probe of such devices. Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- include/linux/pci_ids.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 3329965ed63f..19ca550ff665 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2148,7 +2148,7 @@ #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 #define PCI_DEVICE_ID_NX2_57800_VF 0x16a9 #define PCI_DEVICE_ID_NX2_5706S 0x16aa -#define PCI_DEVICE_ID_NX2_57840_MF 0x16ab +#define PCI_DEVICE_ID_NX2_57840_MF 0x16a4 #define PCI_DEVICE_ID_NX2_5708S 0x16ac #define PCI_DEVICE_ID_NX2_57840_VF 0x16ad #define PCI_DEVICE_ID_NX2_57810_MF 0x16ae -- GitLab From 2ff0cd9f615bae1de9d812de92eff6426aad26c9 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Fri, 25 May 2012 11:29:30 -0700 Subject: [PATCH 0385/1799] openvswitch: Reset upper layer protocol info on internal devices. [ Upstream commit 7fe99e2d434eafeac0c57b279a77e5de39212636 ] It's possible that packets that are sent on internal devices (from the OVS perspective) have already traversed the local IP stack. After they go through the internal device, they will again travel through the IP stack which may get confused by the presence of existing information in the skb. The problem can be observed when switching between namespaces. This clears out that information to avoid problems but deliberately leaves other metadata alone. This is to provide maximum flexibility in chaining together OVS and other Linux components. Signed-off-by: Jesse Gross Signed-off-by: Greg Kroah-Hartman --- net/openvswitch/vport-internal_dev.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c index b6b1d7daa3cb..ce5348f5f601 100644 --- a/net/openvswitch/vport-internal_dev.c +++ b/net/openvswitch/vport-internal_dev.c @@ -24,6 +24,9 @@ #include #include +#include +#include + #include "datapath.h" #include "vport-internal_dev.h" #include "vport-netdev.h" @@ -209,6 +212,11 @@ static int internal_dev_recv(struct vport *vport, struct sk_buff *skb) int len; len = skb->len; + + skb_dst_drop(skb); + nf_reset(skb); + secpath_reset(skb); + skb->dev = netdev; skb->pkt_type = PACKET_HOST; skb->protocol = eth_type_trans(skb, netdev); -- GitLab From fc7da7e1c4356e4ffc7c30423325b7f0da3311b2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 18 Sep 2012 12:48:43 -0700 Subject: [PATCH 0386/1799] workqueue: reimplement work_on_cpu() using system_wq commit ed48ece27cd3d5ee0354c32bbaec0f3e1d4715c3 upstream. The existing work_on_cpu() implementation is hugely inefficient. It creates a new kthread, execute that single function and then let the kthread die on each invocation. Now that system_wq can handle concurrent executions, there's no advantage of doing this. Reimplement work_on_cpu() using system_wq which makes it simpler and way more efficient. stable: While this isn't a fix in itself, it's needed to fix a workqueue related bug in cpufreq/powernow-k8. AFAICS, this shouldn't break other existing users. Signed-off-by: Tejun Heo Acked-by: Jiri Kosina Cc: Linus Torvalds Cc: Bjorn Helgaas Cc: Len Brown Cc: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- kernel/workqueue.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index bfe3f8a1fc33..f483dd0bc9c9 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3620,18 +3620,17 @@ static int __devinit workqueue_cpu_down_callback(struct notifier_block *nfb, #ifdef CONFIG_SMP struct work_for_cpu { - struct completion completion; + struct work_struct work; long (*fn)(void *); void *arg; long ret; }; -static int do_work_for_cpu(void *_wfc) +static void work_for_cpu_fn(struct work_struct *work) { - struct work_for_cpu *wfc = _wfc; + struct work_for_cpu *wfc = container_of(work, struct work_for_cpu, work); + wfc->ret = wfc->fn(wfc->arg); - complete(&wfc->completion); - return 0; } /** @@ -3646,19 +3645,11 @@ static int do_work_for_cpu(void *_wfc) */ long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg) { - struct task_struct *sub_thread; - struct work_for_cpu wfc = { - .completion = COMPLETION_INITIALIZER_ONSTACK(wfc.completion), - .fn = fn, - .arg = arg, - }; + struct work_for_cpu wfc = { .fn = fn, .arg = arg }; - sub_thread = kthread_create(do_work_for_cpu, &wfc, "work_for_cpu"); - if (IS_ERR(sub_thread)) - return PTR_ERR(sub_thread); - kthread_bind(sub_thread, cpu); - wake_up_process(sub_thread); - wait_for_completion(&wfc.completion); + INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn); + schedule_work_on(cpu, &wfc.work); + flush_work(&wfc.work); return wfc.ret; } EXPORT_SYMBOL_GPL(work_on_cpu); -- GitLab From 3b4a9ccbdc75c6c014383b8656b57afd249d65cf Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 18 Sep 2012 14:24:59 -0700 Subject: [PATCH 0387/1799] cpufreq/powernow-k8: workqueue user shouldn't migrate the kworker to another CPU commit 6889125b8b4e09c5e53e6ecab3433bed1ce198c9 upstream. powernowk8_target() runs off a per-cpu work item and if the cpufreq_policy->cpu is different from the current one, it migrates the kworker to the target CPU by manipulating current->cpus_allowed. The function migrates the kworker back to the original CPU but this is still broken. Workqueue concurrency management requires the kworkers to stay on the same CPU and powernowk8_target() ends up triggerring BUG_ON(rq != this_rq()) in try_to_wake_up_local() if it contends on fidvid_mutex and sleeps. It is unclear why this bug is being reported now. Duncan says it appeared to be a regression of 3.6-rc1 and couldn't reproduce it on 3.5. Bisection seemed to point to 63d95a91 "workqueue: use @pool instead of @gcwq or @cpu where applicable" which is an non-functional change. Given that the reproduce case sometimes took upto days to trigger, it's easy to be misled while bisecting. Maybe something made contention on fidvid_mutex more likely? I don't know. This patch fixes the bug by using work_on_cpu() instead if @pol->cpu isn't the same as the current one. The code assumes that cpufreq_policy->cpu is kept online by the caller, which Rafael tells me is the case. stable: ed48ece27c ("workqueue: reimplement work_on_cpu() using system_wq") should be applied before this; otherwise, the behavior could be horrible. Signed-off-by: Tejun Heo Reported-by: Duncan <1i5t5.duncan@cox.net> Tested-by: Duncan <1i5t5.duncan@cox.net> Cc: Rafael J. Wysocki Cc: Andreas Herrmann Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47301 Signed-off-by: Greg Kroah-Hartman --- drivers/cpufreq/powernow-k8.c | 63 +++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index c0e816468e30..1a40935c85fd 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -35,7 +35,6 @@ #include #include #include -#include /* for current / set_cpus_allowed() */ #include #include @@ -1139,16 +1138,23 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, return res; } -/* Driver entry point to switch to the target frequency */ -static int powernowk8_target(struct cpufreq_policy *pol, - unsigned targfreq, unsigned relation) +struct powernowk8_target_arg { + struct cpufreq_policy *pol; + unsigned targfreq; + unsigned relation; +}; + +static long powernowk8_target_fn(void *arg) { - cpumask_var_t oldmask; + struct powernowk8_target_arg *pta = arg; + struct cpufreq_policy *pol = pta->pol; + unsigned targfreq = pta->targfreq; + unsigned relation = pta->relation; struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu); u32 checkfid; u32 checkvid; unsigned int newstate; - int ret = -EIO; + int ret; if (!data) return -EINVAL; @@ -1156,29 +1162,16 @@ static int powernowk8_target(struct cpufreq_policy *pol, checkfid = data->currfid; checkvid = data->currvid; - /* only run on specific CPU from here on. */ - /* This is poor form: use a workqueue or smp_call_function_single */ - if (!alloc_cpumask_var(&oldmask, GFP_KERNEL)) - return -ENOMEM; - - cpumask_copy(oldmask, tsk_cpus_allowed(current)); - set_cpus_allowed_ptr(current, cpumask_of(pol->cpu)); - - if (smp_processor_id() != pol->cpu) { - printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu); - goto err_out; - } - if (pending_bit_stuck()) { printk(KERN_ERR PFX "failing targ, change pending bit set\n"); - goto err_out; + return -EIO; } pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n", pol->cpu, targfreq, pol->min, pol->max, relation); if (query_current_values_with_pending_wait(data)) - goto err_out; + return -EIO; if (cpu_family != CPU_HW_PSTATE) { pr_debug("targ: curr fid 0x%x, vid 0x%x\n", @@ -1196,7 +1189,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate)) - goto err_out; + return -EIO; mutex_lock(&fidvid_mutex); @@ -1209,9 +1202,8 @@ static int powernowk8_target(struct cpufreq_policy *pol, ret = transition_frequency_fidvid(data, newstate); if (ret) { printk(KERN_ERR PFX "transition frequency failed\n"); - ret = 1; mutex_unlock(&fidvid_mutex); - goto err_out; + return 1; } mutex_unlock(&fidvid_mutex); @@ -1220,12 +1212,25 @@ static int powernowk8_target(struct cpufreq_policy *pol, data->powernow_table[newstate].index); else pol->cur = find_khz_freq_from_fid(data->currfid); - ret = 0; -err_out: - set_cpus_allowed_ptr(current, oldmask); - free_cpumask_var(oldmask); - return ret; + return 0; +} + +/* Driver entry point to switch to the target frequency */ +static int powernowk8_target(struct cpufreq_policy *pol, + unsigned targfreq, unsigned relation) +{ + struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq, + .relation = relation }; + + /* + * Must run on @pol->cpu. cpufreq core is responsible for ensuring + * that we're bound to the current CPU and pol->cpu stays online. + */ + if (smp_processor_id() == pol->cpu) + return powernowk8_target_fn(&pta); + else + return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); } /* Driver entry point to verify the policy and range of frequencies */ -- GitLab From f2742791b906afefa8f20906824d594e56afa20c Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Fri, 14 Sep 2012 16:35:10 -0500 Subject: [PATCH 0388/1799] cciss: fix handling of protocol error commit 2453f5f992717251cfadab6184fbb3ec2f2e8b40 upstream. If a command completes with a status of CMD_PROTOCOL_ERR, this information should be conveyed to the SCSI mid layer, not dropped on the floor. Unlike a similar bug in the hpsa driver, this bug only affects tape drives and CD and DVD ROM drives in the cciss driver, and to induce it, you have to disconnect (or damage) a cable, so it is not a very likely scenario (which would explain why the bug has gone undetected for the last 10 years.) Signed-off-by: Stephen M. Cameron Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/cciss_scsi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 38aa6dda6b81..da3311129a0c 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -795,6 +795,7 @@ static void complete_scsi_command(CommandList_struct *c, int timeout, } break; case CMD_PROTOCOL_ERR: + cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "%p has protocol error\n", c); break; -- GitLab From 5975bc201acbe121eaf22ee41076a08b92abc26f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 14 Sep 2012 14:48:21 -0700 Subject: [PATCH 0389/1799] vfs: make O_PATH file descriptors usable for 'fstat()' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 55815f70147dcfa3ead5738fd56d3574e2e3c1c2 upstream. We already use them for openat() and friends, but fstat() also wants to be able to use O_PATH file descriptors. This should make it more directly comparable to the O_SEARCH of Solaris. Note that you could already do the same thing with "fstatat()" and an empty path, but just doing "fstat()" directly is simpler and faster, so there is no reason not to just allow it directly. See also commit 332a2e1244bd, which did the same thing for fchdir, for the same reasons. Reported-by: ольга крыжановская Cc: Al Viro Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/stat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/stat.c b/fs/stat.c index c733dc5753ae..dc6d0be300ca 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -57,7 +57,7 @@ EXPORT_SYMBOL(vfs_getattr); int vfs_fstat(unsigned int fd, struct kstat *stat) { - struct file *f = fget(fd); + struct file *f = fget_raw(fd); int error = -EBADF; if (f) { -- GitLab From f92e8b0ddb85dfe7d8d2547516c873ec8dd9838e Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 17 Sep 2012 22:31:38 +0200 Subject: [PATCH 0390/1799] vfs: dcache: use DCACHE_DENTRY_KILLED instead of DCACHE_DISCONNECTED in d_kill() commit b161dfa6937ae46d50adce8a7c6b12233e96e7bd upstream. IBM reported a soft lockup after applying the fix for the rename_lock deadlock. Commit c83ce989cb5f ("VFS: Fix the nfs sillyrename regression in kernel 2.6.38") was found to be the culprit. The nfs sillyrename fix used DCACHE_DISCONNECTED to indicate that the dentry was killed. This flag can be set on non-killed dentries too, which results in infinite retries when trying to traverse the dentry tree. This patch introduces a separate flag: DCACHE_DENTRY_KILLED, which is only set in d_kill() and makes try_to_ascend() test only this flag. IBM reported successful test results with this patch. Signed-off-by: Miklos Szeredi Cc: Trond Myklebust Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/dcache.c | 4 ++-- include/linux/dcache.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index b80531c91779..10fab2666274 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -373,7 +373,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) * Inform try_to_ascend() that we are no longer attached to the * dentry tree */ - dentry->d_flags |= DCACHE_DISCONNECTED; + dentry->d_flags |= DCACHE_DENTRY_KILLED; if (parent) spin_unlock(&parent->d_lock); dentry_iput(dentry); @@ -1030,7 +1030,7 @@ static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq * or deletion */ if (new != old->d_parent || - (old->d_flags & DCACHE_DISCONNECTED) || + (old->d_flags & DCACHE_DENTRY_KILLED) || (!locked && read_seqretry(&rename_lock, seq))) { spin_unlock(&new->d_lock); new = NULL; diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 7e11f1418203..1332df02d8f2 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -191,6 +191,8 @@ struct dentry_operations { #define DCACHE_MANAGED_DENTRY \ (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT) +#define DCACHE_DENTRY_KILLED 0x100000 + extern seqlock_t rename_lock; static inline int dname_external(struct dentry *dentry) -- GitLab From 25941570aadb0f03270acab13bab1378eec5ea21 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Sat, 18 Aug 2012 07:02:20 +0000 Subject: [PATCH 0391/1799] netconsole: remove a redundant netconsole_target_put() commit 72d3eb13b5c0abe7d63efac41f39c5b644c7bbaa upstream. This netconsole_target_put() is obviously redundant, and it causes a kernel segfault when removing a bridge device which has netconsole running on it. This is caused by: commit 8d8fc29d02a33e4bd5f4fa47823c1fd386346093 Author: Amerigo Wang Date: Thu May 19 21:39:10 2011 +0000 netpoll: disable netpoll when enslave a device Signed-off-by: Cong Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/netconsole.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index f9347ea3d381..63ffbdfe36cc 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -648,7 +648,6 @@ static int netconsole_netdev_event(struct notifier_block *this, flags); dev_put(nt->np.dev); nt->np.dev = NULL; - netconsole_target_put(nt); } nt->enabled = 0; stopped = true; -- GitLab From 2d4d5e8eefbfb75feac2f2d98b70399f4c5c09a5 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Thu, 13 Sep 2012 12:00:56 -0700 Subject: [PATCH 0392/1799] eCryptfs: Copy up attributes of the lower target inode after rename commit 8335eafc2859e1a26282bef7c3d19f3d68868b8a upstream. After calling into the lower filesystem to do a rename, the lower target inode's attributes were not copied up to the eCryptfs target inode. This resulted in the eCryptfs target inode staying around, rather than being evicted, because i_nlink was not updated for the eCryptfs inode. This also meant that eCryptfs didn't do the final iput() on the lower target inode so it stayed around, as well. This would result in a failure to free up space occupied by the target file in the rename() operation. Both target inodes would eventually be evicted when the eCryptfs filesystem was unmounted. This patch calls fsstack_copy_attr_all() after the lower filesystem does its ->rename() so that important inode attributes, such as i_nlink, are updated at the eCryptfs layer. ecryptfs_evict_inode() is now called and eCryptfs can drop its final reference on the lower inode. http://launchpad.net/bugs/561129 Signed-off-by: Tyler Hicks Tested-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/inode.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index ab35b113003b..6f5fb1a0d906 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -621,6 +621,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct dentry *lower_old_dir_dentry; struct dentry *lower_new_dir_dentry; struct dentry *trap = NULL; + struct inode *target_inode; lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry); lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); @@ -628,6 +629,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, dget(lower_new_dentry); lower_old_dir_dentry = dget_parent(lower_old_dentry); lower_new_dir_dentry = dget_parent(lower_new_dentry); + target_inode = new_dentry->d_inode; trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); /* source should not be ancestor of target */ if (trap == lower_old_dentry) { @@ -643,6 +645,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, lower_new_dir_dentry->d_inode, lower_new_dentry); if (rc) goto out_lock; + if (target_inode) + fsstack_copy_attr_all(target_inode, + ecryptfs_inode_to_lower(target_inode)); fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode); if (new_dir != old_dir) fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); -- GitLab From a18a65bd69dfdb28e729f22f9ca171fa81544dc4 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 16 Aug 2012 15:33:10 -0700 Subject: [PATCH 0393/1799] target: Fix ->data_length re-assignment bug with SCSI overflow commit 4c054ba63ad47ef244cfcfa1cea38134620a5bae upstream. This patch fixes a long-standing bug with SCSI overflow handling where se_cmd->data_length was incorrectly being re-assigned to the larger CDB extracted allocation length, resulting in a number of fabric level errors that would end up causing a session reset in most cases. So instead now: - Only re-assign se_cmd->data_length durining UNDERFLOW (to use the smaller value) - Use existing se_cmd->data_length for OVERFLOW (to use the smaller value) This fix has been tested with the following CDB to generate an SCSI overflow: sg_raw -r512 /dev/sdc 28 0 0 0 0 0 0 0 9 0 Tested using iscsi-target, tcm_qla2xxx, loopback and tcm_vhost fabric ports. Here is a bit more detail on each case: - iscsi-target: Bug with open-iscsi with overflow, sg_raw returns -3584 bytes of data. - tcm_qla2xxx: Working as expected, returnins 512 bytes of data - loopback: sg_raw returns CHECK_CONDITION, from overflow rejection in transport_generic_map_mem_to_cmd() - tcm_vhost: Same as loopback Reported-by: Roland Dreier Cc: Roland Dreier Cc: Christoph Hellwig Cc: Boaz Harrosh Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_transport.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 222f1c5ff946..d594460ed988 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3167,15 +3167,20 @@ static int transport_generic_cmd_sequencer( /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */ goto out_invalid_cdb_field; } - + /* + * For the overflow case keep the existing fabric provided + * ->data_length. Otherwise for the underflow case, reset + * ->data_length to the smaller SCSI expected data transfer + * length. + */ if (size > cmd->data_length) { cmd->se_cmd_flags |= SCF_OVERFLOW_BIT; cmd->residual_count = (size - cmd->data_length); } else { cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; cmd->residual_count = (cmd->data_length - size); + cmd->data_length = size; } - cmd->data_length = size; } if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB && -- GitLab From 3518fd322d6b13b278830cc41e26d6011c3641fa Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 16 Aug 2012 18:55:44 +0100 Subject: [PATCH 0394/1799] ARM: 7496/1: hw_breakpoint: don't rely on dfsr to show watchpoint access type commit bf8801145c01ab600f8df66e8c879ac642fa5846 upstream. From ARM debug architecture v7.1 onwards, a watchpoint exception causes the DFAR to be updated with the faulting data address. However, DFSR.WnR takes an UNKNOWN value and therefore cannot be used in general to determine the access type that triggered the watchpoint. This patch forbids watchpoints without an overflow handler from specifying a specific access type (load/store). Those with overflow handlers must be able to handle false positives potentially triggered by a watchpoint of a different access type on the same address. For SIGTRAP-based handlers (i.e. ptrace), this should have no impact. Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/hw_breakpoint.c | 55 ++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index ba386bd94107..18d39ea4c02f 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -159,6 +159,12 @@ static int debug_arch_supported(void) arch >= ARM_DEBUG_ARCH_V7_1; } +/* Can we determine the watchpoint access type from the fsr? */ +static int debug_exception_updates_fsr(void) +{ + return 0; +} + /* Determine number of WRP registers available. */ static int get_num_wrp_resources(void) { @@ -619,18 +625,35 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) info->address &= ~alignment_mask; info->ctrl.len <<= offset; - /* - * Currently we rely on an overflow handler to take - * care of single-stepping the breakpoint when it fires. - * In the case of userspace breakpoints on a core with V7 debug, - * we can use the mismatch feature as a poor-man's hardware - * single-step, but this only works for per-task breakpoints. - */ - if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) || - !core_has_mismatch_brps() || !bp->hw.bp_target)) { - pr_warning("overflow handler required but none found\n"); - ret = -EINVAL; + if (!bp->overflow_handler) { + /* + * Mismatch breakpoints are required for single-stepping + * breakpoints. + */ + if (!core_has_mismatch_brps()) + return -EINVAL; + + /* We don't allow mismatch breakpoints in kernel space. */ + if (arch_check_bp_in_kernelspace(bp)) + return -EPERM; + + /* + * Per-cpu breakpoints are not supported by our stepping + * mechanism. + */ + if (!bp->hw.bp_target) + return -EINVAL; + + /* + * We only support specific access types if the fsr + * reports them. + */ + if (!debug_exception_updates_fsr() && + (info->ctrl.type == ARM_BREAKPOINT_LOAD || + info->ctrl.type == ARM_BREAKPOINT_STORE)) + return -EINVAL; } + out: return ret; } @@ -706,10 +729,12 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr, goto unlock; /* Check that the access type matches. */ - access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W : - HW_BREAKPOINT_R; - if (!(access & hw_breakpoint_type(wp))) - goto unlock; + if (debug_exception_updates_fsr()) { + access = (fsr & ARM_FSR_ACCESS_MASK) ? + HW_BREAKPOINT_W : HW_BREAKPOINT_R; + if (!(access & hw_breakpoint_type(wp))) + goto unlock; + } /* We have a winner. */ info->trigger = addr; -- GitLab From dab510cf4641187bf69e1b5e1be014848c1b473f Mon Sep 17 00:00:00 2001 From: David Brown Date: Tue, 4 Sep 2012 21:36:37 +0100 Subject: [PATCH 0395/1799] ARM: 7513/1: Make sure dtc is built before running it commit 70b0476a2394de4f4e32e0b67288d80ff71ca963 upstream. 'make dtbs' in a clean tree will try running the dtc before actually building it. Make these rules depend upon the scripts to build it. Signed-off-by: David Brown Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 047a20780fc1..1d6402cbf4b2 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -283,10 +283,10 @@ zImage Image xipImage bootpImage uImage: vmlinux zinstall uinstall install: vmlinux $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ -%.dtb: +%.dtb: scripts $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ -dtbs: +dtbs: scripts $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ # We use MRPROPER_FILES and CLEAN_FILES now -- GitLab From eff605bb6c699aae80b199010f0beb26563fc399 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 7 Sep 2012 18:21:44 +0100 Subject: [PATCH 0396/1799] ARM: 7526/1: traps: send SIGILL if get_user fails on undef handling path commit 2b2040af0b64cd93e5d4df2494c4486cf604090d upstream. get_user may fail to load from the provided __user address due to an unhandled fault generated by the access. In the case of the undefined instruction trap, this results in failure to load the faulting instruction, in which case we should send SIGILL to the task rather than continue with potentially uninitialised data. Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/traps.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index a8ad1e34902e..a53a5a3c3c2e 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -388,20 +388,23 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) #endif instr = *(u32 *) pc; } else if (thumb_mode(regs)) { - get_user(instr, (u16 __user *)pc); + if (get_user(instr, (u16 __user *)pc)) + goto die_sig; if (is_wide_instruction(instr)) { unsigned int instr2; - get_user(instr2, (u16 __user *)pc+1); + if (get_user(instr2, (u16 __user *)pc+1)) + goto die_sig; instr <<= 16; instr |= instr2; } - } else { - get_user(instr, (u32 __user *)pc); + } else if (get_user(instr, (u32 __user *)pc)) { + goto die_sig; } if (call_undef_hook(regs, instr) == 0) return; +die_sig: #ifdef CONFIG_DEBUG_USER if (user_debug & UDBG_UNDEFINED) { printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", -- GitLab From 8cc876def310b034ab0e0775a14d1a49472d7f5f Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 7 Sep 2012 18:22:28 +0100 Subject: [PATCH 0397/1799] ARM: 7527/1: uaccess: explicitly check __user pointer when !CPU_USE_DOMAINS commit 8404663f81d212918ff85f493649a7991209fa04 upstream. The {get,put}_user macros don't perform range checking on the provided __user address when !CPU_HAS_DOMAINS. This patch reworks the out-of-line assembly accessors to check the user address against a specified limit, returning -EFAULT if is is out of range. [will: changed get_user register allocation to match put_user] [rmk: fixed building on older ARM architectures] Reported-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/assembler.h | 8 +++++++ arch/arm/include/asm/uaccess.h | 40 +++++++++++++++++++++----------- arch/arm/lib/getuser.S | 23 +++++++++++------- arch/arm/lib/putuser.S | 6 +++++ 4 files changed, 56 insertions(+), 21 deletions(-) diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 03fb93621d0d..5c8b3bf4d825 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -320,4 +320,12 @@ .size \name , . - \name .endm + .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req +#ifndef CONFIG_CPU_USE_DOMAINS + adds \tmp, \addr, #\size - 1 + sbcccs \tmp, \tmp, \limit + bcs \bad +#endif + .endm + #endif /* __ASM_ASSEMBLER_H__ */ diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 71f6536d17ac..0a070e98625d 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -101,28 +101,39 @@ extern int __get_user_1(void *); extern int __get_user_2(void *); extern int __get_user_4(void *); -#define __get_user_x(__r2,__p,__e,__s,__i...) \ +#define __GUP_CLOBBER_1 "lr", "cc" +#ifdef CONFIG_CPU_USE_DOMAINS +#define __GUP_CLOBBER_2 "ip", "lr", "cc" +#else +#define __GUP_CLOBBER_2 "lr", "cc" +#endif +#define __GUP_CLOBBER_4 "lr", "cc" + +#define __get_user_x(__r2,__p,__e,__l,__s) \ __asm__ __volatile__ ( \ __asmeq("%0", "r0") __asmeq("%1", "r2") \ + __asmeq("%3", "r1") \ "bl __get_user_" #__s \ : "=&r" (__e), "=r" (__r2) \ - : "0" (__p) \ - : __i, "cc") + : "0" (__p), "r" (__l) \ + : __GUP_CLOBBER_##__s) #define get_user(x,p) \ ({ \ + unsigned long __limit = current_thread_info()->addr_limit - 1; \ register const typeof(*(p)) __user *__p asm("r0") = (p);\ register unsigned long __r2 asm("r2"); \ + register unsigned long __l asm("r1") = __limit; \ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ case 1: \ - __get_user_x(__r2, __p, __e, 1, "lr"); \ - break; \ + __get_user_x(__r2, __p, __e, __l, 1); \ + break; \ case 2: \ - __get_user_x(__r2, __p, __e, 2, "r3", "lr"); \ + __get_user_x(__r2, __p, __e, __l, 2); \ break; \ case 4: \ - __get_user_x(__r2, __p, __e, 4, "lr"); \ + __get_user_x(__r2, __p, __e, __l, 4); \ break; \ default: __e = __get_user_bad(); break; \ } \ @@ -135,31 +146,34 @@ extern int __put_user_2(void *, unsigned int); extern int __put_user_4(void *, unsigned int); extern int __put_user_8(void *, unsigned long long); -#define __put_user_x(__r2,__p,__e,__s) \ +#define __put_user_x(__r2,__p,__e,__l,__s) \ __asm__ __volatile__ ( \ __asmeq("%0", "r0") __asmeq("%2", "r2") \ + __asmeq("%3", "r1") \ "bl __put_user_" #__s \ : "=&r" (__e) \ - : "0" (__p), "r" (__r2) \ + : "0" (__p), "r" (__r2), "r" (__l) \ : "ip", "lr", "cc") #define put_user(x,p) \ ({ \ + unsigned long __limit = current_thread_info()->addr_limit - 1; \ register const typeof(*(p)) __r2 asm("r2") = (x); \ register const typeof(*(p)) __user *__p asm("r0") = (p);\ + register unsigned long __l asm("r1") = __limit; \ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ case 1: \ - __put_user_x(__r2, __p, __e, 1); \ + __put_user_x(__r2, __p, __e, __l, 1); \ break; \ case 2: \ - __put_user_x(__r2, __p, __e, 2); \ + __put_user_x(__r2, __p, __e, __l, 2); \ break; \ case 4: \ - __put_user_x(__r2, __p, __e, 4); \ + __put_user_x(__r2, __p, __e, __l, 4); \ break; \ case 8: \ - __put_user_x(__r2, __p, __e, 8); \ + __put_user_x(__r2, __p, __e, __l, 8); \ break; \ default: __e = __put_user_bad(); break; \ } \ diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index 11093a7c3e32..9b06bb41fca6 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -16,8 +16,9 @@ * __get_user_X * * Inputs: r0 contains the address + * r1 contains the address limit, which must be preserved * Outputs: r0 is the error code - * r2, r3 contains the zero-extended value + * r2 contains the zero-extended value * lr corrupted * * No other registers must be altered. (see @@ -27,33 +28,39 @@ * Note also that it is intended that __get_user_bad is not global. */ #include +#include #include #include ENTRY(__get_user_1) + check_uaccess r0, 1, r1, r2, __get_user_bad 1: TUSER(ldrb) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__get_user_1) ENTRY(__get_user_2) -#ifdef CONFIG_THUMB2_KERNEL -2: TUSER(ldrb) r2, [r0] -3: TUSER(ldrb) r3, [r0, #1] + check_uaccess r0, 2, r1, r2, __get_user_bad +#ifdef CONFIG_CPU_USE_DOMAINS +rb .req ip +2: ldrbt r2, [r0], #1 +3: ldrbt rb, [r0], #0 #else -2: TUSER(ldrb) r2, [r0], #1 -3: TUSER(ldrb) r3, [r0] +rb .req r0 +2: ldrb r2, [r0] +3: ldrb rb, [r0, #1] #endif #ifndef __ARMEB__ - orr r2, r2, r3, lsl #8 + orr r2, r2, rb, lsl #8 #else - orr r2, r3, r2, lsl #8 + orr r2, rb, r2, lsl #8 #endif mov r0, #0 mov pc, lr ENDPROC(__get_user_2) ENTRY(__get_user_4) + check_uaccess r0, 4, r1, r2, __get_user_bad 4: TUSER(ldr) r2, [r0] mov r0, #0 mov pc, lr diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S index 7db25990c589..3d73dcb959b0 100644 --- a/arch/arm/lib/putuser.S +++ b/arch/arm/lib/putuser.S @@ -16,6 +16,7 @@ * __put_user_X * * Inputs: r0 contains the address + * r1 contains the address limit, which must be preserved * r2, r3 contains the value * Outputs: r0 is the error code * lr corrupted @@ -27,16 +28,19 @@ * Note also that it is intended that __put_user_bad is not global. */ #include +#include #include #include ENTRY(__put_user_1) + check_uaccess r0, 1, r1, ip, __put_user_bad 1: TUSER(strb) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__put_user_1) ENTRY(__put_user_2) + check_uaccess r0, 2, r1, ip, __put_user_bad mov ip, r2, lsr #8 #ifdef CONFIG_THUMB2_KERNEL #ifndef __ARMEB__ @@ -60,12 +64,14 @@ ENTRY(__put_user_2) ENDPROC(__put_user_2) ENTRY(__put_user_4) + check_uaccess r0, 4, r1, ip, __put_user_bad 4: TUSER(str) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__put_user_4) ENTRY(__put_user_8) + check_uaccess r0, 8, r1, ip, __put_user_bad #ifdef CONFIG_THUMB2_KERNEL 5: TUSER(str) r2, [r0] 6: TUSER(str) r3, [r0, #4] -- GitLab From 6252fbdc0a40c20a21b24d7bfccf3c08ea9b10dc Mon Sep 17 00:00:00 2001 From: "Dae S. Kim" Date: Fri, 31 Aug 2012 02:00:51 +0200 Subject: [PATCH 0398/1799] Staging: Android alarm: IOCTL command encoding fix commit 6bd4a5d96c08dc2380f8053b1bd4f879f55cd3c9 upstream. Fixed a bug. Data was being written to user space using an IOCTL command encoded with _IOC_WRITE access mode. Signed-off-by: Dae S. Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/android_alarm.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h index 6eecbde2ef6f..66b6e3decc64 100644 --- a/drivers/staging/android/android_alarm.h +++ b/drivers/staging/android/android_alarm.h @@ -110,10 +110,12 @@ enum android_alarm_return_flags { #define ANDROID_ALARM_WAIT _IO('a', 1) #define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size) +#define ALARM_IOR(c, type, size) _IOR('a', (c) | ((type) << 4), size) + /* Set alarm */ #define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) #define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec) -#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec) +#define ANDROID_ALARM_GET_TIME(type) ALARM_IOR(4, type, struct timespec) #define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) #define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0))) #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4) -- GitLab From 4dbbba47b19e4e2902a3b5115569e97c210c3297 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 25 Aug 2012 09:03:15 +0100 Subject: [PATCH 0399/1799] ARM: Fix ioremap() of address zero commit a849088aa1552b1a28eea3daff599ee22a734ae3 upstream. Murali Nalajala reports a regression that ioremapping address zero results in an oops dump: Unable to handle kernel paging request at virtual address fa200000 pgd = d4f80000 [fa200000] *pgd=00000000 Internal error: Oops: 5 [#1] PREEMPT SMP ARM Modules linked in: CPU: 0 Tainted: G W (3.4.0-g3b5f728-00009-g638207a #13) PC is at msm_pm_config_rst_vector_before_pc+0x8/0x30 LR is at msm_pm_boot_config_before_pc+0x18/0x20 pc : [] lr : [] psr: a0000093 sp : c0837ef0 ip : cfe00000 fp : 0000000d r10: da7efc17 r9 : 225c4278 r8 : 00000006 r7 : 0003c000 r6 : c085c824 r5 : 00000001 r4 : fa101000 r3 : fa200000 r2 : c095080c r1 : 002250fc r0 : 00000000 Flags: NzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel Control: 10c5387d Table: 25180059 DAC: 00000015 [] (msm_pm_config_rst_vector_before_pc+0x8/0x30) from [] (msm_pm_boot_config_before_pc+0x18/0x20) [] (msm_pm_boot_config_before_pc+0x18/0x20) from [] (msm_pm_power_collapse+0x410/0xb04) [] (msm_pm_power_collapse+0x410/0xb04) from [] (arch_idle+0x294/0x3e0) [] (arch_idle+0x294/0x3e0) from [] (default_idle+0x18/0x2c) [] (default_idle+0x18/0x2c) from [] (cpu_idle+0x90/0xe4) [] (cpu_idle+0x90/0xe4) from [] (rest_init+0x88/0xa0) [] (rest_init+0x88/0xa0) from [] (start_kernel+0x3a8/0x40c) Code: c0704256 e12fff1e e59f2020 e5923000 (e5930000) This is caused by the 'reserved' entries which we insert (see 19b52abe3c5d7 - ARM: 7438/1: fill possible PMD empty section gaps) which get matched for physical address zero. Resolve this by marking these reserved entries with a different flag. Tested-by: Murali Nalajala Acked-by: Nicolas Pitre Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/mm/mm.h | 3 +++ arch/arm/mm/mmu.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 27f4a619b35d..d3f25c9aaf82 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -55,6 +55,9 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page /* permanent static mappings from iotable_init() */ #define VM_ARM_STATIC_MAPPING 0x40000000 +/* empty mapping */ +#define VM_ARM_EMPTY_MAPPING 0x20000000 + /* mapping type (attributes) for permanent static mappings */ #define VM_ARM_MTYPE(mt) ((mt) << 20) #define VM_ARM_MTYPE_MASK (0x1f << 20) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 75f9f9d67097..7d419193d49a 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -805,7 +805,7 @@ static void __init pmd_empty_section_gap(unsigned long addr) vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm)); vm->addr = (void *)addr; vm->size = SECTION_SIZE; - vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING; + vm->flags = VM_IOREMAP | VM_ARM_EMPTY_MAPPING; vm->caller = pmd_empty_section_gap; vm_area_add_early(vm); } @@ -818,7 +818,7 @@ static void __init fill_pmd_gaps(void) /* we're still single threaded hence no lock needed here */ for (vm = vmlist; vm; vm = vm->next) { - if (!(vm->flags & VM_ARM_STATIC_MAPPING)) + if (!(vm->flags & (VM_ARM_STATIC_MAPPING | VM_ARM_EMPTY_MAPPING))) continue; addr = (unsigned long)vm->addr; if (addr < next) -- GitLab From 68983b9dae341fbca6b74be02248adb86e105818 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Sep 2012 10:10:11 +0200 Subject: [PATCH 0400/1799] ALSA: hda - Fix missing Master volume for STAC9200/925x commit ab548d2dba63ba947287965e525cc02a15d9853d upstream. With the commit [2faa3bf: ALSA: hda - Rewrite the mute-LED hook with vmaster hook in patch_sigmatel.c], the former Master volume control was converted to PCM. This was supposed to be covered by the vmaster control. But due to the lack of "PCM" slave definition, this didn't happen properly. The patch fixes the missing entry. Reported-by: Andrew Shadura Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- 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 fd5331244171..04cd44fa2248 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1072,7 +1072,7 @@ static struct snd_kcontrol_new stac_smux_mixer = { static const char * const slave_pfxs[] = { "Front", "Surround", "Center", "LFE", "Side", - "Headphone", "Speaker", "IEC958", + "Headphone", "Speaker", "IEC958", "PCM", NULL }; -- GitLab From 6172ace501d10b1c629c5e82af26d0b87773c1ef Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Sep 2012 09:39:31 +0200 Subject: [PATCH 0401/1799] ALSA: hda - Fix Oops at codec reset/reconfig commit 07dc59f0988cb54fd87bd373b3b27eb2401dd811 upstream. snd_hda_codec_reset() calls restore_pincfgs() where the codec is powered up again, which eventually tries to resume and initialize via the callbacks of the codec. However, it's the place just after codec free callback, thus no codec callbacks should be called after that. On a codec like CS4206, it results in Oops due to the access in init callback. This patch fixes the issue by clearing the codec callbacks properly after freeing codec. Reported-by: Daniel J Blueman 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 926b455392c7..cec747998e5c 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2279,6 +2279,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) } if (codec->patch_ops.free) codec->patch_ops.free(codec); + memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); snd_hda_jack_tbl_clear(codec); codec->proc_widget_hook = NULL; codec->spec = NULL; @@ -2292,7 +2293,6 @@ int snd_hda_codec_reset(struct hda_codec *codec) codec->num_pcms = 0; codec->pcm_info = NULL; codec->preset = NULL; - memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); codec->slave_dig_outs = NULL; codec->spdif_status_reset = 0; module_put(codec->owner); -- GitLab From 23b5a5da4f07b887adce9b42daa7aa14a72a5427 Mon Sep 17 00:00:00 2001 From: Matteo Frigo Date: Wed, 12 Sep 2012 10:12:06 -0400 Subject: [PATCH 0402/1799] ALSA: ice1724: Use linear scale for AK4396 volume control. commit 3737e2be505d872bf2b3c1cd4151b2d2b413d7b5 upstream. The AK4396 DAC has a linear-scale attentuator, but sound/pci/ice1712/prodigy_hifi.c used a log scale instead, which is not quite right. This patch restores the correct scale, borrowing from the ak4396 code in sound/pci/oxygen/oxygen.c. Signed-off-by: Matteo Frigo Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/ice1712/prodigy_hifi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c index 764cc93dbca4..075d5aa1fee0 100644 --- a/sound/pci/ice1712/prodigy_hifi.c +++ b/sound/pci/ice1712/prodigy_hifi.c @@ -297,6 +297,7 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem } static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); +static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = { { @@ -307,7 +308,7 @@ static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = { .info = ak4396_dac_vol_info, .get = ak4396_dac_vol_get, .put = ak4396_dac_vol_put, - .tlv = { .p = db_scale_wm_dac }, + .tlv = { .p = ak4396_db_scale }, }, }; -- GitLab From 4386363312d70a764a376f1635467bab8e26965a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 20 Sep 2012 07:44:11 +0200 Subject: [PATCH 0403/1799] ALSA: hda - Workaround for silent output on VAIO Z with ALC889 commit e427c2375646789ecd0ccaef1a1e41458559ab2d upstream. On recent kernels, Realtek codec parser tries to optimize the routing aggressively and take the headphone output as primary at first. This caused a regression on VAIO Z with ALC889, the silent output from the speaker. The problem seems that the speaker pin must be connected to the first DAC (0x02) on this machine by some reason although the codec itself advertises the flexible routing with any DACs. This patch adds a fix-up for choosing the speaker pin as the primary so that the right DAC is assigned on this device. Reported-and-tested-by: Adam Williamson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 + sound/pci/hda/patch_realtek.c | 22 +++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 286ec04d1383..82dd174396d1 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -47,6 +47,7 @@ ALC882/883/885/888/889 acer-aspire-4930g Acer Aspire 4930G/5930G/6530G/6930G/7730G acer-aspire-8930g Acer Aspire 8330G/6935G acer-aspire Acer Aspire others + no-primary-hp VAIO Z workaround (for fixed speaker DAC) ALC861/660 ========== diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 152d91b7e103..52e7a45f6e57 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -188,6 +188,7 @@ struct alc_spec { unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */ unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ + unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */ /* auto-mute control */ int automute_mode; @@ -4365,7 +4366,8 @@ static int alc_parse_auto_config(struct hda_codec *codec, return 0; /* can't find valid BIOS pin config */ } - if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && + if (!spec->no_primary_hp && + cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->line_outs <= cfg->hp_outs) { /* use HP as primary out */ cfg->speaker_outs = cfg->line_outs; @@ -5076,6 +5078,7 @@ enum { ALC889_FIXUP_DAC_ROUTE, ALC889_FIXUP_MBP_VREF, ALC889_FIXUP_IMAC91_VREF, + ALC882_FIXUP_NO_PRIMARY_HP, }; static void alc889_fixup_coef(struct hda_codec *codec, @@ -5199,6 +5202,17 @@ static void alc889_fixup_imac91_vref(struct hda_codec *codec, spec->keep_vref_in_automute = 1; } +/* Don't take HP output as primary + * strangely, the speaker output doesn't work on VAIO Z through DAC 0x05 + */ +static void alc882_fixup_no_primary_hp(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + if (action == ALC_FIXUP_ACT_PRE_PROBE) + spec->no_primary_hp = 1; +} + static const struct alc_fixup alc882_fixups[] = { [ALC882_FIXUP_ABIT_AW9D_MAX] = { .type = ALC_FIXUP_PINS, @@ -5381,6 +5395,10 @@ static const struct alc_fixup alc882_fixups[] = { .chained = true, .chain_id = ALC882_FIXUP_GPIO1, }, + [ALC882_FIXUP_NO_PRIMARY_HP] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc882_fixup_no_primary_hp, + }, }; static const struct snd_pci_quirk alc882_fixup_tbl[] = { @@ -5415,6 +5433,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC), SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601), SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT), + SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP), /* All Apple entries are in codec SSIDs */ SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF), @@ -5455,6 +5474,7 @@ static const struct alc_model_fixup alc882_fixup_models[] = { {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"}, {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"}, {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"}, + {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"}, {} }; -- GitLab From 18e64a0a0dfc533ab56f7aa198316b4ea11adca9 Mon Sep 17 00:00:00 2001 From: Christopher Brannon Date: Sat, 16 Jun 2012 16:55:20 -0500 Subject: [PATCH 0404/1799] Staging: speakup: fix an improperly-declared variable. commit 4ea418b8b2fa8a70d0fcc8231b65e67b3a72984b upstream. A local static variable was declared as a pointer to a string constant. We're assigning to the underlying memory, so it needs to be an array instead. Signed-off-by: Christopher Brannon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index 92b34e29ad06..40e2488b9679 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -1854,7 +1854,7 @@ static void speakup_bits(struct vc_data *vc) static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key) { - static u_char *goto_buf = "\0\0\0\0\0\0"; + static u_char goto_buf[8]; static int num; int maxlen, go_pos; char *cp; -- GitLab From 6d4960ed8247d763e9022bda9f068fec7000af3f Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Wed, 29 Aug 2012 16:58:45 -0500 Subject: [PATCH 0405/1799] staging: zcache: fix cleancache race condition with shrinker commit 6d7d9798ad5c97ee4e911dd070dc12dc5ae55bd0 upstream. This patch fixes a race condition that results in memory corruption when using cleancache. The race exists between the zcache shrinker handler, shrink_zcache_memory() and cleancache_get_page(). In most cases, the shrinker will both evict a zbpg from its buddy list and flush it from tmem before a cleancache_get_page() occurs on that page. A subsequent cleancache_get_page() will fail in the tmem layer. In the rare case that two occur together and the cleancache_get_page() path gets through the tmem layer before the shrinker path can flush tmem, zbud_decompress() does a check to see if the zbpg is a "zombie", i.e. not on a buddy list, which means the shrinker is in the process of reclaiming it. If the zbpg is a zombie, zbud_decompress() returns -EINVAL. However, this return code is being ignored by the caller, zcache_pampd_get_data_and_free(), which results in the caller of cleancache_get_page() thinking that the page has been properly retrieved when it has not. This patch modifies zcache_pampd_get_data_and_free() to convey the failure up the stack so that the caller of cleancache_get_page() knows the page retrieval failed. This needs to be applied to stable trees as well. zcache-main.c was named zcache.c before v3.1, so I'm not sure how you want to handle trees earlier than that. Signed-off-by: Seth Jennings Reviewed-by: Konrad Rzeszutek Wilk Reviewed-by: Minchan Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 2734dacacbaf..1812bedab324 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -1259,13 +1259,12 @@ static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw, void *pampd, struct tmem_pool *pool, struct tmem_oid *oid, uint32_t index) { - int ret = 0; - BUG_ON(!is_ephemeral(pool)); - zbud_decompress((struct page *)(data), pampd); + if (zbud_decompress((struct page *)(data), pampd) < 0) + return -EINVAL; zbud_free_and_delist((struct zbud_hdr *)pampd); atomic_dec(&zcache_curr_eph_pampd_count); - return ret; + return 0; } /* -- GitLab From 191ee4172f0a89b85ce1daad00d88f33b66e07e6 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 29 Aug 2012 23:08:21 +0100 Subject: [PATCH 0406/1799] staging: vt6656: [BUG] - Failed connection, incorrect endian. commit aa209eef3ce8419ff2926c2fa944dfbfb5afbacb upstream. Hi, This patch fixes a bug with driver failing to negotiate a connection. The bug was traced to commit 203e4615ee9d9fa8d3506b9d0ef30095e4d5bc90 staging: vt6656: removed custom definitions of Ethernet packet types In that patch, definitions in include/linux/if_ether.h replaced ones in tether.h which had both big and little endian definitions. include/linux/if_ether.h only refers to big endian values, cpu_to_be16 should be used for the correct endian architectures. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/dpc.c | 2 +- drivers/staging/vt6656/rxtx.c | 38 +++++++++++++++++------------------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index c0edf97535dc..08021f4d5236 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -200,7 +200,7 @@ s_vProcessRxMACHeader ( } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) { cbHeaderSize += 6; pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); - if ((*pwType == cpu_to_le16(ETH_P_IPX)) || + if ((*pwType == cpu_to_be16(ETH_P_IPX)) || (*pwType == cpu_to_le16(0xF380))) { cbHeaderSize -= 8; pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 9b64b102f55c..fe218689a0a4 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -1701,7 +1701,7 @@ s_bPacketToWirelessUsb( // 802.1H if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) { if (pDevice->dwDiagRefCount == 0) { - if ((psEthHeader->wType == cpu_to_le16(ETH_P_IPX)) || + if ((psEthHeader->wType == cpu_to_be16(ETH_P_IPX)) || (psEthHeader->wType == cpu_to_le16(0xF380))) { memcpy((PBYTE) (pbyPayloadHead), abySNAP_Bridgetunnel, 6); @@ -2840,10 +2840,10 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) Packet_Type = skb->data[ETH_HLEN+1]; Descriptor_type = skb->data[ETH_HLEN+1+1+2]; Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]); - if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) { - /* 802.1x OR eapol-key challenge frame transfer */ - if (((Protocol_Version == 1) || (Protocol_Version == 2)) && - (Packet_Type == 3)) { + if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) { + /* 802.1x OR eapol-key challenge frame transfer */ + if (((Protocol_Version == 1) || (Protocol_Version == 2)) && + (Packet_Type == 3)) { bTxeapol_key = TRUE; if(!(Key_info & BIT3) && //WPA or RSN group-key challenge (Key_info & BIT8) && (Key_info & BIT9)) { //send 2/2 key @@ -2989,19 +2989,19 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) } } - if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) { - if (pDevice->byBBType != BB_TYPE_11A) { - pDevice->wCurrentRate = RATE_1M; - pDevice->byACKRate = RATE_1M; - pDevice->byTopCCKBasicRate = RATE_1M; - pDevice->byTopOFDMBasicRate = RATE_6M; - } else { - pDevice->wCurrentRate = RATE_6M; - pDevice->byACKRate = RATE_6M; - pDevice->byTopCCKBasicRate = RATE_1M; - pDevice->byTopOFDMBasicRate = RATE_6M; - } - } + if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) { + if (pDevice->byBBType != BB_TYPE_11A) { + pDevice->wCurrentRate = RATE_1M; + pDevice->byACKRate = RATE_1M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } else { + pDevice->wCurrentRate = RATE_6M; + pDevice->byACKRate = RATE_6M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } + } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dma_tx: pDevice->wCurrentRate = %d\n", @@ -3017,7 +3017,7 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) if (bNeedEncryption == TRUE) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType)); - if ((pDevice->sTxEthHeader.wType) == cpu_to_le16(ETH_P_PAE)) { + if ((pDevice->sTxEthHeader.wType) == cpu_to_be16(ETH_P_PAE)) { bNeedEncryption = FALSE; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType)); if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { -- GitLab From 8fae345eec6e2fff49e634b108f3318d88205c6c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 10 Sep 2012 21:22:11 +0200 Subject: [PATCH 0407/1799] staging: r8712u: fix bug in r8712_recv_indicatepkt() commit abf02cfc179bb4bd30d05f582d61b3b8f429b813 upstream. 64bit arches have a buggy r8712u driver, let's fix it. skb->tail must be set properly or network stack behavior is undefined. Addresses https://bugzilla.redhat.com/show_bug.cgi?id=847525 Addresses https://bugzilla.kernel.org/show_bug.cgi?id=45071 Signed-off-by: Eric Dumazet Cc: Dave Jones Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_linux.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 0e26d5f6cf2d..495ee1205e02 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -117,13 +117,8 @@ void r8712_recv_indicatepkt(struct _adapter *padapter, if (skb == NULL) goto _recv_indicatepkt_drop; skb->data = precv_frame->u.hdr.rx_data; -#ifdef NET_SKBUFF_DATA_USES_OFFSET - skb->tail = (sk_buff_data_t)(precv_frame->u.hdr.rx_tail - - precv_frame->u.hdr.rx_head); -#else - skb->tail = (sk_buff_data_t)precv_frame->u.hdr.rx_tail; -#endif skb->len = precv_frame->u.hdr.len; + skb_set_tail_pointer(skb, skb->len); if ((pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1)) skb->ip_summed = CHECKSUM_UNNECESSARY; else -- GitLab From 8ef2b61115a3baeb3dc60782af32a3f6c46ed7a4 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 31 Aug 2012 20:41:30 +0100 Subject: [PATCH 0408/1799] staging: comedi: das08: Correct AO output for das08jr-16-ao commit 61ed59ed09e6ad2b8395178ea5ad5f653bba08e3 upstream. Don't zero out bits 15..12 of the data value in `das08jr_ao_winsn()` as that knobbles the upper three-quarters of the output range for the 'das08jr-16-ao' board. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index c2dd0ed36a73..d2dd75e2af7f 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -653,7 +653,7 @@ static int das08jr_ao_winsn(struct comedi_device *dev, int chan; lsb = data[0] & 0xff; - msb = (data[0] >> 8) & 0xf; + msb = (data[0] >> 8) & 0xff; chan = CR_CHAN(insn->chanspec); -- GitLab From 125c4c2a41ac9249b54602db68b81a5ad398bbb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Tue, 11 Sep 2012 09:40:31 +0200 Subject: [PATCH 0409/1799] USB: option: replace ZTE K5006-Z entry with vendor class rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit ba9edaa468869a8cea242a411066b0f490751798 upstream. Fix the ZTE K5006-Z entry so that it actually matches anything commit f1b5c997 USB: option: add ZTE K5006-Z added a device specific entry assuming that the device would use class/subclass/proto == ff/ff/ff like other ZTE devices. It turns out that ZTE has started using vendor specific subclass and protocol codes: T: Bus=01 Lev=01 Prnt=01 Port=03 Cnt=01 Dev#= 4 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=19d2 ProdID=1018 Rev= 0.00 S: Manufacturer=ZTE,Incorporated S: Product=ZTE LTE Technologies MSM S: SerialNumber=MF821Vxxxxxxx C:* #Ifs= 5 Cfg#= 1 Atr=c0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=86 Prot=10 Driver=(none) E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=02 Prot=05 Driver=(none) E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=02 Prot=01 Driver=(none) E: Ad=83(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=06 Prot=00 Driver=qmi_wwan E: Ad=85(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 4 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms We do not have any information on how ZTE intend to use these codes, but let us assume for now that the 3 sets matching serial functions in the K5006-Z always will identify a serial function in a ZTE device. Cc: Thomas Schäfer Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ee693ccfdeb6..a49099da93e3 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -886,8 +886,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, @@ -1092,6 +1090,10 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) }, + { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */ -- GitLab From 2ad98b042313307859bf2f332b95b6588ec0ba0d Mon Sep 17 00:00:00 2001 From: Francesco Ruggeri Date: Thu, 13 Sep 2012 15:03:37 -0700 Subject: [PATCH 0410/1799] fs/proc: fix potential unregister_sysctl_table hang commit 6bf6104573482570f7103d3e5ddf9574db43a363 upstream. The unregister_sysctl_table() function hangs if all references to its ctl_table_header structure are not dropped. This can happen sometimes because of a leak in proc_sys_lookup(): proc_sys_lookup() gets a reference to the table via lookup_entry(), but it does not release it when a subsequent call to sysctl_follow_link() fails. This patch fixes this leak by making sure the reference is always dropped on return. See also commit 076c3eed2c31 ("sysctl: Rewrite proc_sys_lookup introducing find_entry and lookup_entry") which reorganized this code in 3.4. Tested in Linux 3.4.4. Signed-off-by: Francesco Ruggeri Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/proc/proc_sysctl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 21d836f40292..ab5352101db5 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -462,9 +462,6 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry, err = ERR_PTR(-ENOMEM); inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p); - if (h) - sysctl_head_finish(h); - if (!inode) goto out; @@ -473,6 +470,8 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry, d_add(dentry, inode); out: + if (h) + sysctl_head_finish(h); sysctl_head_finish(head); return err; } -- GitLab From 9b52a3b313497af37dcdba4ba4c0c95809db525c Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 24 Aug 2012 21:20:15 -0600 Subject: [PATCH 0411/1799] sound: tegra_alc5632: remove HP detect GPIO inversion commit c921928661eda599d73a6a86e58bdd5aecfa18cb upstream. Both the schematics and practical testing show that the HP detect GPIO is high when the headphones are plugged in. Hence, the snd_soc_jack_gpio should not specify to invert the signal. Signed-off-by: Stephen Warren Acked-by: Andrey Danin Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/tegra/tegra_alc5632.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index e45ccd851f6a..76d759ec40a2 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -95,7 +95,6 @@ static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = { .name = "Headset detection", .report = SND_JACK_HEADSET, .debounce_time = 150, - .invert = 1, }; static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = { -- GitLab From d156b47c4242843096e4a13f8ace5a0626bde3e9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Aug 2012 14:59:25 +0100 Subject: [PATCH 0412/1799] perf_event: Switch to internal refcount, fix race with close() commit a6fa941d94b411bbd2b6421ffbde6db3c93e65ab upstream. Don't mess with file refcounts (or keep a reference to file, for that matter) in perf_event. Use explicit refcount of its own instead. Deal with the race between the final reference to event going away and new children getting created for it by use of atomic_long_inc_not_zero() in inherit_event(); just have the latter free what it had allocated and return NULL, that works out just fine (children of siblings of something doomed are created as singletons, same as if the child of leader had been created and immediately killed). Signed-off-by: Al Viro Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20120820135925.GG23464@ZenIV.linux.org.uk Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- include/linux/perf_event.h | 2 +- kernel/events/core.c | 62 ++++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index ddbb6a901f65..f18d537fd4ba 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -925,7 +925,7 @@ struct perf_event { struct hw_perf_event hw; struct perf_event_context *ctx; - struct file *filp; + atomic_long_t refcount; /* * These accumulate total time (in nanoseconds) that children diff --git a/kernel/events/core.c b/kernel/events/core.c index fd126f82b57c..228fdb042fad 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -2929,12 +2929,12 @@ EXPORT_SYMBOL_GPL(perf_event_release_kernel); /* * Called when the last reference to the file is gone. */ -static int perf_release(struct inode *inode, struct file *file) +static void put_event(struct perf_event *event) { - struct perf_event *event = file->private_data; struct task_struct *owner; - file->private_data = NULL; + if (!atomic_long_dec_and_test(&event->refcount)) + return; rcu_read_lock(); owner = ACCESS_ONCE(event->owner); @@ -2969,7 +2969,13 @@ static int perf_release(struct inode *inode, struct file *file) put_task_struct(owner); } - return perf_event_release_kernel(event); + perf_event_release_kernel(event); +} + +static int perf_release(struct inode *inode, struct file *file) +{ + put_event(file->private_data); + return 0; } u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running) @@ -3222,7 +3228,7 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg) static const struct file_operations perf_fops; -static struct perf_event *perf_fget_light(int fd, int *fput_needed) +static struct file *perf_fget_light(int fd, int *fput_needed) { struct file *file; @@ -3236,7 +3242,7 @@ static struct perf_event *perf_fget_light(int fd, int *fput_needed) return ERR_PTR(-EBADF); } - return file->private_data; + return file; } static int perf_event_set_output(struct perf_event *event, @@ -3268,19 +3274,21 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case PERF_EVENT_IOC_SET_OUTPUT: { + struct file *output_file = NULL; struct perf_event *output_event = NULL; int fput_needed = 0; int ret; if (arg != -1) { - output_event = perf_fget_light(arg, &fput_needed); - if (IS_ERR(output_event)) - return PTR_ERR(output_event); + output_file = perf_fget_light(arg, &fput_needed); + if (IS_ERR(output_file)) + return PTR_ERR(output_file); + output_event = output_file->private_data; } ret = perf_event_set_output(event, output_event); if (output_event) - fput_light(output_event->filp, fput_needed); + fput_light(output_file, fput_needed); return ret; } @@ -5920,6 +5928,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, mutex_init(&event->mmap_mutex); + atomic_long_set(&event->refcount, 1); event->cpu = cpu; event->attr = *attr; event->group_leader = group_leader; @@ -6230,12 +6239,12 @@ SYSCALL_DEFINE5(perf_event_open, return event_fd; if (group_fd != -1) { - group_leader = perf_fget_light(group_fd, &fput_needed); - if (IS_ERR(group_leader)) { - err = PTR_ERR(group_leader); + group_file = perf_fget_light(group_fd, &fput_needed); + if (IS_ERR(group_file)) { + err = PTR_ERR(group_file); goto err_fd; } - group_file = group_leader->filp; + group_leader = group_file->private_data; if (flags & PERF_FLAG_FD_OUTPUT) output_event = group_leader; if (flags & PERF_FLAG_FD_NO_GROUP) @@ -6370,7 +6379,6 @@ SYSCALL_DEFINE5(perf_event_open, put_ctx(gctx); } - event->filp = event_file; WARN_ON_ONCE(ctx->parent_ctx); mutex_lock(&ctx->mutex); @@ -6460,7 +6468,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, goto err_free; } - event->filp = NULL; WARN_ON_ONCE(ctx->parent_ctx); mutex_lock(&ctx->mutex); perf_install_in_context(ctx, event, cpu); @@ -6509,7 +6516,7 @@ static void sync_child_event(struct perf_event *child_event, * Release the parent event, if this was the last * reference to it. */ - fput(parent_event->filp); + put_event(parent_event); } static void @@ -6585,9 +6592,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn) * * __perf_event_exit_task() * sync_child_event() - * fput(parent_event->filp) - * perf_release() - * mutex_lock(&ctx->mutex) + * put_event() + * mutex_lock(&ctx->mutex) * * But since its the parent context it won't be the same instance. */ @@ -6655,7 +6661,7 @@ static void perf_free_event(struct perf_event *event, list_del_init(&event->child_list); mutex_unlock(&parent->child_mutex); - fput(parent->filp); + put_event(parent); perf_group_detach(event); list_del_event(event, ctx); @@ -6735,6 +6741,12 @@ inherit_event(struct perf_event *parent_event, NULL, NULL); if (IS_ERR(child_event)) return child_event; + + if (!atomic_long_inc_not_zero(&parent_event->refcount)) { + free_event(child_event); + return NULL; + } + get_ctx(child_ctx); /* @@ -6775,14 +6787,6 @@ inherit_event(struct perf_event *parent_event, add_event_to_ctx(child_event, child_ctx); raw_spin_unlock_irqrestore(&child_ctx->lock, flags); - /* - * Get a reference to the parent filp - we will fput it - * when the child event exits. This is safe to do because - * we are in the parent and we know that the filp still - * exists and has a nonzero count: - */ - atomic_long_inc(&parent_event->filp->f_count); - /* * Link this into the parent event's child list */ -- GitLab From 2bafdfd612901af70fcea3cf1866e388eb68fdf0 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Fri, 14 Sep 2012 00:26:33 +0200 Subject: [PATCH 0413/1799] ACPI / PM: Fix resource_lock dead lock in acpi_power_on_device commit 40bf66ec9791f1452b90b82aadc3b6e6aee201f5 upstream. Commit 0090def("ACPI: Add interface to register/unregister device to/from power resources") used resource_lock to protect the devices list that relies on power resource. It caused a mutex dead lock, as below acpi_power_on ---> lock resource_lock __acpi_power_on acpi_power_on_device acpi_power_get_inferred_state acpi_power_get_list_state ---> lock resource_lock This patch adds a new mutex "devices_lock" to protect the devices list and calls acpi_power_on_device in acpi_power_on, instead of __acpi_power_on, after the resource_lock is released. [rjw: Changed data type of a boolean variable to bool.] Signed-off-by: Lin Ming Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/power.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 0500f719f63e..7bdb676b089b 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -103,6 +103,7 @@ struct acpi_power_resource { /* List of devices relying on this power resource */ struct acpi_power_resource_device *devices; + struct mutex devices_lock; }; static struct list_head acpi_power_resource_list; @@ -221,7 +222,6 @@ static void acpi_power_on_device(struct acpi_power_managed_device *device) static int __acpi_power_on(struct acpi_power_resource *resource) { - struct acpi_power_resource_device *device_list = resource->devices; acpi_status status = AE_OK; status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); @@ -234,19 +234,15 @@ static int __acpi_power_on(struct acpi_power_resource *resource) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", resource->name)); - while (device_list) { - acpi_power_on_device(device_list->device); - - device_list = device_list->next; - } - return 0; } static int acpi_power_on(acpi_handle handle) { int result = 0; + bool resume_device = false; struct acpi_power_resource *resource = NULL; + struct acpi_power_resource_device *device_list; result = acpi_power_get_context(handle, &resource); if (result) @@ -262,10 +258,25 @@ static int acpi_power_on(acpi_handle handle) result = __acpi_power_on(resource); if (result) resource->ref_count--; + else + resume_device = true; } mutex_unlock(&resource->resource_lock); + if (!resume_device) + return result; + + mutex_lock(&resource->devices_lock); + + device_list = resource->devices; + while (device_list) { + acpi_power_on_device(device_list->device); + device_list = device_list->next; + } + + mutex_unlock(&resource->devices_lock); + return result; } @@ -351,7 +362,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, if (acpi_power_get_context(res_handle, &resource)) return; - mutex_lock(&resource->resource_lock); + mutex_lock(&resource->devices_lock); prev = NULL; curr = resource->devices; while (curr) { @@ -368,7 +379,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, prev = curr; curr = curr->next; } - mutex_unlock(&resource->resource_lock); + mutex_unlock(&resource->devices_lock); } /* Unlink dev from all power resources in _PR0 */ @@ -409,10 +420,10 @@ static int __acpi_power_resource_register_device( power_resource_device->device = powered_device; - mutex_lock(&resource->resource_lock); + mutex_lock(&resource->devices_lock); power_resource_device->next = resource->devices; resource->devices = power_resource_device; - mutex_unlock(&resource->resource_lock); + mutex_unlock(&resource->devices_lock); return 0; } @@ -715,6 +726,7 @@ static int acpi_power_add(struct acpi_device *device) resource->device = device; mutex_init(&resource->resource_lock); + mutex_init(&resource->devices_lock); strcpy(resource->name, device->pnp.bus_id); strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_POWER_CLASS); -- GitLab From 8889866c58f77c557e79a30853ee4fd5f50780ef Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Fri, 14 Sep 2012 20:54:44 +0200 Subject: [PATCH 0414/1799] ACPI / PM: Use KERN_DEBUG when no power resources are found commit f25b70613c048ceb1df052576fda03321ebf41cf upstream. commit a606dac368eed5696fb38e16b1394f1d049c09e9 adds support to link devices which have _PRx, if a device does not have _PRx, a warning message will be printed. This commit is for ZPODD on Intel ZPODD capable platforms, on other platforms, it has no problem if there is no power resource for this device, so a warning here is not appropriate, change it to debug. Reported-by: Borislav Petkov Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 7bdb676b089b..2adef535f15e 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -468,7 +468,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle) return ret; no_power_resource: - printk(KERN_WARNING PREFIX "Invalid Power Resource to register!"); + printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!"); return -ENODEV; } -- GitLab From 3a4781e12d0e6264c76bfd110783321450138169 Mon Sep 17 00:00:00 2001 From: Lauri Hintsala Date: Tue, 17 Jul 2012 17:16:09 +0300 Subject: [PATCH 0415/1799] mmc: mxs-mmc: fix deadlock in SDIO IRQ case commit 1af36b2a993dddfa3d6860ec4879c9e8abc9b976 upstream. Release the lock before mmc_signal_sdio_irq is called by mxs_mmc_irq_handler. Backtrace: [ 79.660000] ============================================= [ 79.660000] [ INFO: possible recursive locking detected ] [ 79.660000] 3.4.0-00009-g3e96082-dirty #11 Not tainted [ 79.660000] --------------------------------------------- [ 79.660000] swapper/0 is trying to acquire lock: [ 79.660000] (&(&host->lock)->rlock#2){-.....}, at: [] mxs_mmc_enable_sdio_irq+0x18/0xd4 [ 79.660000] [ 79.660000] but task is already holding lock: [ 79.660000] (&(&host->lock)->rlock#2){-.....}, at: [] mxs_mmc_irq_handler+0x1c/0xe8 [ 79.660000] [ 79.660000] other info that might help us debug this: [ 79.660000] Possible unsafe locking scenario: [ 79.660000] [ 79.660000] CPU0 [ 79.660000] ---- [ 79.660000] lock(&(&host->lock)->rlock#2); [ 79.660000] lock(&(&host->lock)->rlock#2); [ 79.660000] [ 79.660000] *** DEADLOCK *** [ 79.660000] [ 79.660000] May be due to missing lock nesting notation [ 79.660000] [ 79.660000] 1 lock held by swapper/0: [ 79.660000] #0: (&(&host->lock)->rlock#2){-.....}, at: [] mxs_mmc_irq_handler+0x1c/0xe8 [ 79.660000] [ 79.660000] stack backtrace: [ 79.660000] [] (unwind_backtrace+0x0/0xf4) from [] (__lock_acquire+0x1948/0x1d48) [ 79.660000] [] (__lock_acquire+0x1948/0x1d48) from [] (lock_acquire+0xe0/0xf8) [ 79.660000] [] (lock_acquire+0xe0/0xf8) from [] (_raw_spin_lock_irqsave+0x44/0x58) [ 79.660000] [] (_raw_spin_lock_irqsave+0x44/0x58) from [] (mxs_mmc_enable_sdio_irq+0x18/0xd4) [ 79.660000] [] (mxs_mmc_enable_sdio_irq+0x18/0xd4) from [] (mxs_mmc_irq_handler+0xd4/0xe8) [ 79.660000] [] (mxs_mmc_irq_handler+0xd4/0xe8) from [] (handle_irq_event_percpu+0x70/0x254) [ 79.660000] [] (handle_irq_event_percpu+0x70/0x254) from [] (handle_irq_event+0x3c/0x5c) [ 79.660000] [] (handle_irq_event+0x3c/0x5c) from [] (handle_level_irq+0x90/0x110) [ 79.660000] [] (handle_level_irq+0x90/0x110) from [] (generic_handle_irq+0x38/0x50) [ 79.660000] [] (generic_handle_irq+0x38/0x50) from [] (handle_IRQ+0x30/0x84) [ 79.660000] [] (handle_IRQ+0x30/0x84) from [] (__irq_svc+0x38/0x60) [ 79.660000] [] (__irq_svc+0x38/0x60) from [] (default_idle+0x2c/0x40) [ 79.660000] [] (default_idle+0x2c/0x40) from [] (cpu_idle+0x64/0xcc) [ 79.660000] [] (cpu_idle+0x64/0xcc) from [] (start_kernel+0x244/0x2c8) [ 79.660000] BUG: spinlock lockup on CPU#0, swapper/0 [ 79.660000] lock: c398cb2c, .magic: dead4ead, .owner: swapper/0, .owner_cpu: 0 [ 79.660000] [] (unwind_backtrace+0x0/0xf4) from [] (do_raw_spin_lock+0xf0/0x144) [ 79.660000] [] (do_raw_spin_lock+0xf0/0x144) from [] (_raw_spin_lock_irqsave+0x4c/0x58) [ 79.660000] [] (_raw_spin_lock_irqsave+0x4c/0x58) from [] (mxs_mmc_enable_sdio_irq+0x18/0xd4) [ 79.660000] [] (mxs_mmc_enable_sdio_irq+0x18/0xd4) from [] (mxs_mmc_irq_handler+0xd4/0xe8) [ 79.660000] [] (mxs_mmc_irq_handler+0xd4/0xe8) from [] (handle_irq_event_percpu+0x70/0x254) [ 79.660000] [] (handle_irq_event_percpu+0x70/0x254) from [] (handle_irq_event+0x3c/0x5c) [ 79.660000] [] (handle_irq_event+0x3c/0x5c) from [] (handle_level_irq+0x90/0x110) [ 79.660000] [] (handle_level_irq+0x90/0x110) from [] (generic_handle_irq+0x38/0x50) [ 79.660000] [] (generic_handle_irq+0x38/0x50) from [] (handle_IRQ+0x30/0x84) [ 79.660000] [] (handle_IRQ+0x30/0x84) from [] (__irq_svc+0x38/0x60) [ 79.660000] [] (__irq_svc+0x38/0x60) from [] (default_idle+0x2c/0x40) [ 79.660000] [] (default_idle+0x2c/0x40) from [] (cpu_idle+0x64/0xcc) [ 79.660000] [] (cpu_idle+0x64/0xcc) from [] (start_kernel+0x244/0x2c8) Signed-off-by: Lauri Hintsala Acked-by: Shawn Guo Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/mxs-mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index e3f5af96ab87..b6def202bf4d 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -280,11 +280,11 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id) writel(stat & MXS_MMC_IRQ_BITS, host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR); + spin_unlock(&host->lock); + if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN)) mmc_signal_sdio_irq(host->mmc); - spin_unlock(&host->lock); - if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ) cmd->error = -ETIMEDOUT; else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ) -- GitLab From e66a381518f9ebf98cdc583d20ae706aa5d1dc28 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 22 Aug 2012 23:10:01 +0800 Subject: [PATCH 0416/1799] mmc: sdhci-esdhc: break out early if clock is 0 commit 74f330bceaa7b88d06062e1cac3d519a3dfc041e upstream. Since commit 30832ab56 ("mmc: sdhci: Always pass clock request value zero to set_clock host op") was merged, esdhc_set_clock starts hitting "if (clock == 0)" where ESDHC_SYSTEM_CONTROL has been operated. This causes SDHCI card-detection function being broken. Fix the regression by moving "if (clock == 0)" above ESDHC_SYSTEM_CONTROL operation. Signed-off-by: Shawn Guo Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sdhci-esdhc.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index b97b2f5dafdb..d25f9ab9a54d 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h @@ -48,14 +48,14 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) int div = 1; u32 temp; + if (clock == 0) + goto out; + temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK); sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); - if (clock == 0) - goto out; - while (host->max_clk / pre_div / 16 > clock && pre_div < 256) pre_div *= 2; -- GitLab From d409354d1b8a1e47b8f29887179949ec951ffe83 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Wed, 29 Aug 2012 15:05:36 +0900 Subject: [PATCH 0417/1799] mmc: card: Skip secure erase on MoviNAND; causes unrecoverable corruption. commit 3550ccdb9d8d350e526b809bf3dd92b550a74fe1 upstream. For several MoviNAND eMMC parts, there are known issues with secure erase and secure trim. For these specific MoviNAND devices, we skip these operations. Specifically, there is a bug in the eMMC firmware that causes unrecoverable corruption when the MMC is erased with MMC_CAP_ERASE enabled. References: http://forum.xda-developers.com/showthread.php?t=1644364 https://plus.google.com/111398485184813224730/posts/21pTYfTsCkB#111398485184813224730/posts/21pTYfTsCkB Signed-off-by: Ian Chen Reviewed-by: Namjae Jeon Acked-by: Jaehoon Chung Reviewed-by: Linus Walleij Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/card/block.c | 26 +++++++++++++++++++++++++- include/linux/mmc/card.h | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index dabec556ebb8..833ff16f5fe1 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1430,7 +1430,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) /* complete ongoing async transfer before issuing discard */ if (card->host->areq) mmc_blk_issue_rw_rq(mq, NULL); - if (req->cmd_flags & REQ_SECURE) + if (req->cmd_flags & REQ_SECURE && + !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN)) ret = mmc_blk_issue_secdiscard_rq(mq, req); else ret = mmc_blk_issue_discard_rq(mq, req); @@ -1730,6 +1731,7 @@ static int mmc_add_disk(struct mmc_blk_data *md) #define CID_MANFID_SANDISK 0x2 #define CID_MANFID_TOSHIBA 0x11 #define CID_MANFID_MICRON 0x13 +#define CID_MANFID_SAMSUNG 0x15 static const struct mmc_fixup blk_fixups[] = { @@ -1766,6 +1768,28 @@ static const struct mmc_fixup blk_fixups[] = MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc, MMC_QUIRK_LONG_READ_TIME), + /* + * On these Samsung MoviNAND parts, performing secure erase or + * secure trim can result in unrecoverable corruption due to a + * firmware bug. + */ + MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + END_FIXUP }; diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 629b823f8836..b5292f317f47 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -234,6 +234,7 @@ struct mmc_card { #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ #define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */ #define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ +#define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */ /* byte mode */ unsigned int poweroff_notify_state; /* eMMC4.5 notify feature */ #define MMC_NO_POWER_NOTIFICATION 0 -- GitLab From 93ee70835a254181a9d9c5750e9301b70899ad90 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 19 Jul 2012 18:28:26 +0200 Subject: [PATCH 0418/1799] oprofile, s390: Fix uninitialized memory access when writing to oprofilefs commit 81ff3478d9ba7f0b48b0abef740e542fd83adf79 upstream. If oprofilefs_ulong_from_user() is called with count equals zero, *val remains unchanged. Depending on the implementation it might be uninitialized. Fixing users of oprofilefs_ulong_ from_user(). We missed these s390 changes with: 913050b oprofile: Fix uninitialized memory access when writing to writing to oprofilefs Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- arch/s390/oprofile/init.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c index 2297be406c61..abe8722adda6 100644 --- a/arch/s390/oprofile/init.c +++ b/arch/s390/oprofile/init.c @@ -171,7 +171,7 @@ static ssize_t hw_interval_write(struct file *file, char const __user *buf, if (*offset) return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val < oprofile_min_interval) oprofile_hw_interval = oprofile_min_interval; @@ -214,7 +214,7 @@ static ssize_t hwsampler_zero_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val != 0) return -EINVAL; @@ -245,7 +245,7 @@ static ssize_t hwsampler_kernel_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val != 0 && val != 1) @@ -280,7 +280,7 @@ static ssize_t hwsampler_user_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val != 0 && val != 1) @@ -319,7 +319,7 @@ static ssize_t timer_enabled_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val != 0 && val != 1) -- GitLab From f0868b703758f19c2ced945c2c3fce1c151ab369 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 4 Sep 2012 16:07:18 +0100 Subject: [PATCH 0419/1799] ahci: Add alternate identifier for the 88SE9172 commit 17c60c6b763cb5b83b0185e7d38d01d18e55a05a upstream. This can also appear as 0x9192. Reported in bugzilla and confirmed with the board documentation for these boards. Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=42970 Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ahci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ebaf67e4b2bc..93cbc4484ccb 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -396,6 +396,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ { PCI_DEVICE(0x1b4b, 0x917a), .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ + { PCI_DEVICE(0x1b4b, 0x9192), + .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ { PCI_DEVICE(0x1b4b, 0x91a3), .driver_data = board_ahci_yes_fbs }, -- GitLab From cf499a04f9b5c8d2218257046b66b3062401673a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sun, 2 Sep 2012 15:41:34 +0200 Subject: [PATCH 0420/1799] kobject: fix oops with "input0: bad kobj_uevent_env content in show_uevent()" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 60e233a56609fd963c59e99bd75c663d63fa91b6 upstream. Fengguang Wu writes: > After the __devinit* removal series, I can still get kernel panic in > show_uevent(). So there are more sources of bug.. > > Debug patch: > > @@ -343,8 +343,11 @@ static ssize_t show_uevent(struct device > goto out; > > /* copy keys to file */ > - for (i = 0; i < env->envp_idx; i++) > + dev_err(dev, "uevent %d env[%d]: %s/.../%s\n", env->buflen, env->envp_idx, top_kobj->name, dev->kobj.name); > + for (i = 0; i < env->envp_idx; i++) { > + printk(KERN_ERR "uevent %d env[%d]: %s\n", (int)count, i, env->envp[i]); > count += sprintf(&buf[count], "%s\n", env->envp[i]); > + } > > Oops message, the env[] is again not properly initilized: > > [ 44.068623] input input0: uevent 61 env[805306368]: input0/.../input0 > [ 44.069552] uevent 0 env[0]: (null) This is a completely different CONFIG_HOTPLUG problem, only demonstrating another reason why CONFIG_HOTPLUG should go away. I had a hard time trying to disable it anyway ;-) The problem this time is lots of code assuming that a call to add_uevent_var() will guarantee that env->buflen > 0. This is not true if CONFIG_HOTPLUG is unset. So things like this end up overwriting env->envp_idx because the array index is -1: if (add_uevent_var(env, "MODALIAS=")) return -ENOMEM; len = input_print_modalias(&env->buf[env->buflen - 1], sizeof(env->buf) - env->buflen, dev, 0); Don't know what the best action is, given that there seem to be a *lot* of this around the kernel. This patch "fixes" the problem for me, but I don't know if it can be considered an appropriate fix. [ It is the correct fix for now, for 3.7 forcing CONFIG_HOTPLUG to always be on is the longterm fix, but it's too late for 3.6 and older kernels to resolve this that way - gregkh ] Reported-by: Fengguang Wu Signed-off-by: Bjørn Mork Tested-by: Fengguang Wu Signed-off-by: Greg Kroah-Hartman --- include/linux/kobject.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/kobject.h b/include/linux/kobject.h index fc615a97e2d3..1e57449395b1 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -224,7 +224,7 @@ static inline int kobject_uevent_env(struct kobject *kobj, static inline __printf(2, 3) int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) -{ return 0; } +{ return -ENOMEM; } static inline int kobject_action_type(const char *buf, size_t count, enum kobject_action *type) -- GitLab From e3c9398035cbf79a2ab75c2f43de999fc9a726f4 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Sun, 19 Aug 2012 14:41:03 +1200 Subject: [PATCH 0421/1799] Redefine ATOMIC_INIT and ATOMIC64_INIT to drop the casts commit 67a806d9499353fabd5b5ff07337f3aa88a1c3ba upstream. The following build error occurred during an alpha build: net/core/sock.c:274:36: error: initializer element is not constant Dave Anglin says: > Here is the line in sock.i: > > struct static_key memalloc_socks = ((struct static_key) { .enabled = > ((atomic_t) { (0) }) }); The above line contains two compound literals. It also uses a designated initializer to initialize the field enabled. A compound literal is not a constant expression. The location of the above statement isn't fully clear, but if a compound literal occurs outside the body of a function, the initializer list must consist of constant expressions. Signed-off-by: Mel Gorman Signed-off-by: Fengguang Wu Signed-off-by: Michael Cree Acked-by: Matt Turner Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/alpha/include/asm/atomic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h index 3bb7ffeae3bc..c2cbe4fc391c 100644 --- a/arch/alpha/include/asm/atomic.h +++ b/arch/alpha/include/asm/atomic.h @@ -14,8 +14,8 @@ */ -#define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) -#define ATOMIC64_INIT(i) ( (atomic64_t) { (i) } ) +#define ATOMIC_INIT(i) { (i) } +#define ATOMIC64_INIT(i) { (i) } #define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic64_read(v) (*(volatile long *)&(v)->counter) -- GitLab From dd8121960467e40388876403758334fa91516db2 Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Wed, 12 Sep 2012 13:26:55 +0300 Subject: [PATCH 0422/1799] digsig: add hash size comparision on signature verification commit bc01637a80f5b670bd70a0279d3f93fa8de1c96d upstream. When pkcs_1_v1_5_decode_emsa() returns without error and hash sizes do not match, hash comparision is not done and digsig_verify_rsa() returns no error. This is a bug and this patch fixes it. The bug was introduced in v3.3 by commit b35e286a640f ("lib/digsig: pkcs_1_v1_5_decode_emsa cleanup"). Signed-off-by: Dmitry Kasatkin Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- lib/digsig.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/digsig.c b/lib/digsig.c index 286d558033e2..8c0e62975c88 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -163,9 +163,11 @@ static int digsig_verify_rsa(struct key *key, memcpy(out1 + head, p, l); err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len); + if (err) + goto err; - if (!err && len == hlen) - err = memcmp(out2, h, hlen); + if (len != hlen || memcmp(out2, h, hlen)) + err = -EINVAL; err: mpi_free(in); -- GitLab From 1c55a12c2a3d5b54598e7ba04e2d0fcf858b9023 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 16 Aug 2012 16:46:12 +1000 Subject: [PATCH 0423/1799] md: Don't truncate size at 4TB for RAID0 and Linear commit 667a5313ecd7308d79629c0738b0db588b0b0a4e upstream. commit 27a7b260f71439c40546b43588448faac01adb93 md: Fix handling for devices from 2TB to 4TB in 0.90 metadata. changed 0.90 metadata handling to truncated size to 4TB as that is all that 0.90 can record. However for RAID0 and Linear, 0.90 doesn't need to record the size, so this truncation is not needed and causes working arrays to become too small. So avoid the truncation for RAID0 and Linear This bug was introduced in 3.1 and is suitable for any stable kernels from then onwards. As the offending commit was tagged for 'stable', any stable kernel that it was applied to should also get this patch. That includes at least 2.6.32, 2.6.33 and 3.0. (Thanks to Ben Hutchings for providing that list). Signed-off-by: Neil Brown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 9ee8ce3e9650..34f2c9378d09 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1143,8 +1143,11 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor ret = 0; } rdev->sectors = rdev->sb_start; - /* Limit to 4TB as metadata cannot record more than that */ - if (rdev->sectors >= (2ULL << 32)) + /* Limit to 4TB as metadata cannot record more than that. + * (not needed for Linear and RAID0 as metadata doesn't + * record this size) + */ + if (rdev->sectors >= (2ULL << 32) && sb->level >= 1) rdev->sectors = (2ULL << 32) - 2; if (rdev->sectors < ((sector_t)sb->size) * 2 && sb->level >= 1) @@ -1426,7 +1429,7 @@ super_90_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors) /* Limit to 4TB as metadata cannot record more than that. * 4TB == 2^32 KB, or 2*2^32 sectors. */ - if (num_sectors >= (2ULL << 32)) + if (num_sectors >= (2ULL << 32) && rdev->mddev->level >= 1) num_sectors = (2ULL << 32) - 2; md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size, rdev->sb_page); -- GitLab From d765682ea82fb83fd8d01b7663f78b5d2f9fd839 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 19 Sep 2012 12:54:22 +1000 Subject: [PATCH 0424/1799] md: make sure metadata is updated when spares are activated or removed. commit 6dafab6b1383e912cd252fa809570b484eb6e0dc upstream. It isn't always necessary to update the metadata when spares are removed as the presence-or-not of a spare isn't really important to the integrity of an array. Also activating a spare doesn't always require updating the metadata as the update on 'recovery-completed' is usually sufficient. However the introduction of 'replacement' devices have made these transitions sometimes more important. For example the 'Replacement' flag isn't cleared until the original device is removed, so we need to ensure a metadata update after that 'spare' is removed. So set MD_CHANGE_DEVS whenever a spare is activated or removed, to complement the current situation where it is set when a spare is added or a device is failed (or a number of other less common situations). This is suitable for -stable as out-of-data metadata could lead to data corruption. This is only relevant for 3.3 and later 9when 'replacement' as introduced. Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 34f2c9378d09..529ce89b30bc 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7420,6 +7420,8 @@ static int remove_and_add_spares(struct mddev *mddev) } } } + if (removed) + set_bit(MD_CHANGE_DEVS, &mddev->flags); return spares; } @@ -7433,9 +7435,11 @@ static void reap_sync_thread(struct mddev *mddev) !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { /* success...*/ /* activate any spares */ - if (mddev->pers->spare_active(mddev)) + if (mddev->pers->spare_active(mddev)) { sysfs_notify(&mddev->kobj, NULL, "degraded"); + set_bit(MD_CHANGE_DEVS, &mddev->flags); + } } if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && mddev->pers->finish_reshape) -- GitLab From 9fd0132a29b4e40e5cf5ff82a02227b7f603bba7 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 19 Sep 2012 12:52:30 +1000 Subject: [PATCH 0425/1799] md/raid5: fix calculate of 'degraded' when a replacement becomes active. commit e5c86471f933608db5d43679f84cb4346c32033e upstream. When a replacement device becomes active, we mark the device that it replaces as 'faulty' so that it can subsequently get removed. However 'calc_degraded' only pays attention to the primary device, not the replacement, so the array appears to become degraded, which is wrong. So teach 'calc_degraded' to consider any replacement if a primary device is faulty. This is suitable for -stable as an incorrect 'degraded' value can confuse md and could lead to data corruption. This is only relevant for 3.3 and later. Reported-by: Robin Hill Reported-by: John Drescher Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid5.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 73a58007eb99..0240576564dc 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -380,6 +380,8 @@ static int calc_degraded(struct r5conf *conf) degraded = 0; for (i = 0; i < conf->previous_raid_disks; i++) { struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); + if (rdev && test_bit(Faulty, &rdev->flags)) + rdev = rcu_dereference(conf->disks[i].replacement); if (!rdev || test_bit(Faulty, &rdev->flags)) degraded++; else if (test_bit(In_sync, &rdev->flags)) @@ -404,6 +406,8 @@ static int calc_degraded(struct r5conf *conf) degraded2 = 0; for (i = 0; i < conf->raid_disks; i++) { struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); + if (rdev && test_bit(Faulty, &rdev->flags)) + rdev = rcu_dereference(conf->disks[i].replacement); if (!rdev || test_bit(Faulty, &rdev->flags)) degraded2++; else if (test_bit(In_sync, &rdev->flags)) -- GitLab From 547ee164a63242ef14c41410615aa60aa164fce2 Mon Sep 17 00:00:00 2001 From: Paul Clements Date: Mon, 17 Sep 2012 14:09:02 -0700 Subject: [PATCH 0426/1799] nbd: clear waiting_queue on shutdown commit fded4e090c60100d709318896c79816d68d5b47d upstream. Fix a serious but uncommon bug in nbd which occurs when there is heavy I/O going to the nbd device while, at the same time, a failure (server, network) or manual disconnect of the nbd connection occurs. There is a small window between the time that the nbd_thread is stopped and the socket is shutdown where requests can continue to be queued to nbd's internal waiting_queue. When this happens, those requests are never completed or freed. The fix is to clear the waiting_queue on shutdown of the nbd device, in the same way that the nbd request queue (queue_head) is already being cleared. Signed-off-by: Paul Clements Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/block/nbd.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 061427a75d37..3c4c225d1981 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -445,6 +445,14 @@ static void nbd_clear_que(struct nbd_device *nbd) req->errors++; nbd_end_request(req); } + + while (!list_empty(&nbd->waiting_queue)) { + req = list_entry(nbd->waiting_queue.next, struct request, + queuelist); + list_del_init(&req->queuelist); + req->errors++; + nbd_end_request(req); + } } @@ -594,6 +602,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, nbd->file = NULL; nbd_clear_que(nbd); BUG_ON(!list_empty(&nbd->queue_head)); + BUG_ON(!list_empty(&nbd->waiting_queue)); if (file) fput(file); return 0; -- GitLab From a4dd7e6c27a37237f09d437a515a3330093d4f70 Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Sat, 1 Sep 2012 01:38:19 -0700 Subject: [PATCH 0427/1799] ASoC: samsung dma - Don't indicate support for pause/resume. commit 57b2d68863f281737d8596cb3d76d89d9cc54fd8 upstream. The pause and resume operations indicate that the stream can be un-paused/resumed from the exact location they were paused/suspended. This is not true for this driver, the pause and suspend triggers share the same code path with stop, they flush all pending DMA transfers. This drops all pending samples. The pause_release/resume triggers are the same as start, except that prepare won't be called beforehand, nothing will be enqueued to the DMA engine and nothing will happen (no audio). Removing the pause flag will let apps know that it isn't supported. Removing the resume flag will cause user space to call prepare and start instead of resume, so audio will continue playing when the system wakes up. Before removing the pause and resume flags, I tested this on an exynos 5250, using 'aplay -i'. Pause/un-pause leads to silence followed by a write error. Suspend/resume testing led to the same result. Removing the two flags fixes suspend/resume (since snd_pcm_prepare is called again). And leads to a proper reporting of pause not supported. Signed-off-by: Dylan Reid Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/samsung/dma.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index ddc6cde14e2a..2526ecada5f1 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c @@ -34,9 +34,7 @@ static const struct snd_pcm_hardware dma_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME, + SNDRV_PCM_INFO_MMAP_VALID, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U8 | @@ -246,15 +244,11 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: prtd->state |= ST_RUNNING; prtd->params->ops->trigger(prtd->params->ch); break; case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: prtd->state &= ~ST_RUNNING; prtd->params->ops->stop(prtd->params->ch); break; -- GitLab From aa7994f281a5e705b5f9cb13b3219fc346263872 Mon Sep 17 00:00:00 2001 From: Li Haifeng Date: Mon, 17 Sep 2012 14:09:21 -0700 Subject: [PATCH 0428/1799] mm/page_alloc: fix the page address of higher page's buddy calculation commit 0ba8f2d59304dfe69b59c034de723ad80f7ab9ac upstream. The heuristic method for buddy has been introduced since commit 43506fad21ca ("mm/page_alloc.c: simplify calculation of combined index of adjacent buddy lists"). But the page address of higher page's buddy was wrongly calculated, which will lead page_is_buddy to fail for ever. IOW, the heuristic method would be disabled with the wrong page address of higher page's buddy. Calculating the page address of higher page's buddy should be based higher_page with the offset between index of higher page and index of higher page's buddy. Signed-off-by: Haifeng Li Signed-off-by: Gavin Shan Reviewed-by: Michal Hocko Cc: KyongHo Cho Cc: Mel Gorman Cc: Minchan Kim Cc: Johannes Weiner 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 918330f71dba..88a6d87041df 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -579,7 +579,7 @@ static inline void __free_one_page(struct page *page, combined_idx = buddy_idx & page_idx; higher_page = page + (combined_idx - page_idx); buddy_idx = __find_buddy_index(combined_idx, order + 1); - higher_buddy = page + (buddy_idx - combined_idx); + higher_buddy = higher_page + (buddy_idx - combined_idx); if (page_is_buddy(higher_page, higher_buddy, order + 1)) { list_add_tail(&page->lru, &zone->free_area[order].free_list[migratetype]); -- GitLab From 6093dd2f5a10b5a071aa623be7927a6421762adb Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 17 Sep 2012 14:09:17 -0700 Subject: [PATCH 0429/1799] drivers/rtc/rtc-twl.c: ensure all interrupts are disabled during probe commit 8dcebaa9a0ae8a0487f4342f3d56d2cb1c980860 upstream. On some platforms, bootloaders are known to do some interesting RTC programming. Without going into the obscurities as to why this may be the case, suffice it to say the the driver should not make any assumptions about the state of the RTC when the driver loads. In particular, the driver probe should be sure that all interrupts are disabled until otherwise programmed. This was discovered when finding bursty I2C traffic every second on Overo platforms. This I2C overhead was keeping the SoC from hitting deep power states. The cause was found to be the RTC firing every second on the I2C-connected TWL PMIC. Special thanks to Felipe Balbi for suggesting to look for a rogue driver as the source of the I2C traffic rather than the I2C driver itself. Special thanks to Steve Sakoman for helping track down the source of the continuous RTC interrups on the Overo boards. Signed-off-by: Kevin Hilman Cc: Felipe Balbi Tested-by: Steve Sakoman Cc: Alessandro Zummo Tested-by: Shubhrajyoti Datta Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-twl.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 258abeabf624..63ccc0f9427f 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -495,6 +495,11 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) if (ret < 0) goto out1; + /* ensure interrupts are disabled, bootloaders can be strange */ + ret = twl_rtc_write_u8(0, REG_RTC_INTERRUPTS_REG); + if (ret < 0) + dev_warn(&pdev->dev, "unable to disable interrupt\n"); + /* init cached IRQ enable bits */ ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); if (ret < 0) -- GitLab From a95bb54b6345874159a82b93c67c49244d2433f2 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 19 Jun 2012 08:00:00 -0700 Subject: [PATCH 0430/1799] hwmon: (twl4030-madc-hwmon) Initialize uninitialized structure elements commit 73d7c119255615a26070f9d6cdb722a166a29015 upstream. twl4030_madc_conversion uses do_avg and type structure elements of twl4030_madc_request. Initialize structure to avoid random operation. Fix for: Coverity CID 200794 Uninitialized scalar variable. Cc: Keerthy Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Acked-by: Keerthy Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/twl4030-madc-hwmon.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c index 0018c7dd0097..1a174f0a3cde 100644 --- a/drivers/hwmon/twl4030-madc-hwmon.c +++ b/drivers/hwmon/twl4030-madc-hwmon.c @@ -44,12 +44,13 @@ static ssize_t madc_read(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct twl4030_madc_request req; + struct twl4030_madc_request req = { + .channels = 1 << attr->index, + .method = TWL4030_MADC_SW2, + .type = TWL4030_MADC_WAIT, + }; long val; - req.channels = (1 << attr->index); - req.method = TWL4030_MADC_SW2; - req.func_cb = NULL; val = twl4030_madc_conversion(&req); if (val < 0) return val; -- GitLab From 48f0f14ffb6ff4852922994d11fbda418d40100e Mon Sep 17 00:00:00 2001 From: Charles Wang Date: Mon, 20 Aug 2012 16:02:33 +0800 Subject: [PATCH 0431/1799] sched: Add missing call to calc_load_exit_idle() commit 749c8814f08f12baa4a9c2812a7c6ede7d69507d upstream. Azat Khuzhin reported high loadavg in Linux v3.6 After checking the upstream scheduler code, I found Peter's commit: 5167e8d5417b sched/nohz: Rewrite and fix load-avg computation -- again not fully applied, missing the call to calc_load_exit_idle(). After that idle exit in sampling window will always be calculated to non-idle, and the load will be higher than normal. This patch adds the missing call to calc_load_exit_idle(). Signed-off-by: Charles Wang Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1345449754-27130-1-git-send-email-muming.wq@gmail.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/time/tick-sched.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index fd4e160aa9c4..e60347797359 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -145,6 +145,7 @@ static void tick_nohz_update_jiffies(ktime_t now) tick_do_update_jiffies64(now); local_irq_restore(flags); + calc_load_exit_idle(); touch_softlockup_watchdog(); } -- GitLab From fea0071c60870fbebc605ef72d87668d72dbbd81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Locher?= Date: Mon, 27 Aug 2012 15:02:45 +0200 Subject: [PATCH 0432/1799] can: mcp251x: avoid repeated frame bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit cab32f39dcc5b35db96497dc0a026b5dea76e4e7 upstream. The MCP2515 has a silicon bug causing repeated frame transmission, see section 5 of MCP2515 Rev. B Silicon Errata Revision G (March 2007). Basically, setting TXBnCTRL.TXREQ in either SPI mode (00 or 11) will eventually cause the bug. The workaround proposed by Microchip is to use mode 00 and send a RTS command on the SPI bus to initiate the transmission. Signed-off-by: Benoît Locher Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/mcp251x.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 346785c56a25..9d6074273caa 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -83,6 +83,11 @@ #define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n)) #define INSTRUCTION_READ_RXB(n) (((n) == 0) ? 0x90 : 0x94) #define INSTRUCTION_RESET 0xC0 +#define RTS_TXB0 0x01 +#define RTS_TXB1 0x02 +#define RTS_TXB2 0x04 +#define INSTRUCTION_RTS(n) (0x80 | ((n) & 0x07)) + /* MPC251x registers */ #define CANSTAT 0x0e @@ -397,6 +402,7 @@ static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, int tx_buf_idx) { + struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); u32 sid, eid, exide, rtr; u8 buf[SPI_TRANSFER_BUF_LEN]; @@ -418,7 +424,10 @@ static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc; memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc); mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx); - mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ); + + /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */ + priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx); + mcp251x_spi_trans(priv->spi, 1); } static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, -- GitLab From 32e653056d900d3ecc984733dbfcea34c92bf6d0 Mon Sep 17 00:00:00 2001 From: Jianguo Wu Date: Mon, 17 Sep 2012 14:08:56 -0700 Subject: [PATCH 0433/1799] mm/ia64: fix a memory block size bug commit 05cf96398e1b6502f9e191291b715c7463c9d5dd upstream. I found following definition in include/linux/memory.h, in my IA64 platform, SECTION_SIZE_BITS is equal to 32, and MIN_MEMORY_BLOCK_SIZE will be 0. #define MIN_MEMORY_BLOCK_SIZE (1 << SECTION_SIZE_BITS) Because MIN_MEMORY_BLOCK_SIZE is int type and length of 32bits, so MIN_MEMORY_BLOCK_SIZE(1 << 32) will will equal to 0. Actually when SECTION_SIZE_BITS >= 31, MIN_MEMORY_BLOCK_SIZE will be wrong. This will cause wrong system memory infomation in sysfs. I think it should be: #define MIN_MEMORY_BLOCK_SIZE (1UL << SECTION_SIZE_BITS) And "echo offline > memory0/state" will cause following call trace: kernel BUG at mm/memory_hotplug.c:885! sh[6455]: bugcheck! 0 [1] Pid: 6455, CPU 0, comm: sh psr : 0000101008526030 ifs : 8000000000000fa4 ip : [] Not tainted (3.6.0-rc1) ip is at offline_pages+0x210/0xee0 Call Trace: show_stack+0x80/0xa0 show_regs+0x640/0x920 die+0x190/0x2c0 die_if_kernel+0x50/0x80 ia64_bad_break+0x3d0/0x6e0 ia64_native_leave_kernel+0x0/0x270 offline_pages+0x210/0xee0 alloc_pages_current+0x180/0x2a0 Signed-off-by: Jianguo Wu Signed-off-by: Jiang Liu Cc: "Luck, Tony" Reviewed-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/memory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/memory.h b/include/linux/memory.h index 1ac7f6e405f9..ff9a9f8e0ed9 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h @@ -19,7 +19,7 @@ #include #include -#define MIN_MEMORY_BLOCK_SIZE (1 << SECTION_SIZE_BITS) +#define MIN_MEMORY_BLOCK_SIZE (1UL << SECTION_SIZE_BITS) struct memory_block { unsigned long start_section_nr; -- GitLab From 967c0e4ab954d228ca87d85c523ae8a65c03cc5e Mon Sep 17 00:00:00 2001 From: qiuxishi Date: Mon, 17 Sep 2012 14:09:24 -0700 Subject: [PATCH 0434/1799] memory hotplug: fix section info double registration bug commit f14851af0ebb32745c6c5a2e400aa0549f9d20df upstream. There may be a bug when registering section info. For example, on my Itanium platform, the pfn range of node0 includes the other nodes, so other nodes' section info will be double registered, and memmap's page count will equal to 3. node0: start_pfn=0x100, spanned_pfn=0x20fb00, present_pfn=0x7f8a3, => 0x000100-0x20fc00 node1: start_pfn=0x80000, spanned_pfn=0x80000, present_pfn=0x80000, => 0x080000-0x100000 node2: start_pfn=0x100000, spanned_pfn=0x80000, present_pfn=0x80000, => 0x100000-0x180000 node3: start_pfn=0x180000, spanned_pfn=0x80000, present_pfn=0x80000, => 0x180000-0x200000 free_all_bootmem_node() register_page_bootmem_info_node() register_page_bootmem_info_section() When hot remove memory, we can't free the memmap's page because page_count() is 2 after put_page_bootmem(). sparse_remove_one_section() free_section_usemap() free_map_bootmem() put_page_bootmem() [akpm@linux-foundation.org: add code comment] Signed-off-by: Xishi Qiu Signed-off-by: Jiang Liu Acked-by: Mel Gorman Cc: "Luck, Tony" Cc: Yasuaki Ishimatsu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memory_hotplug.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 6629fafd6ce4..9ad7d1ef6ac1 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -127,9 +127,6 @@ static void register_page_bootmem_info_section(unsigned long start_pfn) struct mem_section *ms; struct page *page, *memmap; - if (!pfn_valid(start_pfn)) - return; - section_nr = pfn_to_section_nr(start_pfn); ms = __nr_to_section(section_nr); @@ -188,9 +185,16 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat) end_pfn = pfn + pgdat->node_spanned_pages; /* register_section info */ - for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) - register_page_bootmem_info_section(pfn); - + for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) { + /* + * Some platforms can assign the same pfn to multiple nodes - on + * node0 as well as nodeN. To avoid registering a pfn against + * multiple nodes we check that this pfn does not already + * reside in some other node. + */ + if (pfn_valid(pfn) && (pfn_to_nid(pfn) == node)) + register_page_bootmem_info_section(pfn); + } } #endif /* !CONFIG_SPARSEMEM_VMEMMAP */ -- GitLab From 449efd1d33fcf40a81f902ceed6a21a406f8d105 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 12 Sep 2012 12:44:30 +0100 Subject: [PATCH 0435/1799] xen/m2p: do not reuse kmap_op->dev_bus_addr commit 2fc136eecd0c647a6b13fcd00d0c41a1a28f35a5 upstream. If the caller passes a valid kmap_op to m2p_add_override, we use kmap_op->dev_bus_addr to store the original mfn, but dev_bus_addr is part of the interface with Xen and if we are batching the hypercalls it might not have been written by the hypervisor yet. That means that later on Xen will write to it and we'll think that the original mfn is actually what Xen has written to it. Rather than "stealing" struct members from kmap_op, keep using page->index to store the original mfn and add another parameter to m2p_remove_override to get the corresponding kmap_op instead. It is now responsibility of the caller to keep track of which kmap_op corresponds to a particular page in the m2p_override (gntdev, the only user of this interface that passes a valid kmap_op, is already doing that). Reported-and-Tested-By: Sander Eikelenboom Signed-off-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/xen/page.h | 3 ++- arch/x86/xen/p2m.c | 27 +++++++++++---------------- drivers/block/xen-blkback/blkback.c | 2 +- drivers/xen/gntdev.c | 5 +++-- drivers/xen/grant-table.c | 6 ++++-- include/xen/grant_table.h | 3 ++- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index c34f96c2f7a0..1bd321d00f26 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h @@ -50,7 +50,8 @@ extern unsigned long set_phys_range_identity(unsigned long pfn_s, extern int m2p_add_override(unsigned long mfn, struct page *page, struct gnttab_map_grant_ref *kmap_op); -extern int m2p_remove_override(struct page *page, bool clear_pte); +extern int m2p_remove_override(struct page *page, + struct gnttab_map_grant_ref *kmap_op); extern struct page *m2p_find_override(unsigned long mfn); extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 00a038540c8e..3ace81769478 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -714,9 +714,6 @@ int m2p_add_override(unsigned long mfn, struct page *page, xen_mc_issue(PARAVIRT_LAZY_MMU); } - /* let's use dev_bus_addr to record the old mfn instead */ - kmap_op->dev_bus_addr = page->index; - page->index = (unsigned long) kmap_op; } spin_lock_irqsave(&m2p_override_lock, flags); list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); @@ -743,7 +740,8 @@ int m2p_add_override(unsigned long mfn, struct page *page, return 0; } EXPORT_SYMBOL_GPL(m2p_add_override); -int m2p_remove_override(struct page *page, bool clear_pte) +int m2p_remove_override(struct page *page, + struct gnttab_map_grant_ref *kmap_op) { unsigned long flags; unsigned long mfn; @@ -773,10 +771,8 @@ int m2p_remove_override(struct page *page, bool clear_pte) WARN_ON(!PagePrivate(page)); ClearPagePrivate(page); - if (clear_pte) { - struct gnttab_map_grant_ref *map_op = - (struct gnttab_map_grant_ref *) page->index; - set_phys_to_machine(pfn, map_op->dev_bus_addr); + set_phys_to_machine(pfn, page->index); + if (kmap_op != NULL) { if (!PageHighMem(page)) { struct multicall_space mcs; struct gnttab_unmap_grant_ref *unmap_op; @@ -788,13 +784,13 @@ int m2p_remove_override(struct page *page, bool clear_pte) * issued. In this case handle is going to -1 because * it hasn't been modified yet. */ - if (map_op->handle == -1) + if (kmap_op->handle == -1) xen_mc_flush(); /* - * Now if map_op->handle is negative it means that the + * Now if kmap_op->handle is negative it means that the * hypercall actually returned an error. */ - if (map_op->handle == GNTST_general_error) { + if (kmap_op->handle == GNTST_general_error) { printk(KERN_WARNING "m2p_remove_override: " "pfn %lx mfn %lx, failed to modify kernel mappings", pfn, mfn); @@ -804,8 +800,8 @@ int m2p_remove_override(struct page *page, bool clear_pte) mcs = xen_mc_entry( sizeof(struct gnttab_unmap_grant_ref)); unmap_op = mcs.args; - unmap_op->host_addr = map_op->host_addr; - unmap_op->handle = map_op->handle; + unmap_op->host_addr = kmap_op->host_addr; + unmap_op->handle = kmap_op->handle; unmap_op->dev_bus_addr = 0; MULTI_grant_table_op(mcs.mc, @@ -816,10 +812,9 @@ int m2p_remove_override(struct page *page, bool clear_pte) set_pte_at(&init_mm, address, ptep, pfn_pte(pfn, PAGE_KERNEL)); __flush_tlb_single(address); - map_op->host_addr = 0; + kmap_op->host_addr = 0; } - } else - set_phys_to_machine(pfn, page->index); + } /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present * somewhere in this domain, even before being added to the diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 73f196ca713f..c6decb901e5e 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -337,7 +337,7 @@ static void xen_blkbk_unmap(struct pending_req *req) invcount++; } - ret = gnttab_unmap_refs(unmap, pages, invcount, false); + ret = gnttab_unmap_refs(unmap, NULL, pages, invcount); BUG_ON(ret); } diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 1ffd03bf8e10..7f1241608489 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -314,8 +314,9 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages) } } - err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages + offset, - pages, true); + err = gnttab_unmap_refs(map->unmap_ops + offset, + use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset, + pages); if (err) return err; diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index f100ce20b16b..fda491cd53c1 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -774,7 +774,8 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, EXPORT_SYMBOL_GPL(gnttab_map_refs); int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, - struct page **pages, unsigned int count, bool clear_pte) + struct gnttab_map_grant_ref *kmap_ops, + struct page **pages, unsigned int count) { int i, ret; @@ -786,7 +787,8 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, return ret; for (i = 0; i < count; i++) { - ret = m2p_remove_override(pages[i], clear_pte); + ret = m2p_remove_override(pages[i], kmap_ops ? + &kmap_ops[i] : NULL); if (ret) return ret; } diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 15f8a00ff003..f0037a89f7db 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -185,6 +185,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, struct gnttab_map_grant_ref *kmap_ops, struct page **pages, unsigned int count); int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, - struct page **pages, unsigned int count, bool clear_pte); + struct gnttab_map_grant_ref *kunmap_ops, + struct page **pages, unsigned int count); #endif /* __ASM_GNTTAB_H__ */ -- GitLab From 02fc6e74ca8c7751b7764894fb4c9da5609c79b5 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Fri, 17 Aug 2012 10:22:37 -0400 Subject: [PATCH 0436/1799] xen/boot: Disable NUMA for PV guests. commit 8d54db795dfb1049d45dc34f0dddbc5347ec5642 upstream. The hypervisor is in charge of allocating the proper "NUMA" memory and dealing with the CPU scheduler to keep them bound to the proper NUMA node. The PV guests (and PVHVM) have no inkling of where they run and do not need to know that right now. In the future we will need to inject NUMA configuration data (if a guest spans two or more NUMA nodes) so that the kernel can make the right choices. But those patches are not yet present. In the meantime, disable the NUMA capability in the PV guest, which also fixes a bootup issue. Andre says: "we see Dom0 crashes due to the kernel detecting the NUMA topology not by ACPI, but directly from the northbridge (CONFIG_AMD_NUMA). This will detect the actual NUMA config of the physical machine, but will crash about the mismatch with Dom0's virtual memory. Variation of the theme: Dom0 sees what it's not supposed to see. This happens with the said config option enabled and on a machine where this scanning is still enabled (K8 and Fam10h, not Bulldozer class) We have this dump then: NUMA: Warning: node ids are out of bound, from=-1 to=-1 distance=10 Scanning NUMA topology in Northbridge 24 Number of physical nodes 4 Node 0 MemBase 0000000000000000 Limit 0000000040000000 Node 1 MemBase 0000000040000000 Limit 0000000138000000 Node 2 MemBase 0000000138000000 Limit 00000001f8000000 Node 3 MemBase 00000001f8000000 Limit 0000000238000000 Initmem setup node 0 0000000000000000-0000000040000000 NODE_DATA [000000003ffd9000 - 000000003fffffff] Initmem setup node 1 0000000040000000-0000000138000000 NODE_DATA [0000000137fd9000 - 0000000137ffffff] Initmem setup node 2 0000000138000000-00000001f8000000 NODE_DATA [00000001f095e000 - 00000001f0984fff] Initmem setup node 3 00000001f8000000-0000000238000000 Cannot find 159744 bytes in node 3 BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] __alloc_bootmem_node+0x43/0x96 Pid: 0, comm: swapper Not tainted 3.3.6 #1 AMD Dinar/Dinar RIP: e030:[] [] __alloc_bootmem_node+0x43/0x96 .. snip.. [] sparse_early_usemaps_alloc_node+0x64/0x178 [] sparse_init+0xe4/0x25a [] paging_init+0x13/0x22 [] setup_arch+0x9c6/0xa9b [] ? printk+0x3c/0x3e [] start_kernel+0xe5/0x468 [] x86_64_start_reservations+0xba/0xc1 [] ? xen_setup_runstate_info+0x2c/0x36 [] xen_start_kernel+0x565/0x56c " so we just disable NUMA scanning by setting numa_off=1. Reported-and-Tested-by: Andre Przywara Acked-by: Andre Przywara Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/setup.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 99de967762a8..017d48a26a02 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -431,4 +432,7 @@ void __init xen_arch_setup(void) disable_cpufreq(); WARN_ON(set_pm_idle_to_default()); fiddle_vdso(); +#ifdef CONFIG_NUMA + numa_off = 1; +#endif } -- GitLab From b5b937dae933e1997300ffa2f6c45759a849bee0 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Sun, 23 Sep 2012 20:27:32 +0200 Subject: [PATCH 0437/1799] hwmon: (fam15h_power) Tweak runavg_range on resume commit 5f0ecb907deb1e6f28071ee3bd568903b9da1be4 upstream. The quirk introduced with commit 00250ec90963b7ef6678438888f3244985ecde14 (hwmon: fam15h_power: fix bogus values with current BIOSes) is not only required during driver load but also when system resumes from suspend. The BIOS might set the previously recommended (but unsuitable) initilization value for the running average range register during resume. Signed-off-by: Andreas Herrmann Tested-by: Andreas Hartmann Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/fam15h_power.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index e8e18cab1fb8..ac2d6cb39e7d 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -128,12 +128,12 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4) * counter saturations resulting in bogus power readings. * We correct this value ourselves to cope with older BIOSes. */ -static DEFINE_PCI_DEVICE_TABLE(affected_device) = { +static const struct pci_device_id affected_device[] = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, { 0 } }; -static void __devinit tweak_runavg_range(struct pci_dev *pdev) +static void tweak_runavg_range(struct pci_dev *pdev) { u32 val; @@ -157,6 +157,16 @@ static void __devinit tweak_runavg_range(struct pci_dev *pdev) REG_TDP_RUNNING_AVERAGE, val); } +#ifdef CONFIG_PM +static int fam15h_power_resume(struct pci_dev *pdev) +{ + tweak_runavg_range(pdev); + return 0; +} +#else +#define fam15h_power_resume NULL +#endif + static void __devinit fam15h_power_init_data(struct pci_dev *f4, struct fam15h_power_data *data) { @@ -255,6 +265,7 @@ static struct pci_driver fam15h_power_driver = { .id_table = fam15h_power_id_table, .probe = fam15h_power_probe, .remove = __devexit_p(fam15h_power_remove), + .resume = fam15h_power_resume, }; static int __init fam15h_power_init(void) -- GitLab From 17c7900f51d4cef95f95bbf3743bc9d19075052d Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 11 Sep 2012 13:39:08 -0700 Subject: [PATCH 0438/1799] hwmon: (ads7871) Add 'name' sysfs attribute commit 4e21f4eaa49f78d3e977e316514c941053871c76 upstream. The 'name' sysfs attribute is mandatory for hwmon devices, but was missing in this driver. Cc: Paul Thomas Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Acked-by: Paul Thomas Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/ads7871.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c index e65c6e45d36b..7bf4ce3d405e 100644 --- a/drivers/hwmon/ads7871.c +++ b/drivers/hwmon/ads7871.c @@ -139,6 +139,12 @@ static ssize_t show_voltage(struct device *dev, } } +static ssize_t ads7871_show_name(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); +} + static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_voltage, NULL, 0); static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 1); static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 2); @@ -148,6 +154,8 @@ static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 5); static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 6); static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 7); +static DEVICE_ATTR(name, S_IRUGO, ads7871_show_name, NULL); + static struct attribute *ads7871_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, @@ -157,6 +165,7 @@ static struct attribute *ads7871_attributes[] = { &sensor_dev_attr_in5_input.dev_attr.attr, &sensor_dev_attr_in6_input.dev_attr.attr, &sensor_dev_attr_in7_input.dev_attr.attr, + &dev_attr_name.attr, NULL }; -- GitLab From 3f4d6d765aedf4c52195d1d3938b6c404a2f6555 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 11 Sep 2012 13:43:17 -0700 Subject: [PATCH 0439/1799] hwmon: (ad7314) Add 'name' sysfs attribute commit 3ceefe4319636d89d4bdf40dca9471970f942e4f upstream. The 'name' sysfs attribute is mandatory for hwmon devices, but was missing in this driver. Cc: Jonathan Cameron Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/ad7314.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c index f85ce70d9677..9815f9cc8f7a 100644 --- a/drivers/hwmon/ad7314.c +++ b/drivers/hwmon/ad7314.c @@ -94,10 +94,18 @@ static ssize_t ad7314_show_temperature(struct device *dev, } } +static ssize_t ad7314_show_name(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); +} + +static DEVICE_ATTR(name, S_IRUGO, ad7314_show_name, NULL); static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ad7314_show_temperature, NULL, 0); static struct attribute *ad7314_attributes[] = { + &dev_attr_name.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, NULL, }; -- GitLab From a3bd94a4566b2c107c3d9661076ba184af9f83ba Mon Sep 17 00:00:00 2001 From: Nestor Lopez Casado Date: Fri, 21 Sep 2012 12:21:34 +0200 Subject: [PATCH 0440/1799] HID: Fix logitech-dj: missing Unifying device issue commit 596264082f10dd4a567c43d4526b2f54ac5520bc upstream. This patch fixes an issue introduced after commit 4ea5454203d991ec ("HID: Fix race condition between driver core and ll-driver"). After that commit, hid-core discards any incoming packet that arrives while hid driver's probe function is being executed. This broke the enumeration process of hid-logitech-dj, that must receive control packets in-band with the mouse and keyboard packets. Discarding mouse or keyboard data at the very begining is usually fine, but it is not the case for control packets. This patch forces a re-enumeration of the paired devices when a packet arrives that comes from an unknown device. Based on a patch originally written by Benjamin Tissoires. Signed-off-by: Nestor Lopez Casado Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-logitech-dj.c | 41 +++++++++++++++++++++++++++++++++++ drivers/hid/hid-logitech-dj.h | 1 + 2 files changed, 42 insertions(+) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index d44ea58c597e..88d20101f85b 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -185,6 +185,7 @@ static struct hid_ll_driver logi_dj_ll_driver; static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, size_t count, unsigned char report_type); +static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev); static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, struct dj_report *dj_report) @@ -225,6 +226,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & SPFUNCTION_DEVICE_LIST_EMPTY) { dbg_hid("%s: device list is empty\n", __func__); + djrcv_dev->querying_devices = false; return; } @@ -235,6 +237,12 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, return; } + if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { + /* The device is already known. No need to reallocate it. */ + dbg_hid("%s: device is already known\n", __func__); + return; + } + dj_hiddev = hid_allocate_device(); if (IS_ERR(dj_hiddev)) { dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", @@ -298,6 +306,7 @@ static void delayedwork_callback(struct work_struct *work) struct dj_report dj_report; unsigned long flags; int count; + int retval; dbg_hid("%s\n", __func__); @@ -330,6 +339,25 @@ static void delayedwork_callback(struct work_struct *work) logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); break; default: + /* A normal report (i. e. not belonging to a pair/unpair notification) + * arriving here, means that the report arrived but we did not have a + * paired dj_device associated to the report's device_index, this + * means that the original "device paired" notification corresponding + * to this dj_device never arrived to this driver. The reason is that + * hid-core discards all packets coming from a device while probe() is + * executing. */ + if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) { + /* ok, we don't know the device, just re-ask the + * receiver for the list of connected devices. */ + retval = logi_dj_recv_query_paired_devices(djrcv_dev); + if (!retval) { + /* everything went fine, so just leave */ + break; + } + dev_err(&djrcv_dev->hdev->dev, + "%s:logi_dj_recv_query_paired_devices " + "error:%d\n", __func__, retval); + } dbg_hid("%s: unexpected report type\n", __func__); } } @@ -360,6 +388,12 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, if (!djdev) { dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" " is NULL, index %d\n", dj_report->device_index); + kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); + + if (schedule_work(&djrcv_dev->work) == 0) { + dbg_hid("%s: did not schedule the work item, was already " + "queued\n", __func__); + } return; } @@ -390,6 +424,12 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, if (dj_device == NULL) { dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" " is NULL, index %d\n", dj_report->device_index); + kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); + + if (schedule_work(&djrcv_dev->work) == 0) { + dbg_hid("%s: did not schedule the work item, was already " + "queued\n", __func__); + } return; } @@ -437,6 +477,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) return logi_dj_recv_send_report(djrcv_dev, &dj_report); } + static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, unsigned timeout) { diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h index fd28a5e0ca3b..4a4000340ce1 100644 --- a/drivers/hid/hid-logitech-dj.h +++ b/drivers/hid/hid-logitech-dj.h @@ -101,6 +101,7 @@ struct dj_receiver_dev { struct work_struct work; struct kfifo notif_fifo; spinlock_t lock; + bool querying_devices; }; struct dj_device { -- GitLab From 2ae637123f49eea55c12e2871f7acc28a601dccc Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 18 Sep 2012 14:21:01 -0400 Subject: [PATCH 0441/1799] cifs: fix return value in cifsConvertToUTF16 commit c73f693989d7a7d99ec66a7065295a0c93d0b127 upstream. This function returns the wrong value, which causes the callers to get the length of the resulting pathname wrong when it contains non-ASCII characters. This seems to fix https://bugzilla.samba.org/show_bug.cgi?id=6767 Reported-by: Baldvin Kovacs Reported-and-Tested-by: Nicolas Lefebvre Signed-off-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifs_unicode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index fbb9da951843..33ef60d8e2fb 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -328,6 +328,6 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen, } ctoUTF16_out: - return i; + return j; } -- GitLab From 1db67b66e816cc91335ce18179d97eb125e5a769 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 28 Aug 2012 01:53:54 +0000 Subject: [PATCH 0442/1799] vmwgfx: add dumb ioctl support commit 5e1782d224c79b26ab7d5c31e3f87657000714fb upstream. Testing and works with the -modesetting driver, Reviewed-by: Jakob Bornecrantz Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 5 ++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 10 ++++ drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 73 ++++++++++++++++++++++++ 3 files changed, 88 insertions(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 7279b3ec0124..3a4b15acd763 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1159,6 +1159,11 @@ static struct drm_driver driver = { .open = vmw_driver_open, .preclose = vmw_preclose, .postclose = vmw_postclose, + + .dumb_create = vmw_dumb_create, + .dumb_map_offset = vmw_dumb_map_offset, + .dumb_destroy = vmw_dumb_destroy, + .fops = &vmwgfx_driver_fops, .name = VMWGFX_DRIVER_NAME, .desc = VMWGFX_DRIVER_DESC, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index d0f2c079ee27..29c984ff7f23 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -645,6 +645,16 @@ int vmw_kms_readback(struct vmw_private *dev_priv, int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int vmw_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); + +int vmw_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset); +int vmw_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle); /** * Overlay control - vmwgfx_overlay.c */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index a37abb581cbb..059b32c6f22b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -1917,3 +1917,76 @@ int vmw_user_stream_lookup(struct vmw_private *dev_priv, vmw_resource_unreference(&res); return ret; } + + +int vmw_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + struct vmw_private *dev_priv = vmw_priv(dev); + struct vmw_master *vmaster = vmw_master(file_priv->master); + struct vmw_user_dma_buffer *vmw_user_bo; + struct ttm_buffer_object *tmp; + int ret; + + args->pitch = args->width * ((args->bpp + 7) / 8); + args->size = args->pitch * args->height; + + vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL); + if (vmw_user_bo == NULL) + return -ENOMEM; + + ret = ttm_read_lock(&vmaster->lock, true); + if (ret != 0) { + kfree(vmw_user_bo); + return ret; + } + + ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size, + &vmw_vram_sys_placement, true, + &vmw_user_dmabuf_destroy); + if (ret != 0) + goto out_no_dmabuf; + + tmp = ttm_bo_reference(&vmw_user_bo->dma.base); + ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile, + &vmw_user_bo->base, + false, + ttm_buffer_type, + &vmw_user_dmabuf_release, NULL); + if (unlikely(ret != 0)) + goto out_no_base_object; + + args->handle = vmw_user_bo->base.hash.key; + +out_no_base_object: + ttm_bo_unref(&tmp); +out_no_dmabuf: + ttm_read_unlock(&vmaster->lock); + return ret; +} + +int vmw_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset) +{ + struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; + struct vmw_dma_buffer *out_buf; + int ret; + + ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf); + if (ret != 0) + return -EINVAL; + + *offset = out_buf->base.addr_space_offset; + vmw_dmabuf_unreference(&out_buf); + return 0; +} + +int vmw_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle) +{ + return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, + handle, TTM_REF_USAGE); +} -- GitLab From 0bf2a827d745808dde90001134ecc6a4af39b361 Mon Sep 17 00:00:00 2001 From: Santiago Leon Date: Tue, 4 Sep 2012 14:41:37 +0000 Subject: [PATCH 0443/1799] ibmveth: Fix alignment of rx queue bug commit d90c92fee89ccd75ef2646f3bde0b4c0450666c3 upstream. This patch fixes a bug found by Nish Aravamudan (https://lkml.org/lkml/2012/5/15/220) where the driver is not following the spec (it is not aligning the rx buffer on a 16-byte boundary) and the hypervisor aborts the registration, making the device unusable. The fix follows BenH's recommendation (https://lkml.org/lkml/2012/7/20/461) to replace the kmalloc+map for a single call to dma_alloc_coherent() because that function always aligns to a 16-byte boundary. The stable trees will run into this bug whenever the rx buffer kmalloc call returns something not aligned on a 16-byte boundary. Signed-off-by: Santiago Leon Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/ibm/ibmveth.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 9010cea68bc3..b68d28a130e6 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -472,14 +472,9 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter) } if (adapter->rx_queue.queue_addr != NULL) { - if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) { - dma_unmap_single(dev, - adapter->rx_queue.queue_dma, - adapter->rx_queue.queue_len, - DMA_BIDIRECTIONAL); - adapter->rx_queue.queue_dma = DMA_ERROR_CODE; - } - kfree(adapter->rx_queue.queue_addr); + dma_free_coherent(dev, adapter->rx_queue.queue_len, + adapter->rx_queue.queue_addr, + adapter->rx_queue.queue_dma); adapter->rx_queue.queue_addr = NULL; } @@ -556,10 +551,13 @@ static int ibmveth_open(struct net_device *netdev) goto err_out; } + dev = &adapter->vdev->dev; + adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * rxq_entries; - adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, - GFP_KERNEL); + adapter->rx_queue.queue_addr = + dma_alloc_coherent(dev, adapter->rx_queue.queue_len, + &adapter->rx_queue.queue_dma, GFP_KERNEL); if (!adapter->rx_queue.queue_addr) { netdev_err(netdev, "unable to allocate rx queue pages\n"); @@ -567,19 +565,13 @@ static int ibmveth_open(struct net_device *netdev) goto err_out; } - dev = &adapter->vdev->dev; - adapter->buffer_list_dma = dma_map_single(dev, adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL); adapter->filter_list_dma = dma_map_single(dev, adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL); - adapter->rx_queue.queue_dma = dma_map_single(dev, - adapter->rx_queue.queue_addr, - adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL); if ((dma_mapping_error(dev, adapter->buffer_list_dma)) || - (dma_mapping_error(dev, adapter->filter_list_dma)) || - (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) { + (dma_mapping_error(dev, adapter->filter_list_dma))) { netdev_err(netdev, "unable to map filter or buffer list " "pages\n"); rc = -ENOMEM; -- GitLab From ba41a6df9e32ee5752165496017cadf700c14ca9 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 4 Sep 2012 17:44:45 +0300 Subject: [PATCH 0444/1799] mac80211: clear bssid on auth/assoc failure commit 3d2abdfdf14f4d6decc2023708211e19b096f4ca upstream. ifmgd->bssid wasn't cleared properly in some auth/assoc failure cases, causing mac80211 and the low-level driver to go out of sync. Clear ifmgd->bssid on failure, and notify the driver. Signed-off-by: Eliad Peller Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/mlme.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 25be6831ff09..abc31d7bd2a5 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3232,6 +3232,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, goto out_unlock; err_clear: + memset(ifmgd->bssid, 0, ETH_ALEN); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); ifmgd->auth_data = NULL; err_free: kfree(auth_data); @@ -3410,6 +3412,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, err = 0; goto out; err_clear: + memset(ifmgd->bssid, 0, ETH_ALEN); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); ifmgd->assoc_data = NULL; err_free: kfree(assoc_data); -- GitLab From 7c4a26d507774d22b7e6eb792046c203f71a0ab0 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Tue, 11 Sep 2012 21:16:47 +0200 Subject: [PATCH 0445/1799] brcmfmac: fix big endian bug in i-scan. commit ed205b361956c96e0d8c09a8c9135a6a79cd9541 upstream. ssid len is 32 bit and needs endian conversion for big endian systems. Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index d13ae9c299f2..e360939f7904 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -500,8 +500,10 @@ static void wl_iscan_prep(struct brcmf_scan_params_le *params_le, params_le->active_time = cpu_to_le32(-1); params_le->passive_time = cpu_to_le32(-1); params_le->home_time = cpu_to_le32(-1); - if (ssid && ssid->SSID_len) - memcpy(¶ms_le->ssid_le, ssid, sizeof(struct brcmf_ssid)); + if (ssid && ssid->SSID_len) { + params_le->ssid_le.SSID_len = cpu_to_le32(ssid->SSID_len); + memcpy(¶ms_le->ssid_le.SSID, ssid->SSID, ssid->SSID_len); + } } static s32 -- GitLab From d5217650d6e48503466a9192e2cd72c91c696f50 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Tue, 11 Sep 2012 21:16:48 +0200 Subject: [PATCH 0446/1799] brcmfmac: Fix big endian host configuration data. commit e020a83d0942a5aceac35986500c9834efc8707d upstream. Fixes big endian host configuration parameters. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- .../wireless/brcm80211/brcmfmac/dhd_common.c | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 4187435220f3..4db878dfc365 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -764,8 +764,11 @@ static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode) { char iovbuf[32]; int retcode; + __le32 arp_mode_le; - brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf)); + arp_mode_le = cpu_to_le32(arp_mode); + brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf, + sizeof(iovbuf)); retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); retcode = retcode >= 0 ? 0 : retcode; @@ -781,8 +784,11 @@ static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable) { char iovbuf[32]; int retcode; + __le32 arp_enable_le; - brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4, + arp_enable_le = cpu_to_le32(arp_enable); + + brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4, iovbuf, sizeof(iovbuf)); retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); @@ -803,10 +809,10 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) char buf[128], *ptr; u32 dongle_align = drvr->bus_if->align; u32 glom = 0; - u32 roaming = 1; - uint bcn_timeout = 3; - int scan_assoc_time = 40; - int scan_unassoc_time = 40; + __le32 roaming_le = cpu_to_le32(1); + __le32 bcn_timeout_le = cpu_to_le32(3); + __le32 scan_assoc_time_le = cpu_to_le32(40); + __le32 scan_unassoc_time_le = cpu_to_le32(40); int i; mutex_lock(&drvr->proto_block); @@ -841,14 +847,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) /* Setup timeout if Beacons are lost and roam is off to report link down */ - brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, + brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf, sizeof(iovbuf)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); /* Enable/Disable build-in roaming to allowed ext supplicant to take of romaing */ - brcmf_c_mkiovar("roam_off", (char *)&roaming, 4, + brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4, iovbuf, sizeof(iovbuf)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); @@ -863,9 +869,9 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) sizeof(iovbuf)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME, - (char *)&scan_assoc_time, sizeof(scan_assoc_time)); + (char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME, - (char *)&scan_unassoc_time, sizeof(scan_unassoc_time)); + (char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le)); /* Set and enable ARP offload feature */ brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE); -- GitLab From c68f32825bc8c3e046493262422e134a03adb6c6 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 21 Jun 2012 07:50:02 +0000 Subject: [PATCH 0447/1799] SCSI: lpfc: fix problems with -Werror commit 4bdd03e61b7a5c4c6bc2b25d46fcd491788fdfb3 upstream. Commit d38bd3aef ("Add -Werror compilation flag") is causing build breakage with random gcc incarnations. These look like gcc problems, but we shouldn't break the build because of a bad gcc. Fix this by adding a make flag WARNINGS_BECOME_ERRORS=1 which is the same as aic7xxx uses so ordinarily the build doesn't use -Werror Reported-by: Fengguang Wu Cc: Alex Iannicelli Cc: James Smart Cc: Jonathan Nieder Cc: Mike Pagano Signed-off-by: James Bottomley --- drivers/scsi/lpfc/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/lpfc/Makefile b/drivers/scsi/lpfc/Makefile index fe5d396aca73..e2516ba8ebfa 100644 --- a/drivers/scsi/lpfc/Makefile +++ b/drivers/scsi/lpfc/Makefile @@ -22,7 +22,9 @@ ccflags-$(GCOV) := -fprofile-arcs -ftest-coverage ccflags-$(GCOV) += -O0 +ifdef WARNINGS_BECOME_ERRORS ccflags-y += -Werror +endif obj-$(CONFIG_SCSI_LPFC) := lpfc.o -- GitLab From d39bdd32d086d55a4adf228a0af2874ee489cd61 Mon Sep 17 00:00:00 2001 From: "sreekanth.reddy@lsi.com" Date: Wed, 22 Aug 2012 16:55:13 +0530 Subject: [PATCH 0448/1799] SCSI: mpt2sas: Fix for issue - Unable to boot from the drive connected to HBA commit 10cce6d8b5af0b32bc4254ae4a28423a74c0921c upstream. This patch checks whether HBA is SAS2008 B0 controller. if it is a SAS2008 B0 controller then it use IO-APIC interrupt instead of MSIX, as SAS2008 B0 controller doesn't support MSIX interrupts. [jejb: fix whitespace problems] Signed-off-by: Sreekanth Reddy Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/mpt2sas/mpt2sas_base.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index c4cef569540b..db793621c403 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -1202,6 +1202,13 @@ _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc) u16 message_control; + /* Check whether controller SAS2008 B0 controller, + if it is SAS2008 B0 controller use IO-APIC instead of MSIX */ + if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 && + ioc->pdev->revision == 0x01) { + return -EINVAL; + } + base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX); if (!base) { dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not " -- GitLab From 4f04e027f76aefbcfc987af72e6727d40d8c654d Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 21 Aug 2012 10:35:53 -0700 Subject: [PATCH 0449/1799] SCSI: bnx2i: Fixed NULL ptr deference for 1G bnx2 Linux iSCSI offload commit d6532207116307eb7ecbfa7b9e02c53230096a50 upstream. This patch fixes the following kernel panic invoked by uninitialized fields in the chip initialization for the 1G bnx2 iSCSI offload. One of the bits in the chip initialization is being used by the latest firmware to control overflow packets. When this control bit gets enabled erroneously, it would ultimately result in a bad packet placement which would cause the bnx2 driver to dereference a NULL ptr in the placement handler. This can happen under certain stress I/O environment under the Linux iSCSI offload operation. This change only affects Broadcom's 5709 chipset. Unable to handle kernel NULL pointer dereference at 0000000000000008 RIP: [] :bnx2:bnx2_poll_work+0xd0d/0x13c5 Pid: 0, comm: swapper Tainted: G ---- 2.6.18-333.el5debug #2 RIP: 0010:[] [] :bnx2:bnx2_poll_work+0xd0d/0x13c5 RSP: 0018:ffff8101b575bd50 EFLAGS: 00010216 RAX: 0000000000000005 RBX: ffff81007c5fb180 RCX: 0000000000000000 RDX: 0000000000000ffc RSI: 00000000817e8000 RDI: 0000000000000220 RBP: ffff81015bbd7ec0 R08: ffff8100817e9000 R09: 0000000000000000 R10: ffff81007c5fb180 R11: 00000000000000c8 R12: 000000007a25a010 R13: 0000000000000000 R14: 0000000000000005 R15: ffff810159f80558 FS: 0000000000000000(0000) GS:ffff8101afebc240(0000) knlGS:0000000000000000 CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: 0000000000000008 CR3: 0000000000201000 CR4: 00000000000006a0 Process swapper (pid: 0, threadinfo ffff8101b5754000, task ffff8101afebd820) Stack: 000000000000000b ffff810159f80000 0000000000000040 ffff810159f80520 ffff810159f80500 00cf00cf8008e84b ffffc200100939e0 ffff810009035b20 0000502900000000 000000be00000001 ffff8100817e7810 00d08101b575bea8 Call Trace: [] show_schedstat+0x1c2/0x25b [] :bnx2:bnx2_poll+0xf6/0x231 [] net_rx_action+0xac/0x1b1 [] __do_softirq+0x89/0x133 [] call_softirq+0x1c/0x28 [] do_softirq+0x2c/0x7d [] do_IRQ+0xee/0xf7 [] ret_from_intr+0x0/0xa [] acpi_processor_idle_simple+0x1c5/0x341 [] acpi_processor_idle_simple+0x182/0x341 [] acpi_processor_idle_simple+0x0/0x341 [] cpu_idle+0x95/0xb8 [] start_secondary+0x479/0x488 Signed-off-by: Eddie Wai Reviewed-by: Mike Christie Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/bnx2i/bnx2i_hwi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index f9d6f4129093..72de3ba51657 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1264,6 +1264,9 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba) int rc = 0; u64 mask64; + memset(&iscsi_init, 0x00, sizeof(struct iscsi_kwqe_init1)); + memset(&iscsi_init2, 0x00, sizeof(struct iscsi_kwqe_init2)); + bnx2i_adjust_qp_size(hba); iscsi_init.flags = -- GitLab From c2cf6b0d20d0febfead4b29d87f9fc2e903127c0 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Fri, 14 Sep 2012 16:34:25 -0500 Subject: [PATCH 0450/1799] SCSI: hpsa: fix handling of protocol error commit 256d0eaac87da1e993190846064f339f4c7a63f5 upstream. If a command status of CMD_PROTOCOL_ERR is received, this information should be conveyed to the SCSI mid layer, not dropped on the floor. CMD_PROTOCOL_ERR may be received from the Smart Array for any commands destined for an external RAID controller such as a P2000, or commands destined for tape drives or CD/DVD-ROM drives, if for instance a cable is disconnected. This mostly affects multipath configurations, as disconnecting a cable on a non-multipath configuration is not going to do anything good regardless of whether CMD_PROTOCOL_ERR is handled correctly or not. Not handling CMD_PROTOCOL_ERR correctly in a multipath configaration involving external RAID controllers may cause data corruption, so this is quite a serious bug. This bug should not normally cause a problem for direct attached disk storage. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/hpsa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 500e20dd56ec..7c49e0ab90e4 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1264,8 +1264,9 @@ static void complete_scsi_command(struct CommandList *cp) } break; case CMD_PROTOCOL_ERR: + cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "cp %p has " - "protocol error \n", cp); + "protocol error\n", cp); break; case CMD_HARDWARE_ERR: cmd->result = DID_ERROR << 16; -- GitLab From f51909c0af2ebc533eaf48c7daff503b3e54d983 Mon Sep 17 00:00:00 2001 From: Wang Sen Date: Mon, 30 Jul 2012 14:25:06 +0800 Subject: [PATCH 0451/1799] SCSI: scsi: virtio-scsi: Fix address translation failure of HighMem pages used by sg list commit 27e99ade81368e6fdda3212bff9345177cf9e57a upstream. When using the commands below to write some data to a virtio-scsi LUN of the QEMU guest(32-bit) with 1G physical memory(qemu -m 1024), the qemu will crash. # sudo mkfs.ext4 /dev/sdb (/dev/sdb is the virtio-scsi LUN.) # sudo mount /dev/sdb /mnt # dd if=/dev/zero of=/mnt/file bs=1M count=1024 In current implementation, sg_set_buf is called to add buffers to sg list which is put into the virtqueue eventually. But if there are some HighMem pages in table->sgl you can not get virtual address by sg_virt. So, sg_virt(sg_elem) may return NULL value. This will cause QEMU exit when virtqueue_map_sg is called in QEMU because an invalid GPA is passed by virtqueue. Two solutions are discussed here: http://lkml.indiana.edu/hypermail/linux/kernel/1207.3/00675.html Finally, value assignment approach was adopted because: Value assignment creates a well-formed scatterlist, because the termination marker in source sg_list has been set in blk_rq_map_sg(). The last entry of the source sg_list is just copied to the the last entry in destination list. Note that, for now, virtio_ring does not care about the form of the scatterlist and simply processes the first out_num + in_num consecutive elements of the sg[] array. I have tested the patch on my workstation. QEMU would not crash any more. Signed-off-by: Wang Sen Acked-by: Paolo Bonzini Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/virtio_scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 1b3843117268..6661610c752e 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -198,7 +198,7 @@ static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx, int i; for_each_sg(table->sgl, sg_elem, table->nents, i) - sg_set_buf(&sg[idx++], sg_virt(sg_elem), sg_elem->length); + sg[idx++] = *sg_elem; *p_idx = idx; } -- GitLab From dcc8dbc21ff2052c0df6dee3e1a36c3ef4f1133c Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 29 Aug 2012 10:02:08 +0200 Subject: [PATCH 0452/1799] Bluetooth: mgmt: Fix enabling SSP while powered off commit 3d1cbdd6aefff711bcf389fdabc4af9bc22e8201 upstream. When new BT USB adapter is plugged in it's configured while still being powered off (HCI_AUTO_OFF flag is set), thus Set SSP will only set dev_flags but won't write changes to controller. As a result remote devices won't use Secure Simple Pairing with our device due to SSP Host Support flag disabled in extended features and may also reject SSP attempt from our side (with possible fallback to legacy pairing). This patch ensures HCI Write Simple Pairing Mode is sent when Set Powered is called to power on controller and clear HCI_AUTO_OFF flag. Signed-off-by: Andrzej Kaczmarek Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/mgmt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 4bb03b111122..78186b083869 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2801,6 +2801,12 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) if (scan) hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); + if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { + u8 ssp = 1; + + hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp); + } + update_class(hdev); update_name(hdev, hdev->dev_name); update_eir(hdev); -- GitLab From ec4d417c66a406bb464598220faf9f561d5b6d25 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 14 Sep 2012 16:34:46 -0300 Subject: [PATCH 0453/1799] Bluetooth: Fix not removing power_off delayed work commit 78c04c0bf52360dc2f7185e99c8e9aa05d73ae5a upstream. For example, when a usb reset is received (I could reproduce it running something very similar to this[1] in a loop) it could be that the device is unregistered while the power_off delayed work is still scheduled to run. Backtrace: WARNING: at lib/debugobjects.c:261 debug_print_object+0x7c/0x8d() Hardware name: To Be Filled By O.E.M. ODEBUG: free active (active state 0) object type: timer_list hint: delayed_work_timer_fn+0x0/0x26 Modules linked in: nouveau mxm_wmi btusb wmi bluetooth ttm coretemp drm_kms_helper Pid: 2114, comm: usb-reset Not tainted 3.5.0bt-next #2 Call Trace: [] ? free_obj_work+0x57/0x91 [] warn_slowpath_common+0x7e/0x97 [] warn_slowpath_fmt+0x41/0x43 [] debug_print_object+0x7c/0x8d [] ? __queue_work+0x259/0x259 [] ? debug_check_no_obj_freed+0x6f/0x1b5 [] debug_check_no_obj_freed+0x98/0x1b5 [] ? bt_host_release+0x10/0x1e [bluetooth] [] kfree+0x90/0xe6 [] bt_host_release+0x10/0x1e [bluetooth] [] device_release+0x4a/0x7e [] kobject_release+0x11d/0x154 [] kobject_put+0x4a/0x4f [] put_device+0x12/0x14 [] hci_free_dev+0x22/0x26 [bluetooth] [] btusb_disconnect+0x96/0x9f [btusb] [] usb_unbind_interface+0x57/0x106 [] __device_release_driver+0x83/0xd6 [] device_release_driver+0x20/0x2d [] usb_driver_release_interface+0x44/0x7b [] usb_forced_unbind_intf+0x45/0x4e [] usb_reset_device+0xa6/0x12e [] usbdev_do_ioctl+0x319/0xe20 [] ? avc_has_perm_flags+0xc9/0x12e [] ? avc_has_perm_flags+0x25/0x12e [] ? do_page_fault+0x31e/0x3a1 [] usbdev_ioctl+0x9/0xd [] vfs_ioctl+0x21/0x34 [] do_vfs_ioctl+0x408/0x44b [] ? file_has_perm+0x76/0x81 [] sys_ioctl+0x51/0x76 [] system_call_fastpath+0x16/0x1b [1] http://cpansearch.perl.org/src/DPAVLIN/Biblio-RFID-0.03/examples/usbreset.c Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hci_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index d6dc44cd15b0..0a30ec10d40f 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -750,6 +750,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) cancel_work_sync(&hdev->le_scan); + cancel_delayed_work(&hdev->power_off); + hci_req_cancel(hdev, ENODEV); hci_req_lock(hdev); -- GitLab From a6be20b8cd1e5e847c4191b8f249b939aaabf987 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 29 Aug 2012 10:02:09 +0200 Subject: [PATCH 0454/1799] Bluetooth: mgmt: Fix enabling LE while powered off commit 562fcc246ebe31ade6e1be08585673b9b2785498 upstream. When new BT USB adapter is plugged in it's configured while still being powered off (HCI_AUTO_OFF flag is set), thus Set LE will only set dev_flags but won't write changes to controller. As a result it's not possible to start device discovery session on LE controller as it uses interleaved discovery which requires LE Supported Host flag in extended features. This patch ensures HCI Write LE Host Supported is sent when Set Powered is called to power on controller and clear HCI_AUTO_OFF flag. Signed-off-by: Andrzej Kaczmarek Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/mgmt.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 78186b083869..8f3d9dc7013d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2807,6 +2807,16 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp); } + if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { + struct hci_cp_write_le_host_supported cp; + + cp.le = 1; + cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); + + hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, + sizeof(cp), &cp); + } + update_class(hdev); update_name(hdev, hdev->dev_name); update_eir(hdev); -- GitLab From 9f8a301630c67302cab77da0c4cb06272a95459d Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Mon, 27 Aug 2012 12:52:24 -0600 Subject: [PATCH 0455/1799] hpwdt: Fix kdump issue in hpwdt commit 308b135e4fcc00c80c07e0e04e7afa8edf78583c upstream. kdump can be interrupted by watchdog timer when the timer is left activated on the crash kernel. Changed the hpwdt driver to disable watchdog timer at boot-time. This assures that watchdog timer is disabled until /dev/watchdog is opened, and prevents watchdog timer to be left running on the crash kernel. Signed-off-by: Toshi Kani Tested-by: Lisa Mitchell Signed-off-by: Thomas Mingarelli Signed-off-by: Wim Van Sebroeck Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/hpwdt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 9f13b897fd64..6019929a54a5 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -806,6 +806,9 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev, hpwdt_timer_reg = pci_mem_addr + 0x70; hpwdt_timer_con = pci_mem_addr + 0x72; + /* Make sure that timer is disabled until /dev/watchdog is opened */ + hpwdt_stop(); + /* Make sure that we have a valid soft_margin */ if (hpwdt_change_timer(soft_margin)) hpwdt_change_timer(DEFAULT_MARGIN); -- GitLab From dca2dd18c62e3b90cb71534e0a715d246ce7196d Mon Sep 17 00:00:00 2001 From: Matthew Leach Date: Tue, 11 Sep 2012 17:56:57 +0100 Subject: [PATCH 0456/1799] ARM: 7532/1: decompressor: reset SCTLR.TRE for VMSA ARMv7 cores commit e1e5b7e4251c7538ca08c2c5545b0c2fbd8a6635 upstream. This patch zeroes the SCTLR.TRE bit prior to setting the mapping as cacheable for ARMv7 cores in the decompressor, ensuring that the memory region attributes are obtained from the C and B bits, not from the page tables. Cc: Nicolas Pitre Reviewed-by: Will Deacon Signed-off-by: Matthew Leach Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/boot/compressed/head.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index dc7e8ce8e6be..87278fc80d9f 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -648,6 +648,7 @@ __armv7_mmu_cache_on: mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs #endif mrc p15, 0, r0, c1, c0, 0 @ read control reg + bic r0, r0, #1 << 28 @ clear SCTLR.TRE orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement orr r0, r0, #0x003c @ write buffer #ifdef CONFIG_MMU -- GitLab From c648535596087f7d17458c293d69829ff6e60a6c Mon Sep 17 00:00:00 2001 From: Wen Congyang Date: Thu, 20 Sep 2012 14:04:47 +0800 Subject: [PATCH 0457/1799] tracing: Don't call page_to_pfn() if page is NULL commit 85f2a2ef1d0ab99523e0b947a2b723f5650ed6aa upstream. When allocating memory fails, page is NULL. page_to_pfn() will cause the kernel panicked if we don't use sparsemem vmemmap. Link: http://lkml.kernel.org/r/505AB1FF.8020104@cn.fujitsu.com Acked-by: Mel Gorman Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Andrew Morton Reviewed-by: Minchan Kim Signed-off-by: Wen Congyang Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- include/trace/events/kmem.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h index 5f889f16b0c8..08fa27244da7 100644 --- a/include/trace/events/kmem.h +++ b/include/trace/events/kmem.h @@ -214,7 +214,7 @@ TRACE_EVENT(mm_page_alloc, TP_printk("page=%p pfn=%lu order=%d migratetype=%d gfp_flags=%s", __entry->page, - page_to_pfn(__entry->page), + __entry->page ? page_to_pfn(__entry->page) : 0, __entry->order, __entry->migratetype, show_gfp_flags(__entry->gfp_flags)) @@ -240,7 +240,7 @@ DECLARE_EVENT_CLASS(mm_page, TP_printk("page=%p pfn=%lu order=%u migratetype=%d percpu_refill=%d", __entry->page, - page_to_pfn(__entry->page), + __entry->page ? page_to_pfn(__entry->page) : 0, __entry->order, __entry->migratetype, __entry->order == 0) -- GitLab From 0ed92b21f3807633c70f7565f92b034ef8bf4b1c Mon Sep 17 00:00:00 2001 From: Anisse Astier Date: Wed, 19 Sep 2012 11:10:48 -0700 Subject: [PATCH 0458/1799] Input: i8042 - disable mux on Toshiba C850D commit 8669cf6793bb38307a30fb6b9565ddc8840ebd3f upstream. On Toshiba Satellite C850D, the touchpad and the keyboard might randomly not work at boot. Preventing MUX mode activation solves this issue. Signed-off-by: Anisse Astier Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/serio/i8042-x86ia64io.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 6918773ce024..d6cc77a53c7e 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -333,6 +333,12 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"), }, }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"), + }, + }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"), -- GitLab From 870fefcd916e9766ff3ac689aa87e9f3abbe9381 Mon Sep 17 00:00:00 2001 From: Jovi Zhang Date: Wed, 22 Aug 2012 10:34:08 +0800 Subject: [PATCH 0459/1799] MIPS: mm: Add compound tail page _mapcount when mapped commit af89fa3986b9d034a286544ab1ed95096496a2f9 upstream. See commit b6999b191 which did the same modification for x86's mm/gup, Quote from commit b6999b191: "If compound pages are used and the page is a tail page, gup_huge_pmd() increases _mapcount to record tail page are mapped while gup_huge_pud does not do that." [ralf@linux-mips.org: fixed rejects caused by the original patch getting linewrapped.] Signed-off-by: Jovi Zhang Cc: Youquan Song Cc: Andi Kleen Patchwork: https://patchwork.linux-mips.org/patch/4291/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- arch/mips/mm/gup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/mm/gup.c b/arch/mips/mm/gup.c index 33aadbcf170b..dcfd573871c1 100644 --- a/arch/mips/mm/gup.c +++ b/arch/mips/mm/gup.c @@ -152,6 +152,8 @@ static int gup_huge_pud(pud_t pud, unsigned long addr, unsigned long end, do { VM_BUG_ON(compound_head(page) != head); pages[*nr] = page; + if (PageTail(page)) + get_huge_page_tail(page); (*nr)++; page++; refs++; -- GitLab From b9e8ad48eca69a02b03ea2beea38383d5f3f0b3f Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 11 Sep 2012 11:11:13 -0500 Subject: [PATCH 0460/1799] rtlwifi: rtl8192ce: Log message that B_CUT device may not work commit 022e1d0680c7b4366017393417b8758be5abcee8 upstream. There are a number of problems that occur for the latest version of the Realtek RTL8188CE device with the in-kernel driver. These include selection of the wrong firmware, and system lockup. A full fix is known, but is too invasive for inclusion in stable. This patch fixes the problem with loading the wrong firmware, and logs a message that the device may not work for kernels 3.6 and older. Signed-off-by: Larry Finger Cc: Anisse Astier Cc: Li Chaoming Tested-by: Anisse Astier Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/rtl8192ce/def.h | 1 + drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | 12 ++++++++++-- drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 6 ++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 04c3aef8a4f6..2925094b2d91 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -117,6 +117,7 @@ #define CHIP_VER_B BIT(4) #define CHIP_92C_BITMASK BIT(0) +#define CHIP_UNKNOWN BIT(7) #define CHIP_92C_1T2R 0x03 #define CHIP_92C 0x01 #define CHIP_88C 0x00 diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 5c4d9bc040f1..509f66195f2f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -995,8 +995,16 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw) version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C : VERSION_A_CHIP_88C; } else { - version = (value32 & TYPE_ID) ? VERSION_B_CHIP_92C : - VERSION_B_CHIP_88C; + version = (enum version_8192c) (CHIP_VER_B | + ((value32 & TYPE_ID) ? CHIP_92C_BITMASK : 0) | + ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0)); + if ((!IS_CHIP_VENDOR_UMC(version)) && (value32 & + CHIP_VER_RTL_MASK)) { + version = (enum version_8192c)(version | + ((((value32 & CHIP_VER_RTL_MASK) == BIT(12)) + ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) | + CHIP_VENDOR_UMC)); + } } switch (version) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 2c3b73366cd2..4e2a45839ed7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -162,10 +162,12 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) /* request fw */ if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && - !IS_92C_SERIAL(rtlhal->version)) + !IS_92C_SERIAL(rtlhal->version)) { rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin"; - else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) + } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin"; + pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n"); + } rtlpriv->max_fw_size = 0x4000; pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); -- GitLab From d83e6a4819844782ac16591a89c598342eef8627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Holm?= Date: Mon, 17 Sep 2012 21:50:57 +0000 Subject: [PATCH 0461/1799] asix: Support DLink DUB-E100 H/W Ver C1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit ed3770a9cd5764a575b83810ea679bbff2b03082 upstream. Signed-off-by: Søren Holm Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/asix.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 609fcc331595..ef84a586c176 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -1603,6 +1603,10 @@ static const struct usb_device_id products [] = { // DLink DUB-E100 H/W Ver B1 Alternate USB_DEVICE (0x2001, 0x3c05), .driver_info = (unsigned long) &ax88772_info, +}, { + // DLink DUB-E100 H/W Ver C1 + USB_DEVICE (0x2001, 0x1a02), + .driver_info = (unsigned long) &ax88772_info, }, { // Linksys USB1000 USB_DEVICE (0x1737, 0x0039), -- GitLab From 4a3aa6ef866b7128e57358858e053450ab97c41a Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 19 Sep 2012 14:58:45 +0200 Subject: [PATCH 0462/1799] can: ti_hecc: fix oops during rmmod commit ab04c8bd423edb03e2148350a091836c196107fc upstream. This patch fixes an oops which occurs when unloading the driver, while the network interface is still up. The problem is that first the io mapping is teared own, then the CAN device is unregistered, resulting in accessing the hardware's iomem: [ 172.744232] Unable to handle kernel paging request at virtual address c88b0040 [ 172.752441] pgd = c7be4000 [ 172.755645] [c88b0040] *pgd=87821811, *pte=00000000, *ppte=00000000 [ 172.762207] Internal error: Oops: 807 [#1] PREEMPT ARM [ 172.767517] Modules linked in: ti_hecc(-) can_dev [ 172.772430] CPU: 0 Not tainted (3.5.0alpha-00037-g3554cc0 #126) [ 172.778961] PC is at ti_hecc_close+0xb0/0x100 [ti_hecc] [ 172.784423] LR is at __dev_close_many+0x90/0xc0 [ 172.789123] pc : [] lr : [] psr: 60000013 [ 172.789123] sp : c5c1de68 ip : 00040081 fp : 00000000 [ 172.801025] r10: 00000001 r9 : c5c1c000 r8 : 00100100 [ 172.806457] r7 : c5d0a48c r6 : c5d0a400 r5 : 00000000 r4 : c5d0a000 [ 172.813232] r3 : c88b0000 r2 : 00000001 r1 : c5d0a000 r0 : c5d0a000 [ 172.820037] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user [ 172.827423] Control: 10c5387d Table: 87be4019 DAC: 00000015 [ 172.833404] Process rmmod (pid: 600, stack limit = 0xc5c1c2f0) [ 172.839447] Stack: (0xc5c1de68 to 0xc5c1e000) [ 172.843994] de60: bf00c6b8 c5c1dec8 c5d0a000 c5d0a000 00200200 c033be58 [ 172.852478] de80: c5c1de44 c5c1dec8 c5c1dec8 c033bf2c c5c1de90 c5c1de90 c5d0a084 c5c1de44 [ 172.860992] dea0: c5c1dec8 c033c098 c061d3dc c5d0a000 00000000 c05edf28 c05edb34 c000d724 [ 172.869476] dec0: 00000000 c033c2f8 c5d0a084 c5d0a084 00000000 c033c370 00000000 c5d0a000 [ 172.877990] dee0: c05edb00 c033c3b8 c5d0a000 bf00d3ac c05edb00 bf00d7c8 bf00d7c8 c02842dc [ 172.886474] df00: c02842c8 c0282f90 c5c1c000 c05edb00 bf00d7c8 c0283668 bf00d7c8 00000000 [ 172.894989] df20: c0611f98 befe2f80 c000d724 c0282d10 bf00d804 00000000 00000013 c0068a8c [ 172.903472] df40: c5c538e8 685f6974 00636365 c61571a8 c5cb9980 c61571a8 c6158a20 c00c9bc4 [ 172.911987] df60: 00000000 00000000 c5cb9980 00000000 c5cb9980 00000000 c7823680 00000006 [ 172.920471] df80: bf00d804 00000880 c5c1df8c 00000000 000d4267 befe2f80 00000001 b6d90068 [ 172.928985] dfa0: 00000081 c000d5a0 befe2f80 00000001 befe2f80 00000880 b6d90008 00000008 [ 172.937469] dfc0: befe2f80 00000001 b6d90068 00000081 00000001 00000000 befe2eac 00000000 [ 172.945983] dfe0: 00000000 befe2b18 00023ba4 b6e6addc 60000010 befe2f80 a8e00190 86d2d344 [ 172.954498] [] (ti_hecc_close+0xb0/0x100 [ti_hecc]) from [] (__dev__registered_many+0xc0/0x2a0) [ 172.984161] [] (rollback_registered_many+0xc0/0x2a0) from [] (rollback_registered+0x20/0x30) [ 172.994750] [] (rollback_registered+0x20/0x30) from [] (unregister_netdevice_queue+0x68/0x98) [ 173.005401] [] (unregister_netdevice_queue+0x68/0x98) from [] (unregister_netdev+0x18/0x20) [ 173.015899] [] (unregister_netdev+0x18/0x20) from [] (ti_hecc_remove+0x60/0x80 [ti_hecc]) [ 173.026245] [] (ti_hecc_remove+0x60/0x80 [ti_hecc]) from [] (platform_drv_remove+0x14/0x18) [ 173.036712] [] (platform_drv_remove+0x14/0x18) from [] (__device_release_driver+0x7c/0xbc) Tested-by: Jan Luebbe Cc: Anant Gole Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/ti_hecc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 4accd7ec6954..5ec27008ab4e 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -984,12 +984,12 @@ static int __devexit ti_hecc_remove(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct ti_hecc_priv *priv = netdev_priv(ndev); + unregister_candev(ndev); clk_disable(priv->clk); clk_put(priv->clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); iounmap(priv->base); release_mem_region(res->start, resource_size(res)); - unregister_candev(ndev); free_candev(ndev); platform_set_drvdata(pdev, NULL); -- GitLab From 12e58ca43097b5330e028f4087e7e4789c08abf7 Mon Sep 17 00:00:00 2001 From: "Ira W. Snyder" Date: Tue, 11 Sep 2012 15:58:15 -0700 Subject: [PATCH 0463/1799] can: janz-ican3: fix support for older hardware revisions commit e21093ef6fb4cbecdf926102286dbe280ae965db upstream. The Revision 1.0 Janz CMOD-IO Carrier Board does not have support for the reset registers. To support older hardware, the code is changed to use the hardware reset register on the Janz VMOD-ICAN3 hardware itself. Signed-off-by: Ira W. Snyder Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/janz-ican3.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 08c893cb7896..e7823dd989f4 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1250,7 +1250,6 @@ static irqreturn_t ican3_irq(int irq, void *dev_id) */ static int ican3_reset_module(struct ican3_dev *mod) { - u8 val = 1 << mod->num; unsigned long start; u8 runold, runnew; @@ -1264,8 +1263,7 @@ static int ican3_reset_module(struct ican3_dev *mod) runold = ioread8(mod->dpm + TARGET_RUNNING); /* reset the module */ - iowrite8(val, &mod->ctrl->reset_assert); - iowrite8(val, &mod->ctrl->reset_deassert); + iowrite8(0x00, &mod->dpmctrl->hwreset); /* wait until the module has finished resetting and is running */ start = jiffies; -- GitLab From 7334e402a35e0379933e8b0442f0baeed1104217 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 14 Sep 2012 15:36:57 -0700 Subject: [PATCH 0464/1799] cfg80211: fix possible circular lock on reg_regdb_search() commit a85d0d7f3460b1a123b78e7f7e39bf72c37dfb78 upstream. When call_crda() is called we kick off a witch hunt search for the same regulatory domain on our internal regulatory database and that work gets kicked off on a workqueue, this is done while the cfg80211_mutex is held. If that workqueue kicks off it will first lock reg_regdb_search_mutex and later cfg80211_mutex but to ensure two CPUs will not contend against cfg80211_mutex the right thing to do is to have the reg_regdb_search() wait until the cfg80211_mutex is let go. The lockdep report is pasted below. cfg80211: Calling CRDA to update world regulatory domain ====================================================== [ INFO: possible circular locking dependency detected ] 3.3.8 #3 Tainted: G O ------------------------------------------------------- kworker/0:1/235 is trying to acquire lock: (cfg80211_mutex){+.+...}, at: [<816468a4>] set_regdom+0x78c/0x808 [cfg80211] but task is already holding lock: (reg_regdb_search_mutex){+.+...}, at: [<81646828>] set_regdom+0x710/0x808 [cfg80211] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 (reg_regdb_search_mutex){+.+...}: [<800a8384>] lock_acquire+0x60/0x88 [<802950a8>] mutex_lock_nested+0x54/0x31c [<81645778>] is_world_regdom+0x9f8/0xc74 [cfg80211] -> #1 (reg_mutex#2){+.+...}: [<800a8384>] lock_acquire+0x60/0x88 [<802950a8>] mutex_lock_nested+0x54/0x31c [<8164539c>] is_world_regdom+0x61c/0xc74 [cfg80211] -> #0 (cfg80211_mutex){+.+...}: [<800a77b8>] __lock_acquire+0x10d4/0x17bc [<800a8384>] lock_acquire+0x60/0x88 [<802950a8>] mutex_lock_nested+0x54/0x31c [<816468a4>] set_regdom+0x78c/0x808 [cfg80211] other info that might help us debug this: Chain exists of: cfg80211_mutex --> reg_mutex#2 --> reg_regdb_search_mutex Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(reg_regdb_search_mutex); lock(reg_mutex#2); lock(reg_regdb_search_mutex); lock(cfg80211_mutex); *** DEADLOCK *** 3 locks held by kworker/0:1/235: #0: (events){.+.+..}, at: [<80089a00>] process_one_work+0x230/0x460 #1: (reg_regdb_work){+.+...}, at: [<80089a00>] process_one_work+0x230/0x460 #2: (reg_regdb_search_mutex){+.+...}, at: [<81646828>] set_regdom+0x710/0x808 [cfg80211] stack backtrace: Call Trace: [<80290fd4>] dump_stack+0x8/0x34 [<80291bc4>] print_circular_bug+0x2ac/0x2d8 [<800a77b8>] __lock_acquire+0x10d4/0x17bc [<800a8384>] lock_acquire+0x60/0x88 [<802950a8>] mutex_lock_nested+0x54/0x31c [<816468a4>] set_regdom+0x78c/0x808 [cfg80211] Reported-by: Felix Fietkau Tested-by: Felix Fietkau Signed-off-by: Luis R. Rodriguez Reviewed-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/reg.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 460af03d8149..b01449f01bbd 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -340,6 +340,9 @@ static void reg_regdb_search(struct work_struct *work) struct reg_regdb_search_request *request; const struct ieee80211_regdomain *curdom, *regdom; int i, r; + bool set_reg = false; + + mutex_lock(&cfg80211_mutex); mutex_lock(®_regdb_search_mutex); while (!list_empty(®_regdb_search_list)) { @@ -355,9 +358,7 @@ static void reg_regdb_search(struct work_struct *work) r = reg_copy_regd(®dom, curdom); if (r) break; - mutex_lock(&cfg80211_mutex); - set_regdom(regdom); - mutex_unlock(&cfg80211_mutex); + set_reg = true; break; } } @@ -365,6 +366,11 @@ static void reg_regdb_search(struct work_struct *work) kfree(request); } mutex_unlock(®_regdb_search_mutex); + + if (set_reg) + set_regdom(regdom); + + mutex_unlock(&cfg80211_mutex); } static DECLARE_WORK(reg_regdb_work, reg_regdb_search); -- GitLab From fe9803b58dce15848465ab0270ccea29f4a5c4bb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 17 Sep 2012 15:20:22 +0530 Subject: [PATCH 0465/1799] DMA: PL330: Fix potential NULL pointer dereference in pl330_submit_req() commit 2e2c682becb20416c140aa0d6d3137b51a5c76da upstream. 'r->cfg' is being checked for NULL. However, it is dereferenced in the previous statements. Thus moving those statements within the check. Signed-off-by: Sachin Kamat Acked-by: Jassi Brar Signed-off-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/pl330.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 8c44f17a99e4..69f1c4dc4b87 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -1568,17 +1568,19 @@ static int pl330_submit_req(void *ch_id, struct pl330_req *r) goto xfer_exit; } - /* Prefer Secure Channel */ - if (!_manager_ns(thrd)) - r->cfg->nonsecure = 0; - else - r->cfg->nonsecure = 1; /* Use last settings, if not provided */ - if (r->cfg) + if (r->cfg) { + /* Prefer Secure Channel */ + if (!_manager_ns(thrd)) + r->cfg->nonsecure = 0; + else + r->cfg->nonsecure = 1; + ccr = _prepare_ccr(r->cfg); - else + } else { ccr = readl(regs + CC(thrd->id)); + } /* If this req doesn't have valid xfer settings */ if (!_is_valid(ccr)) { -- GitLab From 570d1520c48a9033c62b9ae552b250d2822c6f9e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 17 Sep 2012 15:20:23 +0530 Subject: [PATCH 0466/1799] DMA: PL330: Check the pointer returned by kzalloc commit 61c6e7531d3b66b33187b8cdd700fd8ab93ffd62 upstream. kzalloc could return NULL. Hence add a check to avoid NULL pointer dereference. Signed-off-by: Sachin Kamat Acked-by: Jassi Brar Signed-off-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/pl330.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 69f1c4dc4b87..758122f33a92 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -2937,6 +2937,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan); pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); + if (!pdmac->peripherals) { + ret = -ENOMEM; + dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n"); + goto probe_err5; + } for (i = 0; i < num_chan; i++) { pch = &pdmac->peripherals[i]; -- GitLab From 8dd47c73d93505aee90bc56d56965ef82b535f93 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 11 Sep 2012 17:21:44 +0200 Subject: [PATCH 0467/1799] dmaengine: at_hdmac: fix comment in atc_prep_slave_sg() commit c618a9be0e8c0f36baee2560860a0118a428fb26 upstream. s/dma_memcpy/slave_sg/ and it is sg length that we are talking about. Signed-off-by: Nicolas Ferre Signed-off-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/at_hdmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index bf0d7e4e345b..6a089828d25f 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -664,7 +664,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, flags); if (unlikely(!atslave || !sg_len)) { - dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n"); + dev_dbg(chan2dev(chan), "prep_slave_sg: sg length is zero!\n"); return NULL; } -- GitLab From 87a34202d070db674e215091e98d21881af56f22 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 11 Sep 2012 17:21:45 +0200 Subject: [PATCH 0468/1799] dmaengine: at_hdmac: check that each sg data length is non-null commit c456797681db814f4f5b36909e8e94047bf53d9c upstream. Avoid the construction of a malformed DMA request sent to the DMA controller. Log message is for debug only because this condition is unlikely to append and may only trigger at driver development time. Signed-off-by: Nicolas Ferre Signed-off-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/at_hdmac.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 6a089828d25f..9ec3943b1232 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -691,6 +691,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_dma_address(sg); len = sg_dma_len(sg); + if (unlikely(!len)) { + dev_dbg(chan2dev(chan), + "prep_slave_sg: sg(%d) data length is zero\n", i); + goto err; + } mem_width = 2; if (unlikely(mem & 3 || len & 3)) mem_width = 0; @@ -726,6 +731,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_dma_address(sg); len = sg_dma_len(sg); + if (unlikely(!len)) { + dev_dbg(chan2dev(chan), + "prep_slave_sg: sg(%d) data length is zero\n", i); + goto err; + } mem_width = 2; if (unlikely(mem & 3 || len & 3)) mem_width = 0; @@ -759,6 +769,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, err_desc_get: dev_err(chan2dev(chan), "not enough descriptors available\n"); +err: atc_desc_put(atchan, first); return NULL; } -- GitLab From 117fe26c51421653d28bfbf91fe71027e9abb253 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 31 Aug 2012 19:22:09 +0200 Subject: [PATCH 0469/1799] rt2x00: Identify ASUS USB-N53 device. commit 177ef8360fabdc49ff08d2598c06e7f7a36b53e3 upstream. This is an RT3572 based device. Signed-off-by: Maximilian Engelhardt Signed-off-by: Gertjan van Wingerde Acked-by: Ivo Van Doorn Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2800usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 7e1a492680c1..bec1c60cb7fe 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1157,6 +1157,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x1690, 0x0744) }, { USB_DEVICE(0x1690, 0x0761) }, { USB_DEVICE(0x1690, 0x0764) }, + /* ASUS */ + { USB_DEVICE(0x0b05, 0x179d) }, /* Cisco */ { USB_DEVICE(0x167b, 0x4001) }, /* EnGenius */ @@ -1222,7 +1224,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0b05, 0x1760) }, { USB_DEVICE(0x0b05, 0x1761) }, { USB_DEVICE(0x0b05, 0x1790) }, - { USB_DEVICE(0x0b05, 0x179d) }, /* AzureWave */ { USB_DEVICE(0x13d3, 0x3262) }, { USB_DEVICE(0x13d3, 0x3284) }, -- GitLab From c0b4947b6456ca77865b296d6b80eaf8c76fa722 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 31 Aug 2012 19:22:10 +0200 Subject: [PATCH 0470/1799] rt2x00: Fix word size of rt2500usb MAC_CSR19 register. commit 6ced58a5dbb94dbfbea1b33ca3c56d1e929cd548 upstream. The register is 16 bits wide, not 32. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo Van Doorn Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2500usb.h | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 1de9c752c88b..b66b8b4e9122 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) u16 reg; rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); - return rt2x00_get_field32(reg, MAC_CSR19_BIT7); + return rt2x00_get_field16(reg, MAC_CSR19_BIT7); } #ifdef CONFIG_RT2X00_LIB_LEDS diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index b493306a7eed..192531db0b65 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -189,14 +189,14 @@ * MAC_CSR19: GPIO control register. */ #define MAC_CSR19 0x0426 -#define MAC_CSR19_BIT0 FIELD32(0x0001) -#define MAC_CSR19_BIT1 FIELD32(0x0002) -#define MAC_CSR19_BIT2 FIELD32(0x0004) -#define MAC_CSR19_BIT3 FIELD32(0x0008) -#define MAC_CSR19_BIT4 FIELD32(0x0010) -#define MAC_CSR19_BIT5 FIELD32(0x0020) -#define MAC_CSR19_BIT6 FIELD32(0x0040) -#define MAC_CSR19_BIT7 FIELD32(0x0080) +#define MAC_CSR19_BIT0 FIELD16(0x0001) +#define MAC_CSR19_BIT1 FIELD16(0x0002) +#define MAC_CSR19_BIT2 FIELD16(0x0004) +#define MAC_CSR19_BIT3 FIELD16(0x0008) +#define MAC_CSR19_BIT4 FIELD16(0x0010) +#define MAC_CSR19_BIT5 FIELD16(0x0020) +#define MAC_CSR19_BIT6 FIELD16(0x0040) +#define MAC_CSR19_BIT7 FIELD16(0x0080) /* * MAC_CSR20: LED control register. -- GitLab From 010ec57f5f6706fbafe9b198846c35500de7aa91 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 31 Aug 2012 19:22:11 +0200 Subject: [PATCH 0471/1799] rt2x00: Fix rfkill polling prior to interface start. commit a396e10019eaf3809b0219c966865aaafec12630 upstream. We need to program the rfkill switch GPIO pin direction to input at device initialization time, not only when the interface is brought up. Doing this only when the interface is brought up could lead to rfkill detecting the switch is turned on erroneously and inability to create the interface and bringing it up. Reported-and-tested-by: Andreas Messer Signed-off-by: Gertjan van Wingerde Acked-by: Ivo Van Doorn Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2400pci.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt2400pci.h | 1 + drivers/net/wireless/rt2x00/rt2500pci.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt2500usb.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt2500usb.h | 1 + drivers/net/wireless/rt2x00/rt2800pci.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt2800usb.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt61pci.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt61pci.h | 1 + drivers/net/wireless/rt2x00/rt73usb.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt73usb.h | 3 +++ 11 files changed, 69 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 3a6b40239bc1..0ea85f46659d 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1611,6 +1611,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -1623,6 +1624,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); + rt2x00_set_field32(®, GPIOCSR_BIT8, 1); + rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index d3a4a68cc439..7564ae992b73 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -670,6 +670,7 @@ #define GPIOCSR_BIT5 FIELD32(0x00000020) #define GPIOCSR_BIT6 FIELD32(0x00000040) #define GPIOCSR_BIT7 FIELD32(0x00000080) +#define GPIOCSR_BIT8 FIELD32(0x00000100) /* * BBPPCSR: BBP Pin control register. diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index dcc0e1fcca77..aa10c48c0dfa 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1929,6 +1929,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -1941,6 +1942,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); + rt2x00_set_field32(®, GPIOCSR_DIR0, 1); + rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index b66b8b4e9122..e0a7efccb73b 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u16 reg; /* * Allocate eeprom data. @@ -1780,6 +1781,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); + rt2x00_set_field16(®, MAC_CSR19_BIT8, 0); + rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 192531db0b65..196bd5103e4f 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -197,6 +197,7 @@ #define MAC_CSR19_BIT5 FIELD16(0x0020) #define MAC_CSR19_BIT6 FIELD16(0x0040) #define MAC_CSR19_BIT7 FIELD16(0x0080) +#define MAC_CSR19_BIT8 FIELD16(0x0100) /* * MAC_CSR20: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 0397bbf0ce01..ff81e761d20f 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -973,6 +973,7 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -985,6 +986,14 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); + rt2x00pci_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index bec1c60cb7fe..a9d124bd80d0 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -736,6 +736,7 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -748,6 +749,14 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); + rt2x00usb_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 0f4bf8c23bff..bdaba3fddd9a 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2832,6 +2832,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Disable power saving. @@ -2849,6 +2850,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); + rt2x00_set_field32(®, MAC_CSR13_BIT13, 1); + rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e3cd6db76b0e..8f3da5a56766 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -372,6 +372,7 @@ struct hw_pairwise_ta_entry { #define MAC_CSR13_BIT10 FIELD32(0x00000400) #define MAC_CSR13_BIT11 FIELD32(0x00000800) #define MAC_CSR13_BIT12 FIELD32(0x00001000) +#define MAC_CSR13_BIT13 FIELD32(0x00002000) /* * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index e477a964081d..fda8671474dc 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -2189,6 +2190,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); + rt2x00_set_field32(®, MAC_CSR13_BIT15, 0); + rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 9f6b470414d3..df1cc116b83b 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -282,6 +282,9 @@ struct hw_pairwise_ta_entry { #define MAC_CSR13_BIT10 FIELD32(0x00000400) #define MAC_CSR13_BIT11 FIELD32(0x00000800) #define MAC_CSR13_BIT12 FIELD32(0x00001000) +#define MAC_CSR13_BIT13 FIELD32(0x00002000) +#define MAC_CSR13_BIT14 FIELD32(0x00004000) +#define MAC_CSR13_BIT15 FIELD32(0x00008000) /* * MAC_CSR14: LED control register. -- GitLab From f15e72437813a8943aaa3f7528e464923c31437f Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 3 Sep 2012 14:56:02 -0400 Subject: [PATCH 0472/1799] NFS: Fix the initialisation of the readdir 'cookieverf' array commit c3f52af3e03013db5237e339c817beaae5ec9e3a upstream. When the NFS_COOKIEVERF helper macro was converted into a static inline function in commit 99fadcd764 (nfs: convert NFS_*(inode) helpers to static inline), we broke the initialisation of the readdir cookies, since that depended on doing a memset with an argument of 'sizeof(NFS_COOKIEVERF(inode))' which therefore changed from sizeof(be32 cookieverf[2]) to sizeof(be32 *). At this point, NFS_COOKIEVERF seems to be more of an obfuscation than a helper, so the best thing would be to just get rid of it. Also see: https://bugzilla.kernel.org/show_bug.cgi?id=46881 Reported-by: Andi Kleen Reported-by: David Binderman Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/inode.c | 2 +- fs/nfs/nfs3proc.c | 2 +- fs/nfs/nfs4proc.c | 4 ++-- include/linux/nfs_fs.h | 5 ----- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e8bbfa5b3500..edf411988bf3 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -152,7 +152,7 @@ static void nfs_zap_caches_locked(struct inode *inode) nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); nfsi->attrtimeo_timestamp = jiffies; - memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); + memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; else diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index a1e416b7baea..a7a043d272da 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -644,7 +644,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, u64 cookie, struct page **pages, unsigned int count, int plus) { struct inode *dir = dentry->d_inode; - __be32 *verf = NFS_COOKIEVERF(dir); + __be32 *verf = NFS_I(dir)->cookieverf; struct nfs3_readdirargs arg = { .fh = NFS_FH(dir), .cookie = cookie, diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index dc573245eea3..b106b9729bcf 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3150,11 +3150,11 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long long)cookie); - nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); + nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args); res.pgbase = args.pgbase; status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); if (status >= 0) { - memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); + memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE); status += args.pgbase; } diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 52a1bdb4ee2b..941d688c2034 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -264,11 +264,6 @@ static inline const struct nfs_rpc_ops *NFS_PROTO(const struct inode *inode) return NFS_SERVER(inode)->nfs_client->rpc_ops; } -static inline __be32 *NFS_COOKIEVERF(const struct inode *inode) -{ - return NFS_I(inode)->cookieverf; -} - static inline unsigned NFS_MINATTRTIMEO(const struct inode *inode) { struct nfs_server *nfss = NFS_SERVER(inode); -- GitLab From 3672dff93b8c5c7d2ebaf18eb32c98b06e942dac Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 4 Sep 2012 11:05:07 -0400 Subject: [PATCH 0473/1799] NFS: Fix a problem with the legacy binary mount code commit 872ece86ea5c367aa92f44689c2d01a1c767aeb3 upstream. Apparently, am-utils is still using the legacy binary mountdata interface, and is having trouble parsing /proc/mounts due to the 'port=' field being incorrectly set. The following patch should fix up the regression. Reported-by: Marius Tolzmann Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/super.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 7b55f51137e3..5976e243d24a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -1886,6 +1886,7 @@ static int nfs_validate_mount_data(void *options, memcpy(sap, &data->addr, sizeof(data->addr)); args->nfs_server.addrlen = sizeof(data->addr); + args->nfs_server.port = ntohs(data->addr.sin_port); if (!nfs_verify_server_address(sap)) goto out_no_address; @@ -2598,6 +2599,7 @@ static int nfs4_validate_mount_data(void *options, return -EFAULT; if (!nfs_verify_server_address(sap)) goto out_no_address; + args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port); if (data->auth_flavourlen) { if (data->auth_flavourlen > 1) -- GitLab From 6da04d620105c54d37de139f9b09e62196b5d0c3 Mon Sep 17 00:00:00 2001 From: Weston Andros Adamson Date: Thu, 6 Sep 2012 15:54:27 -0400 Subject: [PATCH 0474/1799] NFS: return error from decode_getfh in decode open commit 01913b49cf1dc6409a07dd2a4cc6af2e77f3c410 upstream. If decode_getfh failed, nfs4_xdr_dec_open would return 0 since the last decode_* call must have succeeded. Signed-off-by: Weston Andros Adamson Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4xdr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index c54aae364bee..c8ac9a1461c2 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -6081,7 +6081,8 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, status = decode_open(xdr, res); if (status) goto out; - if (decode_getfh(xdr, &res->fh) != 0) + status = decode_getfh(xdr, &res->fh); + if (status) goto out; if (decode_getfattr(xdr, res->f_attr, res->server) != 0) goto out; -- GitLab From 7fe0451922d30d1e540edaa26c95dd708ae55e1a Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Fri, 7 Sep 2012 11:23:28 +0530 Subject: [PATCH 0475/1799] EHCI: Update qTD next pointer in QH overlay region during unlink commit 3d037774b42ed677f699b1dce7d548d55f4e4c2b upstream. There is a possibility of QH overlay region having reference to a stale qTD pointer during unlink. Consider an endpoint having two pending qTD before unlink process begins. The endpoint's QH queue looks like this. qTD1 --> qTD2 --> Dummy To unlink qTD2, QH is removed from asynchronous list and Asynchronous Advance Doorbell is programmed. The qTD1's next qTD pointer is set to qTD2'2 next qTD pointer and qTD2 is retired upon controller's doorbell interrupt. If QH's current qTD pointer points to qTD1, transfer overlay region still have reference to qTD2. But qtD2 is just unlinked and freed. This may cause EHCI system error. Fix this by updating qTD next pointer in QH overlay region with the qTD next pointer of the current qTD. Signed-off-by: Pavankumar Kondeti Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 36ca5077cdf7..7261e8fc8575 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -128,9 +128,17 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) else { qtd = list_entry (qh->qtd_list.next, struct ehci_qtd, qtd_list); - /* first qtd may already be partially processed */ - if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) + /* + * first qtd may already be partially processed. + * If we come here during unlink, the QH overlay region + * might have reference to the just unlinked qtd. The + * qtd is updated in qh_completions(). Update the QH + * overlay here. + */ + if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) { + qh->hw->hw_qtd_next = qtd->hw_next; qtd = NULL; + } } if (qtd) -- GitLab From 7d9088f7173dc7e93d73bbe1b3fdc8f2ea107275 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Fri, 31 Aug 2012 00:00:28 +0200 Subject: [PATCH 0476/1799] USB: ftdi_sio: PID for NZR SEM 16+ USB commit 26a538b9ea2a3ee10dafc0068f0560dfd7b7ba37 upstream. This adds the USB PID for the NZR SEM 16+ USB energy monitor device . It works perfectly with the GPL software on . Signed-off-by: Horst Schirmeier 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 f5819cb4dcf4..5b066be62a3e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -704,6 +704,7 @@ 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(FTDI_VID, FTDI_NZR_SEM_USB_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) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 5dd96ca6c380..117f42ba770b 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -75,6 +75,9 @@ #define FTDI_OPENDCC_GATEWAY_PID 0xBFDB #define FTDI_OPENDCC_GBM_PID 0xBFDC +/* NZR SEM 16+ USB (http://www.nzr.de) */ +#define FTDI_NZR_SEM_USB_PID 0xC1E0 /* NZR SEM-LOG16+ */ + /* * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) */ -- GitLab From c5a79afd07d3aa476eb62851df56fe53f5c07d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 10 Sep 2012 12:01:05 +0200 Subject: [PATCH 0477/1799] USB: ftdi_sio: do not claim CDC ACM function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f08dea734844aa42ec57c229b0b73b3d7d21f810 upstream. The Microchip vid:pid 04d8:000a is used for their CDC ACM demo firmware application. This is a device with a single function conforming to the CDC ACM specification and with the intention of demonstrating CDC ACM class firmware and driver interaction. The demo is used on a number of development boards, and may also be used unmodified by vendors using Microchip hardware. Some vendors have re-used this vid:pid for other types of firmware, emulating FTDI chips. Attempting to continue to support such devices without breaking class based applications that by matching on interface class/subclass/proto being ff/ff/00. I have no information about the actual device or interface descriptors, but this will at least make the proper CDC ACM devices work again. Anyone having details of the offending device's descriptors should update this entry with the details. Reported-by: Florian Wöhrl Reported-by: Xiaofan Chen Cc: Alan Cox Cc: Bruno Thomsen Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 4 +++- drivers/usb/serial/ftdi_sio_ids.h | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 5b066be62a3e..d0d97ca44735 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -805,7 +805,9 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) }, + { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID, + USB_CLASS_VENDOR_SPEC, + USB_SUBCLASS_VENDOR_SPEC, 0x00) }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 117f42ba770b..899b65ae2901 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -542,7 +542,10 @@ /* * Microchip Technology, Inc. * - * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by: + * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are + * used by single function CDC ACM class based firmware demo + * applications. The VID/PID has also been used in firmware + * emulating FTDI serial chips by: * Hornby Elite - Digital Command Control Console * http://www.hornby.com/hornby-dcc/controllers/ */ -- GitLab From 1ea39e97a7cebcb8ab8c969ba05ac1e8b1b0457d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Piel?= Date: Tue, 4 Sep 2012 17:25:06 +0200 Subject: [PATCH 0478/1799] USB: ftdi-sio: add support for more Physik Instrumente devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit dafc4f7be1a556ca3868d343c00127728b397068 upstream. Commit b69cc672052540 added support for the E-861. After acquiring a C-867, I realised that every Physik Instrumente's device has a different PID. They are listed in the Windows device driver's .inf file. So here are all PIDs for the current (and probably future) USB devices from Physik Instrumente. Compiled, but only actually tested on the E-861 and C-867. Signed-off-by: Éric Piel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 17 +++++++++++++++++ drivers/usb/serial/ftdi_sio_ids.h | 21 ++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d0d97ca44735..4d2b7d31fc67 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -813,7 +813,24 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, + { USB_DEVICE(FTDI_VID, PI_C865_PID) }, + { USB_DEVICE(FTDI_VID, PI_C857_PID) }, + { USB_DEVICE(PI_VID, PI_C866_PID) }, + { USB_DEVICE(PI_VID, PI_C663_PID) }, + { USB_DEVICE(PI_VID, PI_C725_PID) }, + { USB_DEVICE(PI_VID, PI_E517_PID) }, + { USB_DEVICE(PI_VID, PI_C863_PID) }, { USB_DEVICE(PI_VID, PI_E861_PID) }, + { USB_DEVICE(PI_VID, PI_C867_PID) }, + { USB_DEVICE(PI_VID, PI_E609_PID) }, + { USB_DEVICE(PI_VID, PI_E709_PID) }, + { USB_DEVICE(PI_VID, PI_100F_PID) }, + { USB_DEVICE(PI_VID, PI_1011_PID) }, + { USB_DEVICE(PI_VID, PI_1012_PID) }, + { USB_DEVICE(PI_VID, PI_1013_PID) }, + { USB_DEVICE(PI_VID, PI_1014_PID) }, + { USB_DEVICE(PI_VID, PI_1015_PID) }, + { USB_DEVICE(PI_VID, PI_1016_PID) }, { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) }, { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 899b65ae2901..41fe5826100c 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -797,8 +797,27 @@ * Physik Instrumente * http://www.physikinstrumente.com/en/products/ */ +/* These two devices use the VID of FTDI */ +#define PI_C865_PID 0xe0a0 /* PI C-865 Piezomotor Controller */ +#define PI_C857_PID 0xe0a1 /* PI Encoder Trigger Box */ + #define PI_VID 0x1a72 /* Vendor ID */ -#define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */ +#define PI_C866_PID 0x1000 /* PI C-866 Piezomotor Controller */ +#define PI_C663_PID 0x1001 /* PI C-663 Mercury-Step */ +#define PI_C725_PID 0x1002 /* PI C-725 Piezomotor Controller */ +#define PI_E517_PID 0x1005 /* PI E-517 Digital Piezo Controller Operation Module */ +#define PI_C863_PID 0x1007 /* PI C-863 */ +#define PI_E861_PID 0x1008 /* PI E-861 Piezomotor Controller */ +#define PI_C867_PID 0x1009 /* PI C-867 Piezomotor Controller */ +#define PI_E609_PID 0x100D /* PI E-609 Digital Piezo Controller */ +#define PI_E709_PID 0x100E /* PI E-709 Digital Piezo Controller */ +#define PI_100F_PID 0x100F /* PI Digital Piezo Controller */ +#define PI_1011_PID 0x1011 /* PI Digital Piezo Controller */ +#define PI_1012_PID 0x1012 /* PI Motion Controller */ +#define PI_1013_PID 0x1013 /* PI Motion Controller */ +#define PI_1014_PID 0x1014 /* PI Device */ +#define PI_1015_PID 0x1015 /* PI Device */ +#define PI_1016_PID 0x1016 /* PI Digital Servo Module */ /* * Kondo Kagaku Co.Ltd. -- GitLab From 7acab78d0fc555fb57cc8b5a5080b5f637f447a1 Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Fri, 10 Aug 2012 13:42:16 +0530 Subject: [PATCH 0479/1799] usb: dwc3: ep0: correct cache sync issue in case of ep0_bounced commit 0416e494ce7dc84e2719bc9fb7daecb330476074 upstream. In case of ep0 out, if length is not aligned to maxpacket size then we use dwc->ep_bounce_addr for dma transfer and not request->dma. Since, we have alreday done memcpy from dwc->ep0_bounce to request->buf, so we do not need to issue cache sync function. In fact, cache sync function will bring wrong data in request->buf from request->dma in this scenario. So, cache sync function must not be executed in case of ep0 bounced. Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/ep0.c | 1 - drivers/usb/dwc3/gadget.c | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 3584a169886f..e4d87d700554 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -569,7 +569,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, transferred = min_t(u32, ur->length, transfer_size - length); memcpy(ur->buf, dwc->ep0_bounce, transferred); - dwc->ep0_bounced = false; } else { transferred = ur->length - length; } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5255fe975ea1..b8d46978fc58 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -238,8 +238,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, if (req->request.status == -EINPROGRESS) req->request.status = status; - usb_gadget_unmap_request(&dwc->gadget, &req->request, - req->direction); + if (dwc->ep0_bounced && dep->number == 0) + dwc->ep0_bounced = false; + else + usb_gadget_unmap_request(&dwc->gadget, &req->request, + req->direction); dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n", req, dep->name, req->request.actual, -- GitLab From 5527f1341645e192145f7e581230dcf4447dd8c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 10 Sep 2012 22:17:34 +0200 Subject: [PATCH 0480/1799] USB: cdc-wdm: fix wdm_find_device* return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 6a44886899ef8cc396e230e492e6a56a883889f3 upstream. A logic error made the wdm_find_device* functions return a bogus pointer into static data instead of the intended NULL no matching device was found. Signed-off-by: Bjørn Mork Cc: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 01d247e88081..524fe240fcd1 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -134,12 +134,14 @@ static struct usb_driver wdm_driver; /* return intfdata if we own the interface, else look up intf in the list */ static struct wdm_device *wdm_find_device(struct usb_interface *intf) { - struct wdm_device *desc = NULL; + struct wdm_device *desc; spin_lock(&wdm_device_list_lock); list_for_each_entry(desc, &wdm_device_list, device_list) if (desc->intf == intf) - break; + goto found; + desc = NULL; +found: spin_unlock(&wdm_device_list_lock); return desc; @@ -147,12 +149,14 @@ static struct wdm_device *wdm_find_device(struct usb_interface *intf) static struct wdm_device *wdm_find_device_by_minor(int minor) { - struct wdm_device *desc = NULL; + struct wdm_device *desc; spin_lock(&wdm_device_list_lock); list_for_each_entry(desc, &wdm_device_list, device_list) if (desc->intf->minor == minor) - break; + goto found; + desc = NULL; +found: spin_unlock(&wdm_device_list_lock); return desc; -- GitLab From 61fee2c3e35d8496685317c4e17c98e8905ba762 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 29 Aug 2012 11:49:18 +0200 Subject: [PATCH 0481/1799] USB: ohci-at91: fix PIO handling in relation with number of ports commit 6fffb77c8393151b0cf8cef1b9c2ba90587dd2e8 upstream. If the number of ports present on the SoC/board is not the maximum and that the platform data is not filled with all data, there is an easy way to mess the PIO setup for this interface. This quick fix addresses mis-configuration in USB host platform data that is common in at91 boards since commit 0ee6d1e (USB: ohci-at91: change maximum number of ports) that did not modified the associatd board files. Reported-by: Klaus Falkner Signed-off-by: Nicolas Ferre Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-at91.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 55d3d6414478..50bd3f1e3307 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -569,6 +569,16 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev) if (pdata) { at91_for_each_port(i) { + /* + * do not configure PIO if not in relation with + * real USB port on board + */ + if (i >= pdata->ports) { + pdata->vbus_pin[i] = -EINVAL; + pdata->overcurrent_pin[i] = -EINVAL; + break; + } + if (!gpio_is_valid(pdata->vbus_pin[i])) continue; gpio = pdata->vbus_pin[i]; -- GitLab From adc7b2b36a6fb6854f2146d86f08d362b6aa0b83 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 4 Sep 2012 10:41:02 -0400 Subject: [PATCH 0482/1799] USB: add device quirk for Joss Optical touchboard commit 92fc7a8b0f20bdb243c706daf42658e8e0cd2ef0 upstream. This patch (as1604) adds a CONFIG_INTF_STRINGS quirk for the Joss infrared touchboard device. The device doesn't like to be asked for its interface strings. Signed-off-by: Alan Stern Reported-by: adam ? Signed-off-by: Greg Kroah-Hartman --- 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 32d3adc315f5..8b2a9d83090e 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -96,6 +96,10 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x04b4, 0x0526), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Microchip Joss Optical infrared touchboard device */ + { USB_DEVICE(0x04d8, 0x000c), .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 }, -- GitLab From 1f92c25123b256e3c8d892fcb0d71760445ccb90 Mon Sep 17 00:00:00 2001 From: Sergei Poselenov Date: Sun, 2 Sep 2012 13:14:32 +0400 Subject: [PATCH 0483/1799] rt2800usb: Added rx packet length validity check commit efd5d6b03bd9c9e0df646c56fb5f4f3e25e5c1ac upstream. On our system (ARM Cortex-M3 SOC running linux-2.6.33) frequent crashes were observed in the rt2800usb module because of the invalid length of the received packet (3392, 46920...). This patch adds the sanity check on the packet legth. Also, changed WARNING to ERROR in rt2x00lib_rxdone() so that the bad packet condition would be noticed. The fix was tested on the latest compat-wireless-3.5.1-1-snpc. Signed-off-by: Sergei Poselenov Acked-by: Ivo van Doorn Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2800usb.c | 10 +++++++++- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index a9d124bd80d0..65cb4250259f 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -667,8 +667,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, skb_pull(entry->skb, RXINFO_DESC_SIZE); /* - * FIXME: we need to check for rx_pkt_len validity + * Check for rx_pkt_len validity. Return if invalid, leaving + * rxdesc->size zeroed out by the upper level. */ + if (unlikely(rx_pkt_len == 0 || + rx_pkt_len > entry->queue->data_size)) { + ERROR(entry->queue->rt2x00dev, + "Bad frame size %d, forcing to 0\n", rx_pkt_len); + return; + } + rxd = (__le32 *)(entry->skb->data + rx_pkt_len); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 90cc5e772650..12b1ff5a6a30 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -628,7 +628,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry) */ if (unlikely(rxdesc.size == 0 || rxdesc.size > entry->queue->data_size)) { - WARNING(rt2x00dev, "Wrong frame size %d max %d.\n", + ERROR(rt2x00dev, "Wrong frame size %d max %d.\n", rxdesc.size, entry->queue->data_size); dev_kfree_skb(entry->skb); goto renew_skb; -- GitLab From dadc5da6b79314943a7e5eda6369c70e3c7a1d26 Mon Sep 17 00:00:00 2001 From: "Alexis R. Cortes" Date: Fri, 3 Aug 2012 14:00:27 -0500 Subject: [PATCH 0484/1799] usb: host: xhci: Fix Compliance Mode on SN65LVPE502CP Hardware commit 71c731a296f1b08a3724bd1b514b64f1bda87a23 upstream. This patch is intended to work around a known issue on the SN65LVPE502CP USB3.0 re-driver that can delay the negotiation between a device and the host past the usual handshake timeout. If that happens on the first insertion, the host controller port will enter in Compliance Mode and NO port status event will be generated (as per xHCI Spec) making impossible to detect this event by software. The port will remain in compliance mode until a warm reset is applied to it. As a result of this, the port will seem "dead" to the user and no device connections or disconnections will be detected. For solving this, the patch creates a timer which polls every 2 seconds the link state of each host controller's port (this by reading the PORTSC register) and recovers the port by issuing a Warm reset every time Compliance mode is detected. If a xHC USB3.0 port has previously entered to U0, the compliance mode issue will NOT occur only until system resumes from sleep/hibernate, therefore, the compliance mode timer is stopped when all xHC USB 3.0 ports have entered U0. The timer is initialized again after each system resume. Since the issue is being caused by a piece of hardware, the timer will be enabled ONLY on those systems that have the SN65LVPE502CP installed (this patch uses DMI strings for detecting those systems) therefore making this patch to act as a quirk (XHCI_COMP_MODE_QUIRK has been added to the xhci stack). This patch applies for these systems: Vendor: Hewlett-Packard. System Models: Z420, Z620 and Z820. This patch should be backported to kernels as old as 3.2, as that was the first kernel to support warm reset. The kernels will need to contain both commit 10d674a82e553cb8a1f41027bb3c3e309b3f6804 "USB: When hot reset for USB3 fails, try warm reset" and commit 8bea2bd37df08aaa599aa361a9f8b836ba98e554 "usb: Add support for root hub port status CAS". The first patch add warm reset support, and the second patch modifies the USB core to issue a warm reset when the port is in compliance mode. Signed-off-by: Alexis R. Cortes Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 42 +++++++++++++ drivers/usb/host/xhci.c | 121 ++++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci.h | 6 ++ 3 files changed, 169 insertions(+) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index bbf3c0c9cde7..de07b7556d4d 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -493,11 +493,48 @@ static void xhci_hub_report_link_state(u32 *status, u32 status_reg) * when this bit is set. */ pls |= USB_PORT_STAT_CONNECTION; + } else { + /* + * If CAS bit isn't set but the Port is already at + * Compliance Mode, fake a connection so the USB core + * notices the Compliance state and resets the port. + * This resolves an issue generated by the SN65LVPE502CP + * in which sometimes the port enters compliance mode + * caused by a delay on the host-device negotiation. + */ + if (pls == USB_SS_PORT_LS_COMP_MOD) + pls |= USB_PORT_STAT_CONNECTION; } + /* update status field */ *status |= pls; } +/* + * Function for Compliance Mode Quirk. + * + * This Function verifies if all xhc USB3 ports have entered U0, if so, + * the compliance mode timer is deleted. A port won't enter + * compliance mode if it has previously entered U0. + */ +void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex) +{ + u32 all_ports_seen_u0 = ((1 << xhci->num_usb3_ports)-1); + bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0); + + if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK)) + return; + + if ((xhci->port_status_u0 != all_ports_seen_u0) && port_in_u0) { + xhci->port_status_u0 |= 1 << wIndex; + if (xhci->port_status_u0 == all_ports_seen_u0) { + del_timer_sync(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "All USB3 ports have entered U0 already!\n"); + xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted.\n"); + } + } +} + int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { @@ -644,6 +681,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, /* Update Port Link State for super speed ports*/ if (hcd->speed == HCD_USB3) { xhci_hub_report_link_state(&status, temp); + /* + * Verify if all USB3 Ports Have entered U0 already. + * Delete Compliance Mode Timer if so. + */ + xhci_del_comp_mod_timer(xhci, temp, wIndex); } if (bus_state->port_c_suspend & (1 << wIndex)) status |= 1 << USB_PORT_FEAT_C_SUSPEND; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7beed536e6b9..4afe3af319dd 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "xhci.h" @@ -398,6 +399,95 @@ static void xhci_msix_sync_irqs(struct xhci_hcd *xhci) #endif +static void compliance_mode_recovery(unsigned long arg) +{ + struct xhci_hcd *xhci; + struct usb_hcd *hcd; + u32 temp; + int i; + + xhci = (struct xhci_hcd *)arg; + + for (i = 0; i < xhci->num_usb3_ports; i++) { + temp = xhci_readl(xhci, xhci->usb3_ports[i]); + if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) { + /* + * Compliance Mode Detected. Letting USB Core + * handle the Warm Reset + */ + xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n", + i + 1); + xhci_dbg(xhci, "Attempting Recovery routine!\n"); + hcd = xhci->shared_hcd; + + if (hcd->state == HC_STATE_SUSPENDED) + usb_hcd_resume_root_hub(hcd); + + usb_hcd_poll_rh_status(hcd); + } + } + + if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1)) + mod_timer(&xhci->comp_mode_recovery_timer, + jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); +} + +/* + * Quirk to work around issue generated by the SN65LVPE502CP USB3.0 re-driver + * that causes ports behind that hardware to enter compliance mode sometimes. + * The quirk creates a timer that polls every 2 seconds the link state of + * each host controller's port and recovers it by issuing a Warm reset + * if Compliance mode is detected, otherwise the port will become "dead" (no + * device connections or disconnections will be detected anymore). Becasue no + * status event is generated when entering compliance mode (per xhci spec), + * this quirk is needed on systems that have the failing hardware installed. + */ +static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci) +{ + xhci->port_status_u0 = 0; + init_timer(&xhci->comp_mode_recovery_timer); + + xhci->comp_mode_recovery_timer.data = (unsigned long) xhci; + xhci->comp_mode_recovery_timer.function = compliance_mode_recovery; + xhci->comp_mode_recovery_timer.expires = jiffies + + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS); + + set_timer_slack(&xhci->comp_mode_recovery_timer, + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); + add_timer(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "Compliance Mode Recovery Timer Initialized.\n"); +} + +/* + * This function identifies the systems that have installed the SN65LVPE502CP + * USB3.0 re-driver and that need the Compliance Mode Quirk. + * Systems: + * Vendor: Hewlett-Packard -> System Models: Z420, Z620 and Z820 + */ +static bool compliance_mode_recovery_timer_quirk_check(void) +{ + const char *dmi_product_name, *dmi_sys_vendor; + + dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); + dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR); + + if (!(strstr(dmi_sys_vendor, "Hewlett-Packard"))) + return false; + + if (strstr(dmi_product_name, "Z420") || + strstr(dmi_product_name, "Z620") || + strstr(dmi_product_name, "Z820")) + return true; + + return false; +} + +static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci) +{ + return (xhci->port_status_u0 == ((1 << xhci->num_usb3_ports)-1)); +} + + /* * Initialize memory for HCD and xHC (one-time init). * @@ -421,6 +511,12 @@ int xhci_init(struct usb_hcd *hcd) retval = xhci_mem_init(xhci, GFP_KERNEL); xhci_dbg(xhci, "Finished xhci_init\n"); + /* Initializing Compliance Mode Recovery Data If Needed */ + if (compliance_mode_recovery_timer_quirk_check()) { + xhci->quirks |= XHCI_COMP_MODE_QUIRK; + compliance_mode_recovery_timer_init(xhci); + } + return retval; } @@ -629,6 +725,11 @@ void xhci_stop(struct usb_hcd *hcd) del_timer_sync(&xhci->event_ring_timer); #endif + /* Deleting Compliance Mode Recovery Timer */ + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + (!(xhci_all_ports_seen_u0(xhci)))) + del_timer_sync(&xhci->comp_mode_recovery_timer); + if (xhci->quirks & XHCI_AMD_PLL_FIX) usb_amd_dev_put(); @@ -806,6 +907,16 @@ int xhci_suspend(struct xhci_hcd *xhci) } spin_unlock_irq(&xhci->lock); + /* + * Deleting Compliance Mode Recovery Timer because the xHCI Host + * is about to be suspended. + */ + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + (!(xhci_all_ports_seen_u0(xhci)))) { + del_timer_sync(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted!\n"); + } + /* step 5: remove core well power */ /* synchronize irq when using MSI-X */ xhci_msix_sync_irqs(xhci); @@ -938,6 +1049,16 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) usb_hcd_resume_root_hub(hcd); usb_hcd_resume_root_hub(xhci->shared_hcd); } + + /* + * If system is subject to the Quirk, Compliance Mode Timer needs to + * be re-initialized Always after a system resume. Ports are subject + * to suffer the Compliance Mode issue again. It doesn't matter if + * ports have entered previously to U0 before system's suspension. + */ + if (xhci->quirks & XHCI_COMP_MODE_QUIRK) + compliance_mode_recovery_timer_init(xhci); + return retval; } #endif /* CONFIG_PM */ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 19ae30f1d84a..6e77f3b5a7fb 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1487,6 +1487,7 @@ struct xhci_hcd { #define XHCI_AMD_0x96_HOST (1 << 9) #define XHCI_TRUST_TX_LENGTH (1 << 10) #define XHCI_SPURIOUS_REBOOT (1 << 13) +#define XHCI_COMP_MODE_QUIRK (1 << 14) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ @@ -1503,6 +1504,11 @@ struct xhci_hcd { unsigned sw_lpm_support:1; /* support xHCI 1.0 spec USB2 hardware LPM */ unsigned hw_lpm_support:1; + /* Compliance Mode Recovery Data */ + struct timer_list comp_mode_recovery_timer; + u32 port_status_u0; +/* Compliance Mode Timer Triggered every 2 seconds */ +#define COMP_MODE_RCVRY_MSECS 2000 }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ -- GitLab From 3c4154bb097ffc933a70771e976949d00969d451 Mon Sep 17 00:00:00 2001 From: Keng-Yu Lin Date: Fri, 10 Aug 2012 01:39:23 +0800 Subject: [PATCH 0485/1799] Intel xhci: Only switch the switchable ports commit a96874a2a92feaef607ddd3137277a788cb927a6 upstream. With a previous patch to enable the EHCI/XHCI port switching, it switches all the available ports. The assumption is not correct because the BIOS may expect some ports not switchable by the OS. There are two more registers that contains the information of the switchable and non-switchable ports. This patch adds the checking code for the two register so that only the switchable ports are altered. This patch should be backported to kernels as old as 3.0, that contain commit ID 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support EHCI/xHCI port switching." Signed-off-by: Keng-Yu Lin Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index c5e9e4a76f14..b586863e0507 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -75,7 +75,9 @@ #define NB_PIF0_PWRDOWN_1 0x01100013 #define USB_INTEL_XUSB2PR 0xD0 +#define USB_INTEL_USB2PRM 0xD4 #define USB_INTEL_USB3_PSSEN 0xD8 +#define USB_INTEL_USB3PRM 0xDC static struct amd_chipset_info { struct pci_dev *nb_dev; @@ -772,10 +774,18 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) return; } - ports_available = 0xffffffff; + /* Read USB3PRM, the USB 3.0 Port Routing Mask Register + * Indicate the ports that can be changed from OS. + */ + pci_read_config_dword(xhci_pdev, USB_INTEL_USB3PRM, + &ports_available); + + dev_dbg(&xhci_pdev->dev, "Configurable ports to enable SuperSpeed: 0x%x\n", + ports_available); + /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable - * Register, to turn on SuperSpeed terminations for all - * available ports. + * Register, to turn on SuperSpeed terminations for the + * switchable ports. */ pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, cpu_to_le32(ports_available)); @@ -785,7 +795,16 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled " "under xHCI: 0x%x\n", ports_available); - ports_available = 0xffffffff; + /* Read XUSB2PRM, xHCI USB 2.0 Port Routing Mask Register + * Indicate the USB 2.0 ports to be controlled by the xHCI host. + */ + + pci_read_config_dword(xhci_pdev, USB_INTEL_USB2PRM, + &ports_available); + + dev_dbg(&xhci_pdev->dev, "Configurable USB 2.0 ports to hand over to xCHI: 0x%x\n", + ports_available); + /* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to * switch the USB 2.0 power and data lines over to the xHCI * host. -- GitLab From 40fd8822f49ad6ac2b7a575e3b2020e7382db431 Mon Sep 17 00:00:00 2001 From: Ruchika Kharwar Date: Fri, 10 Aug 2012 09:58:30 +0300 Subject: [PATCH 0486/1799] usb: host: xhci-plat: use ioremap_nocache commit 319acdfc064169023cd9ada5085b434fbcdacec2 upstream. Use the ioremap_nocache variant of the ioremap API in order to make sure our memory will be marked uncachable. This patch should be backported to kernels as old as 3.4, that contain the commit 3429e91a661e1f383aecc86c6bbcf65afb15c892 "usb: host: xhci: add platform driver support". Signed-off-by: Ruchika Kharwar Signed-off-by: Felipe Balbi Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-plat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 689bc18b051d..df90fe51b4aa 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -118,7 +118,7 @@ static int xhci_plat_probe(struct platform_device *pdev) goto put_hcd; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_dbg(&pdev->dev, "error mapping memory\n"); ret = -EFAULT; -- GitLab From 3dd2f0bb418f24a3b9a0b9b93b1ba104c2e6d140 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 13 Aug 2012 19:57:03 +0300 Subject: [PATCH 0487/1799] xhci: Fix a logical vs bitwise AND bug commit 052c7f9ffb0e95843e75448d02664459253f9ff8 upstream. The intent was to test whether the flag was set. This patch should be backported to stable kernels as old as 3.0, since it fixes a bug in commit e95829f474f0db3a4d940cae1423783edd966027 "xhci: Switch PPT ports to EHCI on shutdown.", which was marked for stable. Signed-off-by: Dan Carpenter Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 4afe3af319dd..6467d79d760d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -760,7 +760,7 @@ void xhci_shutdown(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); - if (xhci->quirks && XHCI_SPURIOUS_REBOOT) + if (xhci->quirks & XHCI_SPURIOUS_REBOOT) usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); spin_lock_irq(&xhci->lock); -- GitLab From 279412b46d186d0cb6badb02e3bfd4d03beff43e Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 14 Aug 2012 16:44:49 -0400 Subject: [PATCH 0488/1799] xhci: Make handover code more robust commit e955a1cd086de4d165ae0f4c7be7289d84b63bdc upstream. My test platform (Intel DX79SI) boots reliably under BIOS, but frequently crashes when booting via UEFI. I finally tracked this down to the xhci handoff code. It seems that reads from the device occasionally just return 0xff, resulting in xhci_find_next_cap_offset generating a value that's larger than the resource region. We then oops when attempting to read the value. Sanity checking that value lets us avoid the crash. I've no idea what's causing the underlying problem, and xhci still doesn't actually *work* even with this, but the machine at least boots which will probably make further debugging easier. This should be backported to kernels as old as 2.6.31, that contain the commit 66d4eadd8d067269ea8fead1a50fe87c2979a80d "USB: xhci: BIOS handoff and HW initialization." Signed-off-by: Matthew Garrett Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index b586863e0507..e3a9e0b3f1e1 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -841,12 +841,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) void __iomem *op_reg_base; u32 val; int timeout; + int len = pci_resource_len(pdev, 0); if (!mmio_resource_enabled(pdev, 0)) return; - base = ioremap_nocache(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); + base = ioremap_nocache(pci_resource_start(pdev, 0), len); if (base == NULL) return; @@ -856,9 +856,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) */ ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET); do { + if ((ext_cap_offset + sizeof(val)) > len) { + /* We're reading garbage from the controller */ + dev_warn(&pdev->dev, + "xHCI controller failing to respond"); + return; + } + if (!ext_cap_offset) /* We've reached the end of the extended capabilities */ goto hc_init; + val = readl(base + ext_cap_offset); if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY) break; -- GitLab From fa544a230c9ce8b56bef4ea64f2d606f95cee37b Mon Sep 17 00:00:00 2001 From: Manoj Iyer Date: Wed, 22 Aug 2012 11:53:18 -0500 Subject: [PATCH 0489/1799] xhci: Recognize USB 3.0 devices as superspeed at powerup commit 29d214576f936db627ff62afb9ef438eea18bcd2 upstream. On Intel Panther Point chipset USB 3.0 devices show up as high-speed devices on powerup, but after an s3 cycle they are correctly recognized as SuperSpeed. At powerup switch the port to xHCI so that USB 3.0 devices are correctly recognized. BugLink: http://bugs.launchpad.net/bugs/1000424 This patch should be backported to kernels as old as 3.0, that contain commit ID 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support EHCI/xHCI port switching." Signed-off-by: Manoj Iyer Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index e3a9e0b3f1e1..966d1484ee79 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -897,9 +897,10 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) /* Disable any BIOS SMIs and clear all SMI events*/ writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); +hc_init: if (usb_is_intel_switchable_xhci(pdev)) usb_enable_xhci_ports(pdev); -hc_init: + op_reg_base = base + XHCI_HC_LENGTH(readl(base)); /* Wait for the host controller to be ready before writing any -- GitLab From 48877fe63db63f981cc64d597369fb489ae2e556 Mon Sep 17 00:00:00 2001 From: Moiz Sonasath Date: Wed, 5 Sep 2012 08:34:26 +0300 Subject: [PATCH 0490/1799] usb: host: xhci: fix compilation error for non-PCI based stacks commit 296365781903226a3fb8758901eaeec09d2798e4 upstream. For non PCI-based stacks, this function call usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); made from xhci_shutdown is not applicable. Ideally, we wouldn't have any PCI-specific code on a generic driver such as the xHCI stack, but it looks like we should just stub usb_disable_xhci_ports() out for non-PCI devices. [ balbi@ti.com: slight improvement to commit log ] This patch should be backported to kernels as old as 3.0, since the commit it fixes (e95829f474f0db3a4d940cae1423783edd966027 "xhci: Switch PPT ports to EHCI on shutdown.") was marked for stable. Signed-off-by: Moiz Sonasath Signed-off-by: Ruchika Kharwar Signed-off-by: Felipe Balbi Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index ef004a5de20f..7f69a39163ce 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -15,6 +15,7 @@ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); static inline void usb_amd_quirk_pll_disable(void) {} static inline void usb_amd_quirk_pll_enable(void) {} static inline void usb_amd_dev_put(void) {} +static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} #endif /* CONFIG_PCI */ #endif /* __LINUX_USB_PCI_QUIRKS_H */ -- GitLab From 86236252d2449313bdbac790023cbc957bf6e426 Mon Sep 17 00:00:00 2001 From: Xinyu Chen Date: Mon, 27 Aug 2012 09:36:51 +0200 Subject: [PATCH 0491/1799] tty: serial: imx: console write routing is unsafe on SMP commit 9ec1882df244c4ee1baa692676fef5e8b0f5487d upstream. The console feature's write routing is unsafe on SMP with the startup/shutdown call. There could be several consumers of the console * the kernel printk * the init process using /dev/kmsg to call printk to show log * shell, which open /dev/console and write with sys_write() The shell goes into the normal uart open/write routing, but the other two go into the console operations. The open routing calls imx serial startup, which will write USR1/2 register without any lock and critical with imx_console_write call. Add a spin_lock for startup/shutdown/console_write routing. This patch is a port from Freescale's Android kernel. Signed-off-by: Xinyu Chen Tested-by: Dirk Behme CC: Sascha Hauer Acked-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index e7feceeebc2f..0de7ed788631 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -756,6 +756,7 @@ static int imx_startup(struct uart_port *port) } } + spin_lock_irqsave(&sport->port.lock, flags); /* * Finally, clear and enable interrupts */ @@ -809,7 +810,6 @@ static int imx_startup(struct uart_port *port) /* * Enable modem status interrupts */ - spin_lock_irqsave(&sport->port.lock,flags); imx_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->port.lock,flags); @@ -839,10 +839,13 @@ static void imx_shutdown(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; unsigned long temp; + unsigned long flags; + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR2); temp &= ~(UCR2_TXEN); writel(temp, sport->port.membase + UCR2); + spin_unlock_irqrestore(&sport->port.lock, flags); if (USE_IRDA(sport)) { struct imxuart_platform_data *pdata; @@ -871,12 +874,14 @@ static void imx_shutdown(struct uart_port *port) * Disable all interrupts, port and break condition. */ + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR1); temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); if (USE_IRDA(sport)) temp &= ~(UCR1_IREN); writel(temp, sport->port.membase + UCR1); + spin_unlock_irqrestore(&sport->port.lock, flags); } static void @@ -1219,6 +1224,9 @@ imx_console_write(struct console *co, const char *s, unsigned int count) struct imx_port *sport = imx_ports[co->index]; struct imx_port_ucrs old_ucr; unsigned int ucr1; + unsigned long flags; + + spin_lock_irqsave(&sport->port.lock, flags); /* * First, save UCR1/2/3 and then disable interrupts @@ -1244,6 +1252,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count) while (!(readl(sport->port.membase + USR2) & USR2_TXDC)); imx_port_ucrs_restore(&sport->port, &old_ucr); + + spin_unlock_irqrestore(&sport->port.lock, flags); } /* -- GitLab From e60b883144de35ea312a7570460cfe6a42af61c1 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 10 Aug 2012 15:22:09 +0100 Subject: [PATCH 0492/1799] mutex: Place lock in contended state after fastpath_lock failure commit 0bce9c46bf3b15f485d82d7e81dabed6ebcc24b1 upstream. ARM recently moved to asm-generic/mutex-xchg.h for its mutex implementation after the previous implementation was found to be missing some crucial memory barriers. However, this has revealed some problems running hackbench on SMP platforms due to the way in which the MUTEX_SPIN_ON_OWNER code operates. The symptoms are that a bunch of hackbench tasks are left waiting on an unlocked mutex and therefore never get woken up to claim it. This boils down to the following sequence of events: Task A Task B Task C Lock value 0 1 1 lock() 0 2 lock() 0 3 spin(A) 0 4 unlock() 1 5 lock() 0 6 cmpxchg(1,0) 0 7 contended() -1 8 lock() 0 9 spin(C) 0 10 unlock() 1 11 cmpxchg(1,0) 0 12 unlock() 1 At this point, the lock is unlocked, but Task B is in an uninterruptible sleep with nobody to wake it up. This patch fixes the problem by ensuring we put the lock into the contended state if we fail to acquire it on the fastpath, ensuring that any blocked waiters are woken up when the mutex is released. Signed-off-by: Will Deacon Cc: Arnd Bergmann Cc: Chris Mason Cc: Ingo Molnar Reviewed-by: Nicolas Pitre Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-6e9lrw2avczr0617fzl5vqb8@git.kernel.org Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- include/asm-generic/mutex-xchg.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/include/asm-generic/mutex-xchg.h b/include/asm-generic/mutex-xchg.h index 580a6d35c700..c04e0db8a2d6 100644 --- a/include/asm-generic/mutex-xchg.h +++ b/include/asm-generic/mutex-xchg.h @@ -26,7 +26,13 @@ static inline void __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) { if (unlikely(atomic_xchg(count, 0) != 1)) - fail_fn(count); + /* + * We failed to acquire the lock, so mark it contended + * to ensure that any waiting tasks are woken up by the + * unlock slow path. + */ + if (likely(atomic_xchg(count, -1) != 1)) + fail_fn(count); } /** @@ -43,7 +49,8 @@ static inline int __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) { if (unlikely(atomic_xchg(count, 0) != 1)) - return fail_fn(count); + if (likely(atomic_xchg(count, -1) != 1)) + return fail_fn(count); return 0; } -- GitLab From 5e5891d1fe77e50428913ab69ff8cc8c5695a560 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 21 Aug 2012 16:16:10 -0700 Subject: [PATCH 0493/1799] drivers/rtc/rtc-rs5c348.c: fix hour decoding in 12-hour mode commit 7dbfb315b2aaef0a115765946bf3026d074c33a7 upstream. Correct the offset by subtracting 20 from tm_hour before taking the modulo 12. [ "Why 20?" I hear you ask. Or at least I did. Here's the reason why: RS5C348_BIT_PM is 32, and is - stupidly - included in the RS5C348_HOURS_MASK define. So it's really subtracting out that bit to get "hour+12". But then because it does things modulo 12, it needs to add the 12 in again afterwards anyway. This code is confused. It would be much clearer if RS5C348_HOURS_MASK just didn't include the RS5C348_BIT_PM bit at all, then it wouldn't need to do the silly subtract either. Whatever. It's all just math, the end result is the same. - Linus ] Reported-by: James Nute Tested-by: James Nute Signed-off-by: Atsushi Nemoto Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-rs5c348.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 77074ccd2850..fd5c7af04ae5 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -122,9 +122,12 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_min = bcd2bin(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK); tm->tm_hour = bcd2bin(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK); if (!pdata->rtc_24h) { - tm->tm_hour %= 12; - if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) + if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) { + tm->tm_hour -= 20; + tm->tm_hour %= 12; tm->tm_hour += 12; + } else + tm->tm_hour %= 12; } tm->tm_wday = bcd2bin(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK); tm->tm_mday = bcd2bin(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK); -- GitLab From a0bfb9191135a16c84df7ba580ea839aefff4a0f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 15 Aug 2012 21:31:45 +0200 Subject: [PATCH 0494/1799] PM / Runtime: Fix rpm_resume() return value for power.no_callbacks set commit 7f321c26c04807834fef4c524d2b21573423fc74 upstream. For devices whose power.no_callbacks flag is set, rpm_resume() should return 1 if the device's parent is already active, so that the callers of pm_runtime_get() don't think that they have to wait for the device to resume (asynchronously) in that case (the core won't queue up an asynchronous resume in that case, so there's nothing to wait for anyway). Modify the code accordingly (and make sure that an idle notification will be queued up on success, even if 1 is to be returned). Signed-off-by: Rafael J. Wysocki Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/runtime.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index bd0f3949bcf9..7f4567c45fa5 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -652,6 +652,7 @@ static int rpm_resume(struct device *dev, int rpmflags) || dev->parent->power.runtime_status == RPM_ACTIVE) { atomic_inc(&dev->parent->power.child_count); spin_unlock(&dev->parent->power.lock); + retval = 1; goto no_callback; /* Assume success. */ } spin_unlock(&dev->parent->power.lock); @@ -735,7 +736,7 @@ static int rpm_resume(struct device *dev, int rpmflags) } wake_up_all(&dev->power.wait_queue); - if (!retval) + if (retval >= 0) rpm_idle(dev, RPM_ASYNC); out: -- GitLab From 7f2e6defbe27240e9d51e4eee2f2568d31956b79 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 15 Aug 2012 21:31:55 +0200 Subject: [PATCH 0495/1799] PM / Runtime: Clear power.deferred_resume on success in rpm_suspend() commit 58a34de7b1a920d287d17d2ca08bc9aaf7e6d35b upstream. The power.deferred_resume can only be set if the runtime PM status of device is RPM_SUSPENDING and it should be cleared after its status has been changed, regardless of whether or not the runtime suspend has been successful. However, it only is cleared on suspend failure, while it may remain set on successful suspend and is happily leaked to rpm_resume() executed in that case. That shouldn't happen, so if power.deferred_resume is set in rpm_suspend() after the status has been changed to RPM_SUSPENDED, clear it before calling rpm_resume(). Then, it doesn't need to be cleared before changing the status to RPM_SUSPENDING any more, because it's always cleared after the status has been changed to either RPM_SUSPENDED (on success) or RPM_ACTIVE (on failure). Signed-off-by: Rafael J. Wysocki Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/runtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 7f4567c45fa5..bb82b1817ae0 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -430,7 +430,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) goto repeat; } - dev->power.deferred_resume = false; if (dev->power.no_callbacks) goto no_callback; /* Assume success. */ @@ -506,6 +505,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) wake_up_all(&dev->power.wait_queue); if (dev->power.deferred_resume) { + dev->power.deferred_resume = false; rpm_resume(dev, 0); retval = -EAGAIN; goto out; -- GitLab From 95c1d943a1e7515643dcd8466ba82c3566f778b6 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Tue, 21 Aug 2012 16:16:02 -0700 Subject: [PATCH 0496/1799] drivers/misc/sgi-xp/xpc_uv.c: SGI XPC fails to load when cpu 0 is out of IRQ resources commit 7838f994b4fceff24c343f4e26a6cf4393869579 upstream. On many of our larger systems, CPU 0 has had all of its IRQ resources consumed before XPC loads. Worst cases on machines with multiple 10 GigE cards and multiple IB cards have depleted the entire first socket of IRQs. This patch makes selecting the node upon which IRQs are allocated (as well as all the other GRU Message Queue structures) specifiable as a module load param and has a default behavior of searching all nodes/cpus for an available resources. [akpm@linux-foundation.org: fix build: include cpu.h and module.h] 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 | 84 ++++++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 19 deletions(-) diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 17bbacb1b4b1..cc2ae7ec0d22 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -59,6 +61,8 @@ static struct xpc_heartbeat_uv *xpc_heartbeat_uv; XPC_NOTIFY_MSG_SIZE_UV) #define XPC_NOTIFY_IRQ_NAME "xpc_notify" +static int xpc_mq_node = -1; + static struct xpc_gru_mq_uv *xpc_activate_mq_uv; static struct xpc_gru_mq_uv *xpc_notify_mq_uv; @@ -109,11 +113,8 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name) #if defined CONFIG_X86_64 mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset, UV_AFFINITY_CPU); - if (mq->irq < 0) { - dev_err(xpc_part, "uv_setup_irq() returned error=%d\n", - -mq->irq); + if (mq->irq < 0) return mq->irq; - } mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset); @@ -238,8 +239,9 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, mq->mmr_blade = uv_cpu_to_blade_id(cpu); nid = cpu_to_node(cpu); - page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, - pg_order); + page = alloc_pages_exact_node(nid, + GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, + pg_order); if (page == NULL) { dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d " "bytes of memory on nid=%d for GRU mq\n", mq_size, nid); @@ -1731,9 +1733,50 @@ static struct xpc_arch_operations xpc_arch_ops_uv = { .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv, }; +static int +xpc_init_mq_node(int nid) +{ + int cpu; + + get_online_cpus(); + + for_each_cpu(cpu, cpumask_of_node(nid)) { + xpc_activate_mq_uv = + xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, nid, + XPC_ACTIVATE_IRQ_NAME, + xpc_handle_activate_IRQ_uv); + if (!IS_ERR(xpc_activate_mq_uv)) + break; + } + if (IS_ERR(xpc_activate_mq_uv)) { + put_online_cpus(); + return PTR_ERR(xpc_activate_mq_uv); + } + + for_each_cpu(cpu, cpumask_of_node(nid)) { + xpc_notify_mq_uv = + xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, nid, + XPC_NOTIFY_IRQ_NAME, + xpc_handle_notify_IRQ_uv); + if (!IS_ERR(xpc_notify_mq_uv)) + break; + } + if (IS_ERR(xpc_notify_mq_uv)) { + xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); + put_online_cpus(); + return PTR_ERR(xpc_notify_mq_uv); + } + + put_online_cpus(); + return 0; +} + int xpc_init_uv(void) { + int nid; + int ret = 0; + xpc_arch_ops = xpc_arch_ops_uv; if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) { @@ -1742,21 +1785,21 @@ xpc_init_uv(void) return -E2BIG; } - xpc_activate_mq_uv = xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, 0, - XPC_ACTIVATE_IRQ_NAME, - xpc_handle_activate_IRQ_uv); - if (IS_ERR(xpc_activate_mq_uv)) - return PTR_ERR(xpc_activate_mq_uv); + if (xpc_mq_node < 0) + for_each_online_node(nid) { + ret = xpc_init_mq_node(nid); - xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0, - XPC_NOTIFY_IRQ_NAME, - xpc_handle_notify_IRQ_uv); - if (IS_ERR(xpc_notify_mq_uv)) { - xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); - return PTR_ERR(xpc_notify_mq_uv); - } + if (!ret) + break; + } + else + ret = xpc_init_mq_node(xpc_mq_node); - return 0; + if (ret < 0) + dev_err(xpc_part, "xpc_init_mq_node() returned error=%d\n", + -ret); + + return ret; } void @@ -1765,3 +1808,6 @@ xpc_exit_uv(void) xpc_destroy_gru_mq_uv(xpc_notify_mq_uv); xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); } + +module_param(xpc_mq_node, int, 0); +MODULE_PARM_DESC(xpc_mq_node, "Node number on which to allocate message queues."); -- GitLab From 13e902acc58ef41e6516f160bd55976891d3b9cb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 21 Aug 2012 16:29:47 +1000 Subject: [PATCH 0497/1799] fbcon: fix race condition between console lock and cursor timer (v1.1) commit d8636a2717bb3da2a7ce2154bf08de90bb8c87b0 upstream. So we've had a fair few reports of fbcon handover breakage between efi/vesafb and i915 surface recently, so I dedicated a couple of days to finding the problem. Essentially the last thing we saw was the conflicting framebuffer message and that was all. So after much tracing with direct netconsole writes (printks under console_lock not so useful), I think I found the race. Thread A (driver load) Thread B (timer thread) unbind_con_driver -> | bind_con_driver -> | vc->vc_sw->con_deinit -> | fbcon_deinit -> | console_lock() | | | | fbcon_flashcursor timer fires | console_lock() <- blocked for A | | fbcon_del_cursor_timer -> del_timer_sync (BOOM) Of course because all of this is under the console lock, we never see anything, also since we also just unbound the active console guess what we never see anything. Hopefully this fixes the problem for anyone seeing vesafb->kms driver handoff. v1.1: add comment suggestion from Alan. Signed-off-by: Dave Airlie Acked-by: Alan Cox Tested-by: Josh Boyer Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/video/console/fbcon.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 2e471c22abf5..88e92041d8f0 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -372,8 +372,15 @@ static void fb_flashcursor(struct work_struct *work) struct vc_data *vc = NULL; int c; int mode; + int ret; + + /* FIXME: we should sort out the unbind locking instead */ + /* instead we just fail to flash the cursor if we can't get + * the lock instead of blocking fbcon deinit */ + ret = console_trylock(); + if (ret == 0) + return; - console_lock(); if (ops && ops->currcon != -1) vc = vc_cons[ops->currcon].d; -- GitLab From 8ff63613670a03eaa3524f4a55742c17ed105bc5 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 17 Aug 2012 14:40:04 -0400 Subject: [PATCH 0498/1799] drm/radeon: avoid turning off spread spectrum for used pll commit 5efcc76c13a745f98e7b6604d6aca49761be1970 upstream. If spread spectrum is enabled and in use for a given pll we should not turn it off as it will lead to turning off display for crtc that use the pll (this behavior was observed on chelsea edp). Signed-off-by: Jerome Glisse Reviewed-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_crtc.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index a53ca30d05e2..064742cf1131 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -444,11 +444,28 @@ union atom_enable_ss { static void atombios_crtc_program_ss(struct radeon_device *rdev, int enable, int pll_id, + int crtc_id, struct radeon_atom_ss *ss) { + unsigned i; int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); union atom_enable_ss args; + if (!enable) { + for (i = 0; i < 6; i++) { + if (rdev->mode_info.crtcs[i] && + rdev->mode_info.crtcs[i]->enabled && + i != crtc_id && + pll_id == rdev->mode_info.crtcs[i]->pll_id) { + /* one other crtc is using this pll don't turn + * off spread spectrum as it might turn off + * display on active crtc + */ + return; + } + } + } + memset(&args, 0, sizeof(args)); if (ASIC_IS_DCE5(rdev)) { @@ -1039,7 +1056,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, &ref_div, &post_div); - atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss); + atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss); atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, encoder_mode, radeon_encoder->encoder_id, mode->clock, @@ -1062,7 +1079,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode ss.step = step_size; } - atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss); + atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss); } } @@ -1571,11 +1588,11 @@ void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev) ASIC_INTERNAL_SS_ON_DCPLL, rdev->clock.default_dispclk); if (ss_enabled) - atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss); + atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, -1, &ss); /* XXX: DCE5, make sure voltage, dispclk is high enough */ atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk); if (ss_enabled) - atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss); + atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, -1, &ss); } } -- GitLab From 53c6c871480eb31207906a2c7e7e3a859339a8a3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 21 Aug 2012 18:52:56 -0400 Subject: [PATCH 0499/1799] drm/radeon/ss: use num_crtc rather than hardcoded 6 commit 5317670692f61675394db2eb6713484b67383750 upstream. When checking if a pll is in use. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 064742cf1131..d86f948b3886 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -452,7 +452,7 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, union atom_enable_ss args; if (!enable) { - for (i = 0; i < 6; i++) { + for (i = 0; i < rdev->num_crtc; i++) { if (rdev->mode_info.crtcs[i] && rdev->mode_info.crtcs[i]->enabled && i != crtc_id && -- GitLab From 0a1d9a860832a5ca43114cdebf0e8650463cc1f0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 16 Aug 2012 15:39:09 -0400 Subject: [PATCH 0500/1799] drm/radeon: split ATRM support out from the ATPX handler (v3) commit c61e2775873f603148e8e998a938721b7d222d24 upstream. There are systems that use ATRM, but not ATPX. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=41265 V2: fix #ifdefs as per Greg's comments V3: fix it harder Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon.h | 15 ---- drivers/gpu/drm/radeon/radeon_atpx_handler.c | 56 +------------- drivers/gpu/drm/radeon/radeon_bios.c | 80 +++++++++++++++++++- 3 files changed, 77 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 138b95216d8d..66150f0ffc73 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -138,21 +138,6 @@ struct radeon_device; /* * BIOS. */ -#define ATRM_BIOS_PAGE 4096 - -#if defined(CONFIG_VGA_SWITCHEROO) -bool radeon_atrm_supported(struct pci_dev *pdev); -int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len); -#else -static inline bool radeon_atrm_supported(struct pci_dev *pdev) -{ - return false; -} - -static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len){ - return -EINVAL; -} -#endif bool radeon_get_bios(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 98724fcb0088..2a2cf0b88a28 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -30,57 +30,8 @@ static struct radeon_atpx_priv { /* handle for device - and atpx */ acpi_handle dhandle; acpi_handle atpx_handle; - acpi_handle atrm_handle; } radeon_atpx_priv; -/* retrieve the ROM in 4k blocks */ -static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, - int offset, int len) -{ - acpi_status status; - union acpi_object atrm_arg_elements[2], *obj; - struct acpi_object_list atrm_arg; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; - - atrm_arg.count = 2; - atrm_arg.pointer = &atrm_arg_elements[0]; - - atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; - atrm_arg_elements[0].integer.value = offset; - - atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; - atrm_arg_elements[1].integer.value = len; - - status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); - if (ACPI_FAILURE(status)) { - printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); - return -ENODEV; - } - - obj = (union acpi_object *)buffer.pointer; - memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); - len = obj->buffer.length; - kfree(buffer.pointer); - return len; -} - -bool radeon_atrm_supported(struct pci_dev *pdev) -{ - /* get the discrete ROM only via ATRM */ - if (!radeon_atpx_priv.atpx_detected) - return false; - - if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev)) - return false; - return true; -} - - -int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len) -{ - return radeon_atrm_call(radeon_atpx_priv.atrm_handle, bios, offset, len); -} - static int radeon_atpx_get_version(acpi_handle handle) { acpi_status status; @@ -198,7 +149,7 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id, static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) { - acpi_handle dhandle, atpx_handle, atrm_handle; + acpi_handle dhandle, atpx_handle; acpi_status status; dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); @@ -209,13 +160,8 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) if (ACPI_FAILURE(status)) return false; - status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); - if (ACPI_FAILURE(status)) - return false; - radeon_atpx_priv.dhandle = dhandle; radeon_atpx_priv.atpx_handle = atpx_handle; - radeon_atpx_priv.atrm_handle = atrm_handle; return true; } diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 501f4881e5aa..f9b7f05f5413 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -98,16 +98,81 @@ static bool radeon_read_bios(struct radeon_device *rdev) return true; } +#ifdef CONFIG_ACPI /* ATRM is used to get the BIOS on the discrete cards in * dual-gpu systems. */ +/* retrieve the ROM in 4k blocks */ +#define ATRM_BIOS_PAGE 4096 +/** + * radeon_atrm_call - fetch a chunk of the vbios + * + * @atrm_handle: acpi ATRM handle + * @bios: vbios image pointer + * @offset: offset of vbios image data to fetch + * @len: length of vbios image data to fetch + * + * Executes ATRM to fetch a chunk of the discrete + * vbios image on PX systems (all asics). + * Returns the length of the buffer fetched. + */ +static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, + int offset, int len) +{ + acpi_status status; + union acpi_object atrm_arg_elements[2], *obj; + struct acpi_object_list atrm_arg; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; + + atrm_arg.count = 2; + atrm_arg.pointer = &atrm_arg_elements[0]; + + atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[0].integer.value = offset; + + atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[1].integer.value = len; + + status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); + if (ACPI_FAILURE(status)) { + printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); + return -ENODEV; + } + + obj = (union acpi_object *)buffer.pointer; + memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); + len = obj->buffer.length; + kfree(buffer.pointer); + return len; +} + static bool radeon_atrm_get_bios(struct radeon_device *rdev) { int ret; int size = 256 * 1024; int i; + struct pci_dev *pdev = NULL; + acpi_handle dhandle, atrm_handle; + acpi_status status; + bool found = false; - if (!radeon_atrm_supported(rdev->pdev)) + /* ATRM is for the discrete card only */ + if (rdev->flags & RADEON_IS_IGP) + return false; + + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { + dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); + if (!dhandle) + continue; + + status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); + if (!ACPI_FAILURE(status)) { + found = true; + break; + } + } + + if (!found) return false; rdev->bios = kmalloc(size, GFP_KERNEL); @@ -117,9 +182,10 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) } for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { - ret = radeon_atrm_get_bios_chunk(rdev->bios, - (i * ATRM_BIOS_PAGE), - ATRM_BIOS_PAGE); + ret = radeon_atrm_call(atrm_handle, + rdev->bios, + (i * ATRM_BIOS_PAGE), + ATRM_BIOS_PAGE); if (ret < ATRM_BIOS_PAGE) break; } @@ -130,6 +196,12 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) } return true; } +#else +static inline bool radeon_atrm_get_bios(struct radeon_device *rdev) +{ + return false; +} +#endif static bool ni_read_disabled_bios(struct radeon_device *rdev) { -- GitLab From 25413e693f697f801e1cc8fd10e90a7821a3a04b Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 16 Aug 2012 15:45:20 -0400 Subject: [PATCH 0501/1799] drm/radeon: implement ACPI VFCT vbios fetch (v3) commit 268ba0a99f89a84dc5eb312470896113d0709c74 upstream. This is required for pure UEFI systems. The vbios is stored in ACPI rather than at the legacy vga location. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=26891 V2: fix #ifdefs as per Greg's comments V3: fix it harder Signed-off-by: Alex Deucher Reviewed-by: Jerome Glisse Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_bios.c | 60 ++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index f9b7f05f5413..602898dd1669 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -32,6 +32,7 @@ #include #include +#include /* * BIOS. */ @@ -548,6 +549,63 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) return legacy_read_disabled_bios(rdev); } +#ifdef CONFIG_ACPI +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + bool ret = false; + struct acpi_table_header *hdr; + /* acpi_get_table_with_size is not exported :( */ + acpi_size tbl_size = 0x7fffffff; + UEFI_ACPI_VFCT *vfct; + GOP_VBIOS_CONTENT *vbios; + VFCT_IMAGE_HEADER *vhdr; + + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + return false; + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); + goto out_unmap; + } + + vfct = (UEFI_ACPI_VFCT *)hdr; + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); + goto out_unmap; + } + + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); + vhdr = &vbios->VbiosHeader; + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); + + if (vhdr->PCIBus != rdev->pdev->bus->number || + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || + vhdr->VendorID != rdev->pdev->vendor || + vhdr->DeviceID != rdev->pdev->device) { + DRM_INFO("ACPI VFCT table is not for this card\n"); + goto out_unmap; + }; + + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); + goto out_unmap; + } + + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); + ret = !!rdev->bios; + +out_unmap: + /* uh, no idea what to do here... */ + return ret; +} +#else +static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + return false; +} +#endif bool radeon_get_bios(struct radeon_device *rdev) { @@ -555,6 +613,8 @@ bool radeon_get_bios(struct radeon_device *rdev) uint16_t tmp; r = radeon_atrm_get_bios(rdev); + if (r == false) + r = radeon_acpi_vfct_bios(rdev); if (r == false) r = igp_read_bios_from_vram(rdev); if (r == false) -- GitLab From 9e4f7198fda9c9d9effccff1a9d56ea2b0b3d4b4 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 20 Aug 2012 15:16:04 +0100 Subject: [PATCH 0502/1799] drm/radeon/kms: extend the Fujitsu D3003-S2 board connector quirk to cover later silicon stepping commit 52e9b39d9a89ae33662596bd30e62dd56bddbe73 upstream. There is a more recent APU stepping with a new PCI ID shipping in the same board by Fujitsu which needs the same quirk to correctly mark the back plane connectors. Signed-off-by: Tvrtko Ursulin Signed-off-by: Alex Deucher 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 b1e3820df363..5e30e126bfe1 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -452,7 +452,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, } /* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */ - if ((dev->pdev->device == 0x9802) && + if (((dev->pdev->device == 0x9802) || (dev->pdev->device == 0x9806)) && (dev->pdev->subsystem_vendor == 0x1734) && (dev->pdev->subsystem_device == 0x11bd)) { if (*connector_type == DRM_MODE_CONNECTOR_VGA) { -- GitLab From 33822abf1d7190dd8dab1da87661bde5208de6c8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 13 Aug 2012 13:22:34 +0300 Subject: [PATCH 0503/1799] drm/i915: extract connector update from intel_ddc_get_modes() for reuse commit 4eab81366465aedcfd26de960c595bc03599c09f upstream. Refactor the connector update part of intel_ddc_get_modes() into a separate intel_connector_update_modes() function for reuse. No functional changes. Signed-off-by: Jani Nikula Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45881 Tested-by: Alex Ferrando Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_modes.c | 31 +++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 715afa153025..2cae72d17499 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -288,6 +288,8 @@ struct intel_fbc_work { int interval; }; +int intel_connector_update_modes(struct drm_connector *connector, + struct edid *edid); int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus); diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index d1928e79d9b6..9a2b27031a4d 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -59,6 +59,25 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus) return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 2) == 2; } +/** + * intel_connector_update_modes - update connector from edid + * @connector: DRM connector device to use + * @edid: previously read EDID information + */ +int intel_connector_update_modes(struct drm_connector *connector, + struct edid *edid) +{ + int ret; + + drm_mode_connector_update_edid_property(connector, edid); + ret = drm_add_edid_modes(connector, edid); + drm_edid_to_eld(connector, edid); + connector->display_info.raw_edid = NULL; + kfree(edid); + + return ret; +} + /** * intel_ddc_get_modes - get modelist from monitor * @connector: DRM connector device to use @@ -70,18 +89,12 @@ int intel_ddc_get_modes(struct drm_connector *connector, struct i2c_adapter *adapter) { struct edid *edid; - int ret = 0; edid = drm_get_edid(connector, adapter); - if (edid) { - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - drm_edid_to_eld(connector, edid); - connector->display_info.raw_edid = NULL; - kfree(edid); - } + if (!edid) + return 0; - return ret; + return intel_connector_update_modes(connector, edid); } static const struct drm_prop_enum_list force_audio_names[] = { -- GitLab From 91a1da919e60a62ed3dfb10296e8eed4eb2b03bd Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Mon, 20 Aug 2012 23:01:51 +0200 Subject: [PATCH 0504/1799] asus-laptop: HRWS/HWRS typo commit 8871e99f89b7d7b1ea99de550eea2a56273f42ab upstream. Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=24222 Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/asus-laptop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index e38f91be0b10..110c7778cbf9 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -863,9 +863,9 @@ static ssize_t show_infos(struct device *dev, * The significance of others is yet to be found. * If we don't find the method, we assume the device are present. */ - rv = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &temp); + rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp); if (!ACPI_FAILURE(rv)) - len += sprintf(page + len, "HRWS value : %#x\n", + len += sprintf(page + len, "HWRS value : %#x\n", (uint) temp); /* * Another value for userspace: the ASYM method returns 0x02 for @@ -1751,9 +1751,9 @@ static int asus_laptop_get_info(struct asus_laptop *asus) * The significance of others is yet to be found. */ status = - acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result); + acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result); if (!ACPI_FAILURE(status)) - pr_notice(" HRWS returned %x", (int)hwrs_result); + pr_notice(" HWRS returned %x", (int)hwrs_result); if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) asus->have_rsts = true; -- GitLab From 4368ade3ff2bfff1033f9e5758630b3d4e8f7e71 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 4 Jul 2012 15:20:14 +0800 Subject: [PATCH 0505/1799] asus-nb-wmi: add some video toggle keys commit 3766054fff4af1b58a1440a284907887f4d2e8be upstream. There are some new video switch keys that used by newer machines. 0xA0 - SDSP HDMI only 0xA1 - SDSP LCD + HDMI 0xA2 - SDSP CRT + HDMI 0xA3 - SDSP TV + HDMI But in Linux, there is no suitable userspace application to handle this, so, mapping them all to KEY_SWITCHVIDEOMODE. Signed-off-by: AceLan Kao Signed-off-by: Matthew Garrett Cc: Tim Gardner Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/asus-nb-wmi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 99a30b513137..6de14fd090a0 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -94,6 +94,10 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0x8A, { KEY_PROG1 } }, { KE_KEY, 0x95, { KEY_MEDIA } }, { KE_KEY, 0x99, { KEY_PHONE } }, + { KE_KEY, 0xA0, { KEY_SWITCHVIDEOMODE } }, /* SDSP HDMI only */ + { KE_KEY, 0xA1, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + HDMI */ + { KE_KEY, 0xA2, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + HDMI */ + { KE_KEY, 0xA3, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + HDMI */ { KE_KEY, 0xb5, { KEY_CALC } }, { KE_KEY, 0xc4, { KEY_KBDILLUMUP } }, { KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } }, -- GitLab From 2607b9407db4cbc16d5a130c8c16702711c3b7be Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 16 Aug 2012 08:29:03 +0000 Subject: [PATCH 0506/1799] drm: Check for invalid cursor flags commit 7c4eaca4162d0b5ad4fb39f974d7ffd71b9daa09 upstream. Signed-off-by: Jakob Bornecrantz Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_crtc.c | 2 +- include/drm/drm_mode.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index c79870a75c2f..7e479a42af0b 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1981,7 +1981,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - if (!req->flags) + if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags)) return -EINVAL; mutex_lock(&dev->mode_config.mutex); diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index 4a0aae38e160..9242310b47cd 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -343,8 +343,9 @@ struct drm_mode_mode_cmd { struct drm_mode_modeinfo mode; }; -#define DRM_MODE_CURSOR_BO (1<<0) -#define DRM_MODE_CURSOR_MOVE (1<<1) +#define DRM_MODE_CURSOR_BO 0x01 +#define DRM_MODE_CURSOR_MOVE 0x02 +#define DRM_MODE_CURSOR_FLAGS 0x03 /* * depending on the value in flags different members are used. -- GitLab From d468e2150f5f52ea7b0c459366028f28cc1cf96b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 22 Aug 2012 09:54:56 -0400 Subject: [PATCH 0507/1799] drm/radeon/atom: rework DIG modesetting on DCE3+ commit 8d1af57ae3c4458ed0de93ef97f388dd1b3239c7 upstream. The ordering is important and the current drm code wasn't cutting it for modern DIG encoders. We need to have information about crtc before setting up the encoders so I've shifted the ordering a bit. Probably we'll need a full rework akin to danvet's recent intel patchs. This patch fixes numerous issues with DP bridge chips and makes link training much more reliable. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_encoders.c | 109 +++++++++------------ 1 file changed, 47 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index a3ae788a2af2..39b36252ca37 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1379,6 +1379,8 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); struct radeon_connector *radeon_connector = NULL; struct radeon_connector_atom_dig *radeon_dig_connector = NULL; @@ -1390,19 +1392,37 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) switch (mode) { case DRM_MODE_DPMS_ON: - /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) || - ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { - if (ASIC_IS_DCE6(rdev)) { - /* It seems we need to call ATOM_ENCODER_CMD_SETUP again - * before reenabling encoder on DPMS ON, otherwise we never - * get picture - */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + if (!connector) + dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + else + dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); + + /* setup and enable the encoder */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + atombios_dig_encoder_setup(encoder, + ATOM_ENCODER_CMD_SETUP_PANEL_MODE, + dig->panel_mode); + if (ext_encoder) { + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); } atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - } else { + } else if (ASIC_IS_DCE4(rdev)) { + /* setup and enable the encoder */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + /* enable the transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); + } else { + /* setup and enable the encoder and transmitter */ + atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); + /* some early dce3.2 boards have a bug in their transmitter control table */ + if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730)) + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { @@ -1420,10 +1440,19 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + /* disable the transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - else + } else if (ASIC_IS_DCE4(rdev)) { + /* disable the transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + } else { + /* disable the encoder and transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); + } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (ASIC_IS_DCE4(rdev)) atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); @@ -1848,10 +1877,12 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); radeon_encoder->pixel_clock = adjusted_mode->clock; + /* need to call this here rather than in prepare() since we need some crtc info */ + radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); + if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) { if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) atombios_yuv_setup(encoder, true); @@ -1870,38 +1901,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { - struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); - struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - - if (!connector) - dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; - else - dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); - - /* setup and enable the encoder */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); - atombios_dig_encoder_setup(encoder, - ATOM_ENCODER_CMD_SETUP_PANEL_MODE, - dig->panel_mode); - } else if (ASIC_IS_DCE4(rdev)) { - /* disable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - /* setup and enable the encoder */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); - - /* enable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - } else { - /* disable the encoder and transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); - - /* setup and enable the encoder and transmitter */ - atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - } + /* handled in dpms */ break; case ENCODER_OBJECT_ID_INTERNAL_DDI: case ENCODER_OBJECT_ID_INTERNAL_DVO1: @@ -1922,14 +1922,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, break; } - if (ext_encoder) { - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) - atombios_external_encoder_setup(encoder, ext_encoder, - EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); - else - atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); - } - atombios_apply_encoder_quirks(encoder, adjusted_mode); if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { @@ -2102,7 +2094,6 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) } radeon_atom_output_lock(encoder, true); - radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); if (connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -2123,6 +2114,7 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) static void radeon_atom_encoder_commit(struct drm_encoder *encoder) { + /* need to call this here as we need the crtc set up */ radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON); radeon_atom_output_lock(encoder, false); } @@ -2163,14 +2155,7 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - if (ASIC_IS_DCE4(rdev)) - /* disable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - else { - /* disable the encoder and transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); - } + /* handled in dpms */ break; case ENCODER_OBJECT_ID_INTERNAL_DDI: case ENCODER_OBJECT_ID_INTERNAL_DVO1: -- GitLab From 853a847c89384d47afcad59beeecb535fe733402 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 24 Aug 2012 18:21:21 -0400 Subject: [PATCH 0508/1799] drm/radeon/atom: powergating fixes for DCE6 commit c205b232a64fed6d26edd7e40985b396de99a27f upstream. Power gating is per crtc pair, but the powergating registers should be called individually. The hw handles power up/down properly. The pair is powered up if either crtc in the pair is powered up and the pair is not powered down until both crtcs in the pair are powered down. This simplifies programming and should save additional power as the previous code never actually power gated the crtc pair. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_crtc.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index d86f948b3886..71bd61c33b7d 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -258,7 +258,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) radeon_crtc->enabled = true; /* adjust pm to dpms changes BEFORE enabling crtcs */ radeon_pm_compute_clocks(rdev); - /* disable crtc pair power gating before programming */ if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) atombios_powergate_crtc(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_ENABLE); @@ -278,25 +277,8 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_DISABLE); radeon_crtc->enabled = false; - /* power gating is per-pair */ - if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) { - struct drm_crtc *other_crtc; - struct radeon_crtc *other_radeon_crtc; - list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { - other_radeon_crtc = to_radeon_crtc(other_crtc); - if (((radeon_crtc->crtc_id == 0) && (other_radeon_crtc->crtc_id == 1)) || - ((radeon_crtc->crtc_id == 1) && (other_radeon_crtc->crtc_id == 0)) || - ((radeon_crtc->crtc_id == 2) && (other_radeon_crtc->crtc_id == 3)) || - ((radeon_crtc->crtc_id == 3) && (other_radeon_crtc->crtc_id == 2)) || - ((radeon_crtc->crtc_id == 4) && (other_radeon_crtc->crtc_id == 5)) || - ((radeon_crtc->crtc_id == 5) && (other_radeon_crtc->crtc_id == 4))) { - /* if both crtcs in the pair are off, enable power gating */ - if (other_radeon_crtc->enabled == false) - atombios_powergate_crtc(crtc, ATOM_ENABLE); - break; - } - } - } + if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) + atombios_powergate_crtc(crtc, ATOM_ENABLE); /* adjust pm to dpms changes AFTER disabling crtcs */ radeon_pm_compute_clocks(rdev); break; -- GitLab From 6992255930809bc988366e7177126dab74e7df95 Mon Sep 17 00:00:00 2001 From: "Xu, Anhua" Date: Mon, 13 Aug 2012 03:08:33 +0000 Subject: [PATCH 0509/1799] drm/i915: fix wrong order of parameters in port checking functions commit b70ad586162609141f0aa9eb34790f31a8954f89 upstream. Wrong order of parameters passed-in when calling hdmi/adpa /lvds_pipe_enabled(), 2nd and 3rd parameters are reversed. This bug was indroduced by commit 1519b9956eb4b4180fa3f47c73341463cdcfaa37 Author: Keith Packard Date: Sat Aug 6 10:35:34 2011 -0700 drm/i915: Fix PCH port pipe select in CPT disable paths The reachable tag for this commit is v3.1-rc1-3-g1519b99 Signed-off-by: Anhua Xu Reviewed-by: Chris Wilson Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=44876 Tested-by: Daniel Schroeder Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3de3d9b670bb..498bcbeb992f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1099,7 +1099,7 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = I915_READ(reg); - WARN(hdmi_pipe_enabled(dev_priv, val, pipe), + WARN(hdmi_pipe_enabled(dev_priv, pipe, val), "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); } @@ -1116,13 +1116,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, reg = PCH_ADPA; val = I915_READ(reg); - WARN(adpa_pipe_enabled(dev_priv, val, pipe), + WARN(adpa_pipe_enabled(dev_priv, pipe, val), "PCH VGA enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); reg = PCH_LVDS; val = I915_READ(reg); - WARN(lvds_pipe_enabled(dev_priv, val, pipe), + WARN(lvds_pipe_enabled(dev_priv, pipe, val), "PCH LVDS enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); @@ -1487,7 +1487,7 @@ static void disable_pch_hdmi(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = I915_READ(reg); - if (hdmi_pipe_enabled(dev_priv, val, pipe)) { + if (hdmi_pipe_enabled(dev_priv, pipe, val)) { DRM_DEBUG_KMS("Disabling pch HDMI %x on pipe %d\n", reg, pipe); I915_WRITE(reg, val & ~PORT_ENABLE); @@ -1509,12 +1509,12 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv, reg = PCH_ADPA; val = I915_READ(reg); - if (adpa_pipe_enabled(dev_priv, val, pipe)) + if (adpa_pipe_enabled(dev_priv, pipe, val)) I915_WRITE(reg, val & ~ADPA_DAC_ENABLE); reg = PCH_LVDS; val = I915_READ(reg); - if (lvds_pipe_enabled(dev_priv, val, pipe)) { + if (lvds_pipe_enabled(dev_priv, pipe, val)) { DRM_DEBUG_KMS("disable lvds on pipe %d val 0x%08x\n", pipe, val); I915_WRITE(reg, val & ~LVDS_PORT_EN); POSTING_READ(reg); -- GitLab From ea708eb2c1843004a41d0beeac724451202513ff Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 20 Aug 2012 11:06:21 -0400 Subject: [PATCH 0510/1799] drm/radeon: convert radeon vfct code to use acpi_get_table_with_size commit 7c3906d04a4587dceaa78cc1ae6b14e6454ee02a upstream. Allows us to verify the table size. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_bios.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 602898dd1669..d306cc8fdeaa 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -554,13 +554,12 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) { bool ret = false; struct acpi_table_header *hdr; - /* acpi_get_table_with_size is not exported :( */ - acpi_size tbl_size = 0x7fffffff; + acpi_size tbl_size; UEFI_ACPI_VFCT *vfct; GOP_VBIOS_CONTENT *vbios; VFCT_IMAGE_HEADER *vhdr; - if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size))) return false; if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); @@ -597,7 +596,6 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) ret = !!rdev->bios; out_unmap: - /* uh, no idea what to do here... */ return ret; } #else -- GitLab From 5f566f0b27ebddb41b5bd42484047ae96d645704 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 21 Aug 2012 19:06:21 -0400 Subject: [PATCH 0511/1799] drm/radeon: don't disable plls that are in use by other crtcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4e58591c8961b3e31709313f75819f2eec06e322 upstream. Some plls are shared for DP. Signed-off-by: Alex Deucher Reviewed-by: Michel Dänzer 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 71bd61c33b7d..19f4082c6181 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1663,9 +1663,22 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_atom_ss ss; + int i; atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + for (i = 0; i < rdev->num_crtc; i++) { + if (rdev->mode_info.crtcs[i] && + rdev->mode_info.crtcs[i]->enabled && + i != radeon_crtc->crtc_id && + radeon_crtc->pll_id == rdev->mode_info.crtcs[i]->pll_id) { + /* one other crtc is using this pll don't turn + * off the pll + */ + goto done; + } + } + switch (radeon_crtc->pll_id) { case ATOM_PPLL1: case ATOM_PPLL2: @@ -1682,6 +1695,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) default: break; } +done: radeon_crtc->pll_id = -1; } -- GitLab From d6ce9c9ced227fde03cd1377f190c2cd469e09e0 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Tue, 28 Aug 2012 16:50:22 -0400 Subject: [PATCH 0512/1799] drm/radeon: force dma32 to fix regression rs4xx,rs6xx,rs740 commit 4a2b6662c3632176b4fdf012243dd3751367bf1f upstream. It seems some of those IGP dislike non dma32 page despite what documentation says. Fix regression since we allowed non dma32 pages. It seems it only affect some revision of those IGP chips as we don't know which one just force dma32 for all of them. https://bugzilla.redhat.com/show_bug.cgi?id=785375 Signed-off-by: Jerome Glisse Signed-off-by: Alex Deucher 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 5992502a3448..de5e0b51dc63 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -772,7 +772,7 @@ int radeon_device_init(struct radeon_device *rdev, if (rdev->flags & RADEON_IS_AGP) rdev->need_dma32 = true; if ((rdev->flags & RADEON_IS_PCI) && - (rdev->family < CHIP_RS400)) + (rdev->family <= CHIP_RS740)) rdev->need_dma32 = true; dma_bits = rdev->need_dma32 ? 32 : 40; -- GitLab From fcb836f584992f104bcbae16829760e3db876491 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 29 Aug 2012 19:48:26 -0400 Subject: [PATCH 0513/1799] drm/radeon: fix dig encoder selection on DCE61 commit 41fa54377057ab38bc3e08ebb46168a7daf2e63b upstream. Was using the DCE41 code which was wrong. Fixes blank displays on a number of Trinity systems. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_encoders.c | 31 ++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 39b36252ca37..2d07fbf2c27c 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1769,13 +1769,34 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_encoder *test_encoder; - struct radeon_encoder_atom_dig *dig; + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; uint32_t dig_enc_in_use = 0; - /* DCE4/5 */ - if (ASIC_IS_DCE4(rdev)) { - dig = radeon_encoder->enc_priv; - if (ASIC_IS_DCE41(rdev)) { + if (ASIC_IS_DCE6(rdev)) { + /* DCE6 */ + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + if (dig->linkb) + return 1; + else + return 0; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + if (dig->linkb) + return 3; + else + return 2; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + if (dig->linkb) + return 5; + else + return 4; + break; + } + } else if (ASIC_IS_DCE4(rdev)) { + /* DCE4/5 */ + if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) { /* ontario follows DCE4 */ if (rdev->family == CHIP_PALM) { if (dig->linkb) -- GitLab From 4b4ceb8aca588b3ea3e385a31cef9b92f18021af Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 14 Sep 2012 13:28:23 +1000 Subject: [PATCH 0514/1799] drm/nouveau: fix booting with plymouth + dumb support commit 610bd7da160f76f1644ecb4cd7f39511b49a22cc upstream. We noticed a plymouth bug on Fedora 18, and I then noticed this stupid thinko, fixing it fixed the problem with plymouth. Acked-by: Ben Skeggs Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nouveau_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index a85e112863d1..f233b8fe2dad 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -586,7 +586,7 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, args->size = args->pitch * args->height; args->size = roundup(args->size, PAGE_SIZE); - ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo); + ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo); if (ret) return ret; -- GitLab From 1f7edfcc0a87e5daf273981135e376ed61d284e4 Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Thu, 13 Sep 2012 07:43:22 +0800 Subject: [PATCH 0515/1799] drm/i915: HDMI - Clear Audio Enable bit for Hot Plug commit b98b60167279df3acac9422c3c9820d9ebbcf9fb upstream. Clear Audio Enable bit to trigger unsolicated event to notify Audio Driver part the HDMI hot plug change. The patch fixed the bug when remove HDMI cable the bit was not cleared correctly. In intel_hdmi_dpms(), if intel_hdmi->has_audio been true, the "Audio enable bit" will be set to trigger unsolicated event to notify Alsa driver the change. intel_hdmi->has_audio will be reset to false from intel_hdmi_detect() after remove the hdmi cable, here's debug log: [ 187.494153] [drm:output_poll_execute], [CONNECTOR:17:HDMI-A-1] status updated from 1 to 2 [ 187.525349] [drm:intel_hdmi_detect], HDMI: has_audio = 0 so when comes back to intel_hdmi_dpms(), the "Audio enable bit" will not be cleared. And this cause the eld infomation and pin presence doesnot update accordingly in alsa driver side. This patch will also trigger unsolicated event to alsa driver to notify the hot plug event: [ 187.853159] ALSA sound/pci/hda/patch_hdmi.c:772 HDMI hot plug event: Codec=3 Pin=5 Presence_Detect=0 ELD_Valid=1 [ 187.853268] ALSA sound/pci/hda/patch_hdmi.c:990 HDMI status: Codec=3 Pin=5 Presence_Detect=0 ELD_Valid=0 Signed-off-by: Wang Xingchao Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 2d7f47b56b6a..fb44e9d116e4 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -271,7 +271,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) u32 temp; u32 enable_bits = SDVO_ENABLE; - if (intel_hdmi->has_audio) + if (intel_hdmi->has_audio || mode != DRM_MODE_DPMS_ON) enable_bits |= SDVO_AUDIO_ENABLE; temp = I915_READ(intel_hdmi->sdvox_reg); -- GitLab From 956b165f9e89e37aff44d615321d1e3166589701 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 18 Aug 2012 09:51:42 +1000 Subject: [PATCH 0516/1799] md/raid10: fix problem with on-stack allocation of r10bio structure. commit e0ee778528bbaad28a5c69d2e219269a3a096607 upstream. A 'struct r10bio' has an array of per-copy information at the end. This array is declared with size [0] and r10bio_pool_alloc allocates enough extra space to store the per-copy information depending on the number of copies needed. So declaring a 'struct r10bio on the stack isn't going to work. It won't allocate enough space, and memory corruption will ensue. So in the two places where this is done, declare a sufficiently large structure and use that instead. The two call-sites of this bug were introduced in 3.4 and 3.5 so this is suitable for both those kernels. The patch will have to be modified for 3.4 as it only has one bug. Reported-by: Ivan Vasilyev Tested-by: Ivan Vasilyev Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid10.c | 16 ++++++++++------ drivers/md/raid10.h | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index a954c95d7c92..1f7e8cd44e5c 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -612,20 +612,24 @@ static int raid10_mergeable_bvec(struct request_queue *q, max = biovec->bv_len; if (mddev->merge_check_needed) { - struct r10bio r10_bio; + struct { + struct r10bio r10_bio; + struct r10dev devs[conf->copies]; + } on_stack; + struct r10bio *r10_bio = &on_stack.r10_bio; int s; - r10_bio.sector = sector; - raid10_find_phys(conf, &r10_bio); + r10_bio->sector = sector; + raid10_find_phys(conf, r10_bio); rcu_read_lock(); for (s = 0; s < conf->copies; s++) { - int disk = r10_bio.devs[s].devnum; + int disk = r10_bio->devs[s].devnum; struct md_rdev *rdev = rcu_dereference( conf->mirrors[disk].rdev); if (rdev && !test_bit(Faulty, &rdev->flags)) { struct request_queue *q = bdev_get_queue(rdev->bdev); if (q->merge_bvec_fn) { - bvm->bi_sector = r10_bio.devs[s].addr + bvm->bi_sector = r10_bio->devs[s].addr + rdev->data_offset; bvm->bi_bdev = rdev->bdev; max = min(max, q->merge_bvec_fn( @@ -637,7 +641,7 @@ static int raid10_mergeable_bvec(struct request_queue *q, struct request_queue *q = bdev_get_queue(rdev->bdev); if (q->merge_bvec_fn) { - bvm->bi_sector = r10_bio.devs[s].addr + bvm->bi_sector = r10_bio->devs[s].addr + rdev->data_offset; bvm->bi_bdev = rdev->bdev; max = min(max, q->merge_bvec_fn( diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index 7c615613c381..24d45b8af5c9 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h @@ -104,7 +104,7 @@ struct r10bio { * We choose the number when they are allocated. * We sometimes need an extra bio to write to the replacement. */ - struct { + struct r10dev { struct bio *bio; union { struct bio *repl_bio; /* used for resync and -- GitLab From 6adebb0e1d4820435e0c6739b0de20a196cc20d5 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Sun, 2 Sep 2012 00:28:19 +0800 Subject: [PATCH 0517/1799] workqueue: UNBOUND -> REBIND morphing in rebind_workers() should be atomic commit 96e65306b81351b656835c15931d1d237b252f27 upstream. The compiler may compile the following code into TWO write/modify instructions. worker->flags &= ~WORKER_UNBOUND; worker->flags |= WORKER_REBIND; so the other CPU may temporarily see worker->flags which doesn't have either WORKER_UNBOUND or WORKER_REBIND set and perform local wakeup prematurely. Fix it by using single explicit assignment via ACCESS_ONCE(). Because idle workers have another WORKER_NOT_RUNNING flag, this bug doesn't exist for them; however, update it to use the same pattern for consistency. tj: Applied the change to idle workers too and updated comments and patch description a bit. Signed-off-by: Lai Jiangshan Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- kernel/workqueue.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index f483dd0bc9c9..7584322349c1 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3433,14 +3433,17 @@ static int __cpuinit trustee_thread(void *__gcwq) for_each_busy_worker(worker, i, pos, gcwq) { struct work_struct *rebind_work = &worker->rebind_work; + unsigned long worker_flags = worker->flags; /* * Rebind_work may race with future cpu hotplug * operations. Use a separate flag to mark that - * rebinding is scheduled. + * rebinding is scheduled. The morphing should + * be atomic. */ - worker->flags |= WORKER_REBIND; - worker->flags &= ~WORKER_ROGUE; + worker_flags |= WORKER_REBIND; + worker_flags &= ~WORKER_ROGUE; + ACCESS_ONCE(worker->flags) = worker_flags; /* queue rebind_work, wq doesn't matter, use the default one */ if (test_and_set_bit(WORK_STRUCT_PENDING_BIT, -- GitLab From 6c9e62877051270d20e34c0c3652e36f1cc37c04 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 15 May 2012 18:44:15 +0100 Subject: [PATCH 0518/1799] x86: Fix boot on Twinhead H12Y commit 80b3e557371205566a71e569fbfcce5b11f92dbe upstream. Despite lots of investigation into why this is needed we don't know or have an elegant cure. The only answer found on this laptop is to mark a problem region as used so that Linux doesn't put anything there. Currently all the users add reserve= command lines and anyone not knowing this needs to find the magic page that documents it. Automate it instead. Signed-off-by: Alan Cox Tested-and-bugfixed-by: Arne Fitzenreiter Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=10231 Link: http://lkml.kernel.org/r/20120515174347.5109.94551.stgit@bluebook Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/pci/fixup.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index d0e6e403b4f6..5dd467bd6121 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -519,3 +519,20 @@ static void sb600_disable_hpet_bar(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4385, sb600_disable_hpet_bar); + +/* + * Twinhead H12Y needs us to block out a region otherwise we map devices + * there and any access kills the box. + * + * See: https://bugzilla.kernel.org/show_bug.cgi?id=10231 + * + * Match off the LPC and svid/sdid (older kernels lose the bridge subvendor) + */ +static void __devinit twinhead_reserve_killing_zone(struct pci_dev *dev) +{ + if (dev->subsystem_vendor == 0x14FF && dev->subsystem_device == 0xA003) { + pr_info("Reserving memory on Twinhead H12Y\n"); + request_mem_region(0xFFB00000, 0x100000, "twinhead"); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone); -- GitLab From 2b9ec261e3f247dc84b50263564778bcbefec79b Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 2 May 2012 11:41:30 +0800 Subject: [PATCH 0519/1799] macvtap: zerocopy: fix offset calculation when building skb commit 3afc9621f15701c557e60f61eba9242bac2771dd upstream. This patch fixes the offset calculation when building skb: - offset1 were used as skb data offset not vector offset - reset offset to zero only when we advance to next vector Signed-off-by: Jason Wang Signed-off-by: Michael S. Tsirkin Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/net/macvtap.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index c1d602d5f15e..0302bc5adc69 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -506,10 +506,11 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, if (copy > size) { ++from; --count; - } + offset = 0; + } else + offset += size; copy -= size; offset1 += size; - offset = 0; } if (len == offset1) @@ -520,13 +521,13 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, int num_pages; unsigned long base; - len = from->iov_len - offset1; + len = from->iov_len - offset; if (!len) { - offset1 = 0; + offset = 0; ++from; continue; } - base = (unsigned long)from->iov_base + offset1; + base = (unsigned long)from->iov_base + offset; size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; if (i + size > MAX_SKB_FRAGS) return -EMSGSIZE; @@ -548,7 +549,7 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, len -= size; i++; } - offset1 = 0; + offset = 0; ++from; } return 0; -- GitLab From bfd1678ca0143060686d87ae0c07bebab6f0245b Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 2 May 2012 11:41:44 +0800 Subject: [PATCH 0520/1799] macvtap: zerocopy: fix truesize underestimation commit 4ef67ebedffa44ed9939b34708ac2fee06d2f65f upstream. As the skb fragment were pinned/built from user pages, we should account the page instead of length for truesize. Signed-off-by: Jason Wang Signed-off-by: Michael S. Tsirkin Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/net/macvtap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 0302bc5adc69..cf096e0693e2 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -520,6 +520,7 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, struct page *page[MAX_SKB_FRAGS]; int num_pages; unsigned long base; + unsigned long truesize; len = from->iov_len - offset; if (!len) { @@ -535,10 +536,11 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, if (num_pages != size) /* put_page is in skb free */ return -EFAULT; + truesize = size * PAGE_SIZE; skb->data_len += len; skb->len += len; - skb->truesize += len; - atomic_add(len, &skb->sk->sk_wmem_alloc); + skb->truesize += truesize; + atomic_add(truesize, &skb->sk->sk_wmem_alloc); while (len) { int off = base & ~PAGE_MASK; int size = min_t(int, len, PAGE_SIZE - off); -- GitLab From 61f26eb401b04a9312c422a5dcc7436246f37b58 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 2 May 2012 11:41:58 +0800 Subject: [PATCH 0521/1799] macvtap: zerocopy: put page when fail to get all requested user pages commit 02ce04bb3d28c3333231f43bca677228dbc686fe upstream. When get_user_pages_fast() fails to get all requested pages, we could not use kfree_skb() to free it as it has not been put in the skb fragments. So we need to call put_page() instead. Signed-off-by: Jason Wang Signed-off-by: Michael S. Tsirkin Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/net/macvtap.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index cf096e0693e2..7cd750f4c6a0 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -533,9 +533,10 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, if (i + size > MAX_SKB_FRAGS) return -EMSGSIZE; num_pages = get_user_pages_fast(base, size, 0, &page[i]); - if (num_pages != size) - /* put_page is in skb free */ - return -EFAULT; + if (num_pages != size) { + for (i = 0; i < num_pages; i++) + put_page(page[i]); + } truesize = size * PAGE_SIZE; skb->data_len += len; skb->len += len; -- GitLab From 2b3c7134014a200279e7ed31716e528cd009dfb0 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 2 May 2012 11:42:06 +0800 Subject: [PATCH 0522/1799] macvtap: zerocopy: set SKBTX_DEV_ZEROCOPY only when skb is built successfully commit 01d6657b388438def19c8baaea28e742b6ed32ec upstream. Current the SKBTX_DEV_ZEROCOPY is set unconditionally after zerocopy_sg_from_iovec(), this would lead NULL pointer when macvtap fails to build zerocopy skb because destructor_arg was not initialized. Solve this by set this flag after the skb were built successfully. Signed-off-by: Jason Wang Signed-off-by: Michael S. Tsirkin Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/net/macvtap.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 7cd750f4c6a0..b99c418d6b2b 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -716,10 +716,9 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, if (!skb) goto err; - if (zerocopy) { + if (zerocopy) err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count); - skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; - } else + else err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, len); if (err) @@ -738,8 +737,10 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, rcu_read_lock_bh(); vlan = rcu_dereference_bh(q->vlan); /* copy skb_ubuf_info for callback when skb has no error */ - if (zerocopy) + if (zerocopy) { skb_shinfo(skb)->destructor_arg = m->msg_control; + skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; + } if (vlan) macvlan_start_xmit(skb, vlan->dev); else -- GitLab From ef3914b1b84739c721bcbecd0e519509ccde388c Mon Sep 17 00:00:00 2001 From: Manoj Iyer Date: Tue, 10 Jul 2012 14:07:38 -0500 Subject: [PATCH 0523/1799] Bluetooth: btusb: Add vendor specific ID (0a5c:21f4) BCM20702A0 commit 61c964ba1748e984cb232b431582815899bf10fe upstream. Patch adds support for BCM20702A0 device id (0a5c:21f4). usb-devices after patch was applied: T: Bus=03 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0a5c ProdID=21f4 Rev=01.12 S: Manufacturer=Broadcom Corp S: Product=BCM20702A0 S: SerialNumber=E4D53DF154D6 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=ff(vend.) 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=01 Driver=(none) usb-devices before patch was applied: T: Bus=03 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0a5c ProdID=21f4 Rev=01.12 S: Manufacturer=Broadcom Corp S: Product=BCM20702A0 S: SerialNumber=E4D53DF154D6 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=ff(vend.) 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: Manoj Iyer Tested-by: Chris Gagnon Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 9217121362e1..daa7cf389073 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -106,6 +106,7 @@ static struct usb_device_id btusb_table[] = { { USB_DEVICE(0x0a5c, 0x21e6) }, { USB_DEVICE(0x0a5c, 0x21e8) }, { USB_DEVICE(0x0a5c, 0x21f3) }, + { USB_DEVICE(0x0a5c, 0x21f4) }, { USB_DEVICE(0x413c, 0x8197) }, /* Foxconn - Hon Hai */ -- GitLab From 004251b52ce7f5079a70220b30bd99c5010f2c6e Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Mon, 6 Aug 2012 15:36:49 -0300 Subject: [PATCH 0524/1799] Bluetooth: Use USB_VENDOR_AND_INTERFACE() for Broadcom devices commit 92c385f46b30f4954e9dd2d2005c12d233b479ea upstream. Many Broadcom devices has a vendor specific devices class, with this rule we match all existent and future controllers with this behavior. We also remove old rules to that matches product id for Broadcom devices. Tested-by: John Hommel Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- drivers/bluetooth/btusb.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index daa7cf389073..1cb0a30ab5bf 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -102,16 +102,14 @@ static struct usb_device_id btusb_table[] = { /* Broadcom BCM20702A0 */ { USB_DEVICE(0x0489, 0xe042) }, - { USB_DEVICE(0x0a5c, 0x21e3) }, - { USB_DEVICE(0x0a5c, 0x21e6) }, - { USB_DEVICE(0x0a5c, 0x21e8) }, - { USB_DEVICE(0x0a5c, 0x21f3) }, - { USB_DEVICE(0x0a5c, 0x21f4) }, { USB_DEVICE(0x413c, 0x8197) }, /* Foxconn - Hon Hai */ { USB_DEVICE(0x0489, 0xe033) }, + /*Broadcom devices with vendor specific id */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, + { } /* Terminating entry */ }; -- GitLab From 403c9ebee757d7ec82e3e06e456ae2445f0b9f40 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 25 Aug 2012 19:28:06 +0200 Subject: [PATCH 0525/1799] Bluetooth: Add support for Apple vendor-specific devices commit 1fa6535faf055cd71311ab887e94fc234f04ee18 upstream. As pointed out by Gustavo and Marcel, all Apple-specific Broadcom devices seen so far have the same interface class, subclass and protocol numbers. This patch adds an entry which matches all of them, using the new USB_VENDOR_AND_INTERFACE_INFO() macro. In particular, this patch adds support for the MacBook Pro Retina (05ac:8286), which is not in the present list. Signed-off-by: Henrik Rydberg Tested-by: Shea Levy Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan 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 1cb0a30ab5bf..29d31ff7331d 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -60,6 +60,9 @@ static struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, + /* Apple-specific (Broadcom) devices */ + { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) }, + /* Broadcom SoftSailing reporting vendor specific */ { USB_DEVICE(0x0a5c, 0x21e1) }, -- GitLab From 27d50469825fd267f44e13fb0627b011c0da6abd Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Wed, 1 Aug 2012 20:34:15 -0300 Subject: [PATCH 0526/1799] Bluetooth: Fix use-after-free bug in SMP commit 61a0cfb008f57ecf7eb28ee762952fb42dc15d15 upstream. If SMP fails, we should always cancel security_timer delayed work. Otherwise, security_timer function may run after l2cap_conn object has been freed. This patch fixes the following warning reported by ODEBUG: WARNING: at lib/debugobjects.c:261 debug_print_object+0x7c/0x8d() Hardware name: Bochs ODEBUG: free active (active state 0) object type: timer_list hint: delayed_work_timer_fn+0x0/0x27 Modules linked in: btusb bluetooth Pid: 440, comm: kworker/u:2 Not tainted 3.5.0-rc1+ #4 Call Trace: [] ? free_obj_work+0x4a/0x7f [] warn_slowpath_common+0x7e/0x97 [] warn_slowpath_fmt+0x41/0x43 [] debug_print_object+0x7c/0x8d [] ? __queue_work+0x241/0x241 [] debug_check_no_obj_freed+0x92/0x159 [] slab_free_hook+0x6f/0x77 [] ? l2cap_conn_del+0x148/0x157 [bluetooth] [] kfree+0x59/0xac [] l2cap_conn_del+0x148/0x157 [bluetooth] [] l2cap_recv_frame+0xa77/0xfa4 [bluetooth] [] ? trace_hardirqs_on_caller+0x112/0x1ad [] l2cap_recv_acldata+0xe2/0x264 [bluetooth] [] hci_rx_work+0x235/0x33c [bluetooth] [] ? process_one_work+0x126/0x2fe [] process_one_work+0x185/0x2fe [] ? process_one_work+0x126/0x2fe [] ? lock_acquired+0x1b5/0x1cf [] ? le_scan_work+0x11d/0x11d [bluetooth] [] ? spin_lock_irq+0x9/0xb [] worker_thread+0xcf/0x175 [] ? rescuer_thread+0x175/0x175 [] kthread+0x95/0x9d [] kernel_threadi_helper+0x4/0x10 [] ? retint_restore_args+0x13/0x13 [] ? flush_kthread_worker+0xdb/0xdb [] ? gs_change+0x13/0x13 This bug can be reproduced using hctool lecc or l2test tools and bluetoothd not running. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/smp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index deb119875fd9..651272238335 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -266,10 +266,10 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type, hcon->dst_type, reason); - if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { - cancel_delayed_work_sync(&conn->security_timer); + cancel_delayed_work_sync(&conn->security_timer); + + if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) smp_chan_destroy(conn); - } } #define JUST_WORKS 0x00 -- GitLab From 0fcc0805df9cf7483e927cf6a4dc94938318c06a Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Thu, 23 Aug 2012 21:32:43 -0300 Subject: [PATCH 0527/1799] Bluetooth: Change signature of smp_conn_security() commit cc110922da7e902b62d18641a370fec01a9fa794 upstream. To make it clear that it may be called from contexts that may not have any knowledge of L2CAP, we change the connection parameter, to receive a hci_conn. This also makes it clear that it is checking the security of the link. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- include/net/bluetooth/smp.h | 2 +- net/bluetooth/l2cap_core.c | 11 ++++++----- net/bluetooth/l2cap_sock.c | 2 +- net/bluetooth/smp.c | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h index 7b3acdd29134..1bf9bec8e4fe 100644 --- a/include/net/bluetooth/smp.h +++ b/include/net/bluetooth/smp.h @@ -136,7 +136,7 @@ struct smp_chan { }; /* SMP Commands */ -int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level); +int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb); int smp_distribute_keys(struct l2cap_conn *conn, __u8 force); int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9a86759a7e62..627c35445a13 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -937,14 +937,15 @@ static void l2cap_chan_ready(struct l2cap_chan *chan) static void l2cap_conn_ready(struct l2cap_conn *conn) { struct l2cap_chan *chan; + struct hci_conn *hcon = conn->hcon; BT_DBG("conn %p", conn); - if (!conn->hcon->out && conn->hcon->type == LE_LINK) + if (!hcon->out && hcon->type == LE_LINK) l2cap_le_conn_ready(conn); - if (conn->hcon->out && conn->hcon->type == LE_LINK) - smp_conn_security(conn, conn->hcon->pending_sec_level); + if (hcon->out && hcon->type == LE_LINK) + smp_conn_security(hcon, hcon->pending_sec_level); mutex_lock(&conn->chan_lock); @@ -952,8 +953,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) l2cap_chan_lock(chan); - if (conn->hcon->type == LE_LINK) { - if (smp_conn_security(conn, chan->sec_level)) + if (hcon->type == LE_LINK) { + if (smp_conn_security(hcon, chan->sec_level)) l2cap_chan_ready(chan); } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 615b26e0650f..4a26348444bd 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -588,7 +588,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch break; } - if (smp_conn_security(conn, sec.level)) + if (smp_conn_security(conn->hcon, sec.level)) break; sk->sk_state = BT_CONFIG; chan->state = BT_CONFIG; diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 651272238335..1f6cb1f1cd2d 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -753,9 +753,9 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) return 0; } -int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) +int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) { - struct hci_conn *hcon = conn->hcon; + struct l2cap_conn *conn = hcon->l2cap_data; struct smp_chan *smp = conn->smp_chan; __u8 authreq; -- GitLab From c031edca540afb66764db24eed10eb149ac6c852 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Thu, 23 Aug 2012 21:32:44 -0300 Subject: [PATCH 0528/1799] Bluetooth: Fix sending a HCI Authorization Request over LE links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d8343f125710fb596f7a88cd756679f14f4e77b9 upstream. In the case that the link is already in the connected state and a Pairing request arrives from the mgmt interface, hci_conn_security() would be called but it was not considering LE links. Reported-by: João Paulo Rechi Vita Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hci_conn.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 5238b6b3ea6a..39b2baf6c1d5 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -42,6 +42,7 @@ #include #include +#include static void hci_le_connect(struct hci_conn *conn) { @@ -661,6 +662,9 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) { BT_DBG("conn %p", conn); + if (conn->type == LE_LINK) + return smp_conn_security(conn, sec_level); + /* For sdp we don't need the link key. */ if (sec_level == BT_SECURITY_SDP) return 1; -- GitLab From e6da94be68b025bdbbee3764428769a85367aa79 Mon Sep 17 00:00:00 2001 From: "Rustad, Mark D" Date: Wed, 18 Jul 2012 09:06:07 +0000 Subject: [PATCH 0529/1799] net: Statically initialize init_net.dev_base_head commit 734b65417b24d6eea3e3d7457e1f11493890ee1d upstream. This change eliminates an initialization-order hazard most recently seen when netprio_cgroup is built into the kernel. With thanks to Eric Dumazet for catching a bug. Signed-off-by: Mark Rustad Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 3 ++- net/core/net_namespace.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 40d5ab15befa..3fd9cae3ccb1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6303,7 +6303,8 @@ static struct hlist_head *netdev_create_hash(void) /* Initialize per network namespace state */ static int __net_init netdev_init(struct net *net) { - INIT_LIST_HEAD(&net->dev_base_head); + if (net != &init_net) + INIT_LIST_HEAD(&net->dev_base_head); net->dev_name_head = netdev_create_hash(); if (net->dev_name_head == NULL) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 31a5ae51a45c..dd00b71dd092 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -25,7 +25,9 @@ static DEFINE_MUTEX(net_mutex); LIST_HEAD(net_namespace_list); EXPORT_SYMBOL_GPL(net_namespace_list); -struct net init_net; +struct net init_net = { + .dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head), +}; EXPORT_SYMBOL(init_net); #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ -- GitLab From 0d19c30f548369606cce202224c86cf3ae1d20ea Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 18 Jul 2012 13:41:11 -0300 Subject: [PATCH 0530/1799] media: cx25821: Remove bad strcpy to read-only char* commit c854d8883fec59332f0662917f8c94dcfb1c405d upstream. The strcpy was being used to set the name of the board. This was both wrong and redundant, since the destination char* was read-only and the name is set statically at compile time. The type of the name field is changed to const char* to prevent future errors. Reported-by: Radek Masin Signed-off-by: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/cx25821/cx25821-core.c | 3 --- drivers/media/video/cx25821/cx25821.h | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/media/video/cx25821/cx25821-core.c b/drivers/media/video/cx25821/cx25821-core.c index 7930ca58349f..235bf7da6c04 100644 --- a/drivers/media/video/cx25821/cx25821-core.c +++ b/drivers/media/video/cx25821/cx25821-core.c @@ -912,9 +912,6 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) list_add_tail(&dev->devlist, &cx25821_devlist); mutex_unlock(&cx25821_devlist_mutex); - strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown"); - strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821"); - if (dev->pci->device != 0x8210) { pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n", __func__, dev->pci->device); diff --git a/drivers/media/video/cx25821/cx25821.h b/drivers/media/video/cx25821/cx25821.h index b9aa801b00a7..029f2934a6d8 100644 --- a/drivers/media/video/cx25821/cx25821.h +++ b/drivers/media/video/cx25821/cx25821.h @@ -187,7 +187,7 @@ enum port { }; struct cx25821_board { - char *name; + const char *name; enum port porta; enum port portb; enum port portc; -- GitLab From 11266a8e031a3782241760850f002c79ee2887e1 Mon Sep 17 00:00:00 2001 From: Li Zhong Date: Tue, 24 Jul 2012 15:02:49 -0700 Subject: [PATCH 0531/1799] Fix a dead loop in async_synchronize_full() [Fixed upstream by commits 2955b47d2c1983998a8c5915cb96884e67f7cb53 and a4683487f90bfe3049686fc5c566bdc1ad03ace6 from Dan Williams, but they are much more intrusive than this tiny fix, according to Andrew - gregkh] This patch tries to fix a dead loop in async_synchronize_full(), which could be seen when preemption is disabled on a single cpu machine. void async_synchronize_full(void) { do { async_synchronize_cookie(next_cookie); } while (!list_empty(&async_running) || ! list_empty(&async_pending)); } async_synchronize_cookie() calls async_synchronize_cookie_domain() with &async_running as the default domain to synchronize. However, there might be some works in the async_pending list from other domains. On a single cpu system, without preemption, there is no chance for the other works to finish, so async_synchronize_full() enters a dead loop. It seems async_synchronize_full() wants to synchronize all entries in all running lists(domains), so maybe we could just check the entry_count to know whether all works are finished. Currently, async_synchronize_cookie_domain() expects a non-NULL running list ( if NULL, there would be NULL pointer dereference ), so maybe a NULL pointer could be used as an indication for the functions to synchronize all works in all domains. Reported-by: Paul E. McKenney Signed-off-by: Li Zhong Tested-by: Paul E. McKenney Tested-by: Christian Kujau Cc: Andrew Morton Cc: Dan Williams Cc: Christian Kujau Cc: Andrew Morton Cc: Cong Wang Signed-off-by: Greg Kroah-Hartman --- kernel/async.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/kernel/async.c b/kernel/async.c index bd0c168a3bbe..32d8dc960263 100644 --- a/kernel/async.c +++ b/kernel/async.c @@ -86,6 +86,13 @@ static async_cookie_t __lowest_in_progress(struct list_head *running) { struct async_entry *entry; + if (!running) { /* just check the entry count */ + if (atomic_read(&entry_count)) + return 0; /* smaller than any cookie */ + else + return next_cookie; + } + if (!list_empty(running)) { entry = list_first_entry(running, struct async_entry, list); @@ -236,9 +243,7 @@ EXPORT_SYMBOL_GPL(async_schedule_domain); */ void async_synchronize_full(void) { - do { - async_synchronize_cookie(next_cookie); - } while (!list_empty(&async_running) || !list_empty(&async_pending)); + async_synchronize_cookie_domain(next_cookie, NULL); } EXPORT_SYMBOL_GPL(async_synchronize_full); @@ -258,7 +263,7 @@ EXPORT_SYMBOL_GPL(async_synchronize_full_domain); /** * async_synchronize_cookie_domain - synchronize asynchronous function calls within a certain domain with cookie checkpointing * @cookie: async_cookie_t to use as checkpoint - * @running: running list to synchronize on + * @running: running list to synchronize on, NULL indicates all lists * * This function waits until all asynchronous function calls for the * synchronization domain specified by the running list @list submitted -- GitLab From b2c1fcae0409fec6d96351fe2793a502870f4370 Mon Sep 17 00:00:00 2001 From: Weiping Pan Date: Mon, 23 Jul 2012 10:37:48 +0800 Subject: [PATCH 0532/1799] rds: set correct msg_namelen commit 06b6a1cf6e776426766298d055bb3991957d90a7 upstream. Jay Fenlason (fenlason@redhat.com) found a bug, that recvfrom() on an RDS socket can return the contents of random kernel memory to userspace if it was called with a address length larger than sizeof(struct sockaddr_in). rds_recvmsg() also fails to set the addr_len paramater properly before returning, but that's just a bug. There are also a number of cases wher recvfrom() can return an entirely bogus address. Anything in rds_recvmsg() that returns a non-negative value but does not go through the "sin = (struct sockaddr_in *)msg->msg_name;" code path at the end of the while(1) loop will return up to 128 bytes of kernel memory to userspace. And I write two test programs to reproduce this bug, you will see that in rds_server, fromAddr will be overwritten and the following sock_fd will be destroyed. Yes, it is the programmer's fault to set msg_namelen incorrectly, but it is better to make the kernel copy the real length of address to user space in such case. How to run the test programs ? I test them on 32bit x86 system, 3.5.0-rc7. 1 compile gcc -o rds_client rds_client.c gcc -o rds_server rds_server.c 2 run ./rds_server on one console 3 run ./rds_client on another console 4 you will see something like: server is waiting to receive data... old socket fd=3 server received data from client:data from client msg.msg_namelen=32 new socket fd=-1067277685 sendmsg() : Bad file descriptor /***************** rds_client.c ********************/ int main(void) { int sock_fd; struct sockaddr_in serverAddr; struct sockaddr_in toAddr; char recvBuffer[128] = "data from client"; struct msghdr msg; struct iovec iov; sock_fd = socket(AF_RDS, SOCK_SEQPACKET, 0); if (sock_fd < 0) { perror("create socket error\n"); exit(1); } memset(&serverAddr, 0, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); serverAddr.sin_port = htons(4001); if (bind(sock_fd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { perror("bind() error\n"); close(sock_fd); exit(1); } memset(&toAddr, 0, sizeof(toAddr)); toAddr.sin_family = AF_INET; toAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); toAddr.sin_port = htons(4000); msg.msg_name = &toAddr; msg.msg_namelen = sizeof(toAddr); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_iov->iov_base = recvBuffer; msg.msg_iov->iov_len = strlen(recvBuffer) + 1; msg.msg_control = 0; msg.msg_controllen = 0; msg.msg_flags = 0; if (sendmsg(sock_fd, &msg, 0) == -1) { perror("sendto() error\n"); close(sock_fd); exit(1); } printf("client send data:%s\n", recvBuffer); memset(recvBuffer, '\0', 128); msg.msg_name = &toAddr; msg.msg_namelen = sizeof(toAddr); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_iov->iov_base = recvBuffer; msg.msg_iov->iov_len = 128; msg.msg_control = 0; msg.msg_controllen = 0; msg.msg_flags = 0; if (recvmsg(sock_fd, &msg, 0) == -1) { perror("recvmsg() error\n"); close(sock_fd); exit(1); } printf("receive data from server:%s\n", recvBuffer); close(sock_fd); return 0; } /***************** rds_server.c ********************/ int main(void) { struct sockaddr_in fromAddr; int sock_fd; struct sockaddr_in serverAddr; unsigned int addrLen; char recvBuffer[128]; struct msghdr msg; struct iovec iov; sock_fd = socket(AF_RDS, SOCK_SEQPACKET, 0); if(sock_fd < 0) { perror("create socket error\n"); exit(0); } memset(&serverAddr, 0, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); serverAddr.sin_port = htons(4000); if (bind(sock_fd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { perror("bind error\n"); close(sock_fd); exit(1); } printf("server is waiting to receive data...\n"); msg.msg_name = &fromAddr; /* * I add 16 to sizeof(fromAddr), ie 32, * and pay attention to the definition of fromAddr, * recvmsg() will overwrite sock_fd, * since kernel will copy 32 bytes to userspace. * * If you just use sizeof(fromAddr), it works fine. * */ msg.msg_namelen = sizeof(fromAddr) + 16; /* msg.msg_namelen = sizeof(fromAddr); */ msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_iov->iov_base = recvBuffer; msg.msg_iov->iov_len = 128; msg.msg_control = 0; msg.msg_controllen = 0; msg.msg_flags = 0; while (1) { printf("old socket fd=%d\n", sock_fd); if (recvmsg(sock_fd, &msg, 0) == -1) { perror("recvmsg() error\n"); close(sock_fd); exit(1); } printf("server received data from client:%s\n", recvBuffer); printf("msg.msg_namelen=%d\n", msg.msg_namelen); printf("new socket fd=%d\n", sock_fd); strcat(recvBuffer, "--data from server"); if (sendmsg(sock_fd, &msg, 0) == -1) { perror("sendmsg()\n"); close(sock_fd); exit(1); } } close(sock_fd); return 0; } Signed-off-by: Weiping Pan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/rds/recv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/rds/recv.c b/net/rds/recv.c index 5c6e9f132026..9f0f17cf6bf9 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c @@ -410,6 +410,8 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, rdsdebug("size %zu flags 0x%x timeo %ld\n", size, msg_flags, timeo); + msg->msg_namelen = 0; + if (msg_flags & MSG_OOB) goto out; @@ -485,6 +487,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, sin->sin_port = inc->i_hdr.h_sport; sin->sin_addr.s_addr = inc->i_saddr; memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + msg->msg_namelen = sizeof(*sin); } break; } -- GitLab From 9dd30d194e2e83be4e14d7b4bdf21087f389318b Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Mon, 23 Jul 2012 12:22:37 +0800 Subject: [PATCH 0533/1799] libata: Prevent interface errors with Seagate FreeAgent GoFlex commit c531077f40abc9f2129c4c83a30b3f8d6ce1c0e7 upstream. When using my Seagate FreeAgent GoFlex eSATAp external disk enclosure, interface errors are always seen until 1.5Gbps is negotiated [1]. This occurs using any disk in the enclosure, and when the disk is connected directly with a generic passive eSATAp cable, we see stable 3Gbps operation as expected. Blacklist 3Gbps mode to avoid dataloss and the ~30s delay bus reset and renegotiation incurs. Signed-off-by: Daniel J Blueman Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index d31ee557b395..cf4837f3ded7 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4125,6 +4125,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Devices which aren't very happy with higher link speeds */ { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, }, + { "Seagate FreeAgent GoFlex", NULL, ATA_HORKAGE_1_5_GBPS, }, /* * Devices which choke on SETXFER. Applies only if both the -- GitLab From 6418cc471b5d8a64ce22d2aa827fcb275e61449c Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Wed, 20 Jun 2012 12:09:18 +0000 Subject: [PATCH 0534/1799] r8169: RxConfig hack for the 8168evl. commit eb2dc35d99028b698cdedba4f5522bc43e576bd2 upstream. The 8168evl (RTL_GIGA_MAC_VER_34) based Gigabyte GA-990FXA motherboards are very prone to NETDEV watchdog problems without this change. See https://bugzilla.kernel.org/show_bug.cgi?id=42899 for instance. I don't know why it *works*. It's depressingly effective though. For the record: - the problem may go along IOMMU (AMD-Vi) errors but it really looks like a red herring. - the patch sets the RX_MULTI_EN bit. If the 8168c doc is any guide, the chipset now fetches several Rx descriptors at a time. - long ago the driver ignored the RX_MULTI_EN bit. e542a2269f232d61270ceddd42b73a4348dee2bb changed the RxConfig settings. Whatever the problem it's now labeled a regression. - Realtek's own driver can identify two different 8168evl devices (CFG_METHOD_16 and CFG_METHOD_17) where the r8169 driver only sees one. It sucks. Signed-off-by: Francois Romieu Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index a73bbe7fb63a..5fb74c4298fa 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -3737,6 +3737,7 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_22: case RTL_GIGA_MAC_VER_23: case RTL_GIGA_MAC_VER_24: + case RTL_GIGA_MAC_VER_34: RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST); break; default: -- GitLab From e194fab8d7ebe95db5609f1cb6794c2afcc3118f Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 22 Jun 2012 13:36:05 +0200 Subject: [PATCH 0535/1799] sched: Fix race in task_group() commit 8323f26ce3425460769605a6aece7a174edaa7d1 upstream. Stefan reported a crash on a kernel before a3e5d1091c1 ("sched: Don't call task_group() too many times in set_task_rq()"), he found the reason to be that the multiple task_group() invocations in set_task_rq() returned different values. Looking at all that I found a lack of serialization and plain wrong comments. The below tries to fix it using an extra pointer which is updated under the appropriate scheduler locks. Its not pretty, but I can't really see another way given how all the cgroup stuff works. Reported-and-tested-by: Stefan Bader Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1340364965.18025.71.camel@twins Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- include/linux/init_task.h | 12 +++++++++++- include/linux/sched.h | 5 ++++- kernel/sched/core.c | 9 ++++++++- kernel/sched/sched.h | 23 ++++++++++------------- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/include/linux/init_task.h b/include/linux/init_task.h index e4baff5f7ff4..e7bafa432aa3 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -123,8 +123,17 @@ extern struct group_info init_groups; extern struct cred init_cred; +extern struct task_group root_task_group; + +#ifdef CONFIG_CGROUP_SCHED +# define INIT_CGROUP_SCHED(tsk) \ + .sched_task_group = &root_task_group, +#else +# define INIT_CGROUP_SCHED(tsk) +#endif + #ifdef CONFIG_PERF_EVENTS -# define INIT_PERF_EVENTS(tsk) \ +# define INIT_PERF_EVENTS(tsk) \ .perf_event_mutex = \ __MUTEX_INITIALIZER(tsk.perf_event_mutex), \ .perf_event_list = LIST_HEAD_INIT(tsk.perf_event_list), @@ -161,6 +170,7 @@ extern struct cred init_cred; }, \ .tasks = LIST_HEAD_INIT(tsk.tasks), \ INIT_PUSHABLE_TASKS(tsk) \ + INIT_CGROUP_SCHED(tsk) \ .ptraced = LIST_HEAD_INIT(tsk.ptraced), \ .ptrace_entry = LIST_HEAD_INIT(tsk.ptrace_entry), \ .real_parent = &tsk, \ diff --git a/include/linux/sched.h b/include/linux/sched.h index 7b06169d7241..48241aa976c8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1279,6 +1279,9 @@ struct task_struct { const struct sched_class *sched_class; struct sched_entity se; struct sched_rt_entity rt; +#ifdef CONFIG_CGROUP_SCHED + struct task_group *sched_task_group; +#endif #ifdef CONFIG_PREEMPT_NOTIFIERS /* list of struct preempt_notifier: */ @@ -2744,7 +2747,7 @@ extern int sched_group_set_rt_period(struct task_group *tg, extern long sched_group_rt_period(struct task_group *tg); extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk); #endif -#endif +#endif /* CONFIG_CGROUP_SCHED */ extern int task_can_switch_user(struct user_struct *up, struct task_struct *tsk); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index ef6a8f2eeffa..593087b2baf0 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1098,7 +1098,7 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu) * a task's CPU. ->pi_lock for waking tasks, rq->lock for runnable tasks. * * sched_move_task() holds both and thus holding either pins the cgroup, - * see set_task_rq(). + * see task_group(). * * Furthermore, all task_rq users should acquire both locks, see * task_rq_lock(). @@ -7427,6 +7427,7 @@ void sched_destroy_group(struct task_group *tg) */ void sched_move_task(struct task_struct *tsk) { + struct task_group *tg; int on_rq, running; unsigned long flags; struct rq *rq; @@ -7441,6 +7442,12 @@ void sched_move_task(struct task_struct *tsk) if (unlikely(running)) tsk->sched_class->put_prev_task(rq, tsk); + tg = container_of(task_subsys_state_check(tsk, cpu_cgroup_subsys_id, + lockdep_is_held(&tsk->sighand->siglock)), + struct task_group, css); + tg = autogroup_task_group(tsk, tg); + tsk->sched_task_group = tg; + #ifdef CONFIG_FAIR_GROUP_SCHED if (tsk->sched_class->task_move_group) tsk->sched_class->task_move_group(tsk, on_rq); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index d9637f4c43de..acfa7017eb0a 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -536,22 +536,19 @@ DECLARE_PER_CPU(int, sd_llc_id); /* * Return the group to which this tasks belongs. * - * We use task_subsys_state_check() and extend the RCU verification with - * pi->lock and rq->lock because cpu_cgroup_attach() holds those locks for each - * task it moves into the cgroup. Therefore by holding either of those locks, - * we pin the task to the current cgroup. + * We cannot use task_subsys_state() and friends because the cgroup + * subsystem changes that value before the cgroup_subsys::attach() method + * is called, therefore we cannot pin it and might observe the wrong value. + * + * The same is true for autogroup's p->signal->autogroup->tg, the autogroup + * core changes this before calling sched_move_task(). + * + * Instead we use a 'copy' which is updated from sched_move_task() while + * holding both task_struct::pi_lock and rq::lock. */ static inline struct task_group *task_group(struct task_struct *p) { - struct task_group *tg; - struct cgroup_subsys_state *css; - - css = task_subsys_state_check(p, cpu_cgroup_subsys_id, - lockdep_is_held(&p->pi_lock) || - lockdep_is_held(&task_rq(p)->lock)); - tg = container_of(css, struct task_group, css); - - return autogroup_task_group(p, tg); + return p->sched_task_group; } /* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */ -- GitLab From 391c314928c37b0c946061c0adddd5bd5730c8b7 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 11 Jul 2012 14:02:53 -0700 Subject: [PATCH 0536/1799] mm: sparse: fix usemap allocation above node descriptor section commit 99ab7b19440a72ebdf225f99b20f8ef40decee86 upstream. After commit f5bf18fa22f8 ("bootmem/sparsemem: remove limit constraint in alloc_bootmem_section"), usemap allocations may easily be placed outside the optimal section that holds the node descriptor, even if there is space available in that section. This results in unnecessary hotplug dependencies that need to have the node unplugged before the section holding the usemap. The reason is that the bootmem allocator doesn't guarantee a linear search starting from the passed allocation goal but may start out at a much higher address absent an upper limit. Fix this by trying the allocation with the limit at the section end, then retry without if that fails. This keeps the fix from f5bf18fa22f8 of not panicking if the allocation does not fit in the section, but still makes sure to try to stay within the section at first. [rewritten massively by Johannes to apply to 3.4] Signed-off-by: Yinghai Lu Signed-off-by: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/bootmem.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mm/bootmem.c b/mm/bootmem.c index 0131170c9d54..53cf62b186b6 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -766,13 +766,17 @@ void * __init alloc_bootmem_section(unsigned long size, unsigned long section_nr) { bootmem_data_t *bdata; - unsigned long pfn, goal; + unsigned long pfn, goal, limit; pfn = section_nr_to_pfn(section_nr); goal = pfn << PAGE_SHIFT; + limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT; bdata = &bootmem_node_data[early_pfn_to_nid(pfn)]; - return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, 0); + if (goal + size > limit) + limit = 0; + + return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit); } #endif -- GitLab From 504471eb5044e4a1dd10950d1a3efab39ba2083a Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 4 Jun 2012 13:05:24 -0300 Subject: [PATCH 0537/1799] media: lirc_sir: make device registration work commit 4b71ca6bce8fab3d08c61bf330e781f957934ae1 upstream. For one, the driver device pointer needs to be filled in, or the lirc core will refuse to load the driver. And we really need to wire up all the platform_device bits. This has been tested via the lirc sourceforge tree and verified to work, been sitting there for months, finally getting around to sending it. :\ Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab CC: Josh Boyer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/lirc/lirc_sir.c | 60 ++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/lirc/lirc_sir.c b/drivers/staging/media/lirc/lirc_sir.c index 945d9623550b..4afc3b419738 100644 --- a/drivers/staging/media/lirc/lirc_sir.c +++ b/drivers/staging/media/lirc/lirc_sir.c @@ -52,6 +52,7 @@ #include #include #include +#include #ifdef LIRC_ON_SA1100 #include #ifdef CONFIG_SA1100_COLLIE @@ -487,9 +488,11 @@ static struct lirc_driver driver = { .owner = THIS_MODULE, }; +static struct platform_device *lirc_sir_dev; static int init_chrdev(void) { + driver.dev = &lirc_sir_dev->dev; driver.minor = lirc_register_driver(&driver); if (driver.minor < 0) { printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); @@ -1215,20 +1218,71 @@ static int init_lirc_sir(void) return 0; } +static int __devinit lirc_sir_probe(struct platform_device *dev) +{ + return 0; +} + +static int __devexit lirc_sir_remove(struct platform_device *dev) +{ + return 0; +} + +static struct platform_driver lirc_sir_driver = { + .probe = lirc_sir_probe, + .remove = __devexit_p(lirc_sir_remove), + .driver = { + .name = "lirc_sir", + .owner = THIS_MODULE, + }, +}; static int __init lirc_sir_init(void) { int retval; + retval = platform_driver_register(&lirc_sir_driver); + if (retval) { + printk(KERN_ERR LIRC_DRIVER_NAME ": Platform driver register " + "failed!\n"); + return -ENODEV; + } + + lirc_sir_dev = platform_device_alloc("lirc_dev", 0); + if (!lirc_sir_dev) { + printk(KERN_ERR LIRC_DRIVER_NAME ": Platform device alloc " + "failed!\n"); + retval = -ENOMEM; + goto pdev_alloc_fail; + } + + retval = platform_device_add(lirc_sir_dev); + if (retval) { + printk(KERN_ERR LIRC_DRIVER_NAME ": Platform device add " + "failed!\n"); + retval = -ENODEV; + goto pdev_add_fail; + } + retval = init_chrdev(); if (retval < 0) - return retval; + goto fail; + retval = init_lirc_sir(); if (retval) { drop_chrdev(); - return retval; + goto fail; } + return 0; + +fail: + platform_device_del(lirc_sir_dev); +pdev_add_fail: + platform_device_put(lirc_sir_dev); +pdev_alloc_fail: + platform_driver_unregister(&lirc_sir_driver); + return retval; } static void __exit lirc_sir_exit(void) @@ -1236,6 +1290,8 @@ static void __exit lirc_sir_exit(void) drop_hardware(); drop_chrdev(); drop_port(); + platform_device_unregister(lirc_sir_dev); + platform_driver_unregister(&lirc_sir_driver); printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); } -- GitLab From 8e878154f5658ba93cf9bb2b491a930ec195de3d Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 11 Sep 2012 15:04:17 -0400 Subject: [PATCH 0538/1799] time: Improve sanity checking of timekeeping inputs commit 4e8b14526ca7fb046a81c94002c1c43b6fdf0e9b upstream. Unexpected behavior could occur if the time is set to a value large enough to overflow a 64bit ktime_t (which is something larger then the year 2262). Also unexpected behavior could occur if large negative offsets are injected via adjtimex. So this patch improves the sanity check timekeeping inputs by improving the timespec_valid() check, and then makes better use of timespec_valid() to make sure we don't set the time to an invalid negative value or one that overflows ktime_t. Note: This does not protect from setting the time close to overflowing ktime_t and then letting natural accumulation cause the overflow. Reported-by: CAI Qian Reported-by: Sasha Levin Signed-off-by: John Stultz Cc: Peter Zijlstra Cc: Prarit Bhargava Cc: Zhouping Liu Cc: Ingo Molnar Link: http://lkml.kernel.org/r/1344454580-17031-1-git-send-email-john.stultz@linaro.org Signed-off-by: Thomas Gleixner Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- include/linux/ktime.h | 7 ------- include/linux/time.h | 22 ++++++++++++++++++++-- kernel/time/timekeeping.c | 26 ++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/include/linux/ktime.h b/include/linux/ktime.h index 603bec2913b0..06177ba10a16 100644 --- a/include/linux/ktime.h +++ b/include/linux/ktime.h @@ -58,13 +58,6 @@ union ktime { typedef union ktime ktime_t; /* Kill this */ -#define KTIME_MAX ((s64)~((u64)1 << 63)) -#if (BITS_PER_LONG == 64) -# define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) -#else -# define KTIME_SEC_MAX LONG_MAX -#endif - /* * ktime_t definitions when using the 64-bit scalar representation: */ diff --git a/include/linux/time.h b/include/linux/time.h index 8da51299a7d5..ac3118640e5c 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -107,11 +107,29 @@ static inline struct timespec timespec_sub(struct timespec lhs, return ts_delta; } +#define KTIME_MAX ((s64)~((u64)1 << 63)) +#if (BITS_PER_LONG == 64) +# define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) +#else +# define KTIME_SEC_MAX LONG_MAX +#endif + /* * Returns true if the timespec is norm, false if denorm: */ -#define timespec_valid(ts) \ - (((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC)) +static inline bool timespec_valid(const struct timespec *ts) +{ + /* Dates before 1970 are bogus */ + if (ts->tv_sec < 0) + return false; + /* Can't have more nanoseconds then a second */ + if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) + return false; + /* Disallow values that could overflow ktime_t */ + if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX) + return false; + return true; +} extern void read_persistent_clock(struct timespec *ts); extern void read_boot_clock(struct timespec *ts); diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 7c50de83b6fd..dd31d0e96bcb 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -385,7 +385,7 @@ int do_settimeofday(const struct timespec *tv) struct timespec ts_delta; unsigned long flags; - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) + if (!timespec_valid(tv)) return -EINVAL; write_seqlock_irqsave(&timekeeper.lock, flags); @@ -420,6 +420,8 @@ EXPORT_SYMBOL(do_settimeofday); int timekeeping_inject_offset(struct timespec *ts) { unsigned long flags; + struct timespec tmp; + int ret = 0; if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) return -EINVAL; @@ -428,10 +430,17 @@ int timekeeping_inject_offset(struct timespec *ts) timekeeping_forward_now(); + tmp = timespec_add(timekeeper.xtime, *ts); + if (!timespec_valid(&tmp)) { + ret = -EINVAL; + goto error; + } + timekeeper.xtime = timespec_add(timekeeper.xtime, *ts); timekeeper.wall_to_monotonic = timespec_sub(timekeeper.wall_to_monotonic, *ts); +error: /* even if we error out, we forwarded the time, so call update */ timekeeping_update(true); write_sequnlock_irqrestore(&timekeeper.lock, flags); @@ -439,7 +448,7 @@ int timekeeping_inject_offset(struct timespec *ts) /* signal hrtimers about time change */ clock_was_set(); - return 0; + return ret; } EXPORT_SYMBOL(timekeeping_inject_offset); @@ -599,7 +608,20 @@ void __init timekeeping_init(void) struct timespec now, boot; read_persistent_clock(&now); + if (!timespec_valid(&now)) { + pr_warn("WARNING: Persistent clock returned invalid value!\n" + " Check your CMOS/BIOS settings.\n"); + now.tv_sec = 0; + now.tv_nsec = 0; + } + read_boot_clock(&boot); + if (!timespec_valid(&boot)) { + pr_warn("WARNING: Boot clock returned invalid value!\n" + " Check your CMOS/BIOS settings.\n"); + boot.tv_sec = 0; + boot.tv_nsec = 0; + } seqlock_init(&timekeeper.lock); -- GitLab From 80257cbe62ea0919153c43421746269ab68473bf Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 11 Sep 2012 15:04:18 -0400 Subject: [PATCH 0539/1799] time: Avoid making adjustments if we haven't accumulated anything commit bf2ac312195155511a0f79325515cbb61929898a upstream. If update_wall_time() is called and the current offset isn't large enough to accumulate, avoid re-calling timekeeping_adjust which may change the clock freq and can cause 1ns inconsistencies with CLOCK_REALTIME_COARSE/CLOCK_MONOTONIC_COARSE. Signed-off-by: John Stultz Cc: Prarit Bhargava Cc: Ingo Molnar Link: http://lkml.kernel.org/r/1345595449-34965-5-git-send-email-john.stultz@linaro.org Signed-off-by: Thomas Gleixner Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- kernel/time/timekeeping.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index dd31d0e96bcb..104d549f9df1 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1057,9 +1057,12 @@ static void update_wall_time(void) #else offset = (clock->read(clock) - clock->cycle_last) & clock->mask; #endif + /* Check if there's really nothing to do */ + if (offset < timekeeper.cycle_interval) + goto out; + timekeeper.xtime_nsec = (s64)timekeeper.xtime.tv_nsec << timekeeper.shift; - /* * With NO_HZ we may have to accumulate many cycle_intervals * (think "ticks") worth of time at once. To do this efficiently, -- GitLab From 9a227fcb842a03fce5b8a6da0da40f5601ec6908 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 11 Sep 2012 15:04:19 -0400 Subject: [PATCH 0540/1799] time: Move ktime_t overflow checking into timespec_valid_strict commit cee58483cf56e0ba355fdd97ff5e8925329aa936 upstream Andreas Bombe reported that the added ktime_t overflow checking added to timespec_valid in commit 4e8b14526ca7 ("time: Improve sanity checking of timekeeping inputs") was causing problems with X.org because it caused timeouts larger then KTIME_T to be invalid. Previously, these large timeouts would be clamped to KTIME_MAX and would never expire, which is valid. This patch splits the ktime_t overflow checking into a new timespec_valid_strict function, and converts the timekeeping codes internal checking to use this more strict function. Reported-and-tested-by: Andreas Bombe Cc: Zhouping Liu Cc: Ingo Molnar Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz Signed-off-by: Linus Torvalds Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- include/linux/time.h | 7 +++++++ kernel/time/timekeeping.c | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/linux/time.h b/include/linux/time.h index ac3118640e5c..03dce74e217c 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -125,6 +125,13 @@ static inline bool timespec_valid(const struct timespec *ts) /* Can't have more nanoseconds then a second */ if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) return false; + return true; +} + +static inline bool timespec_valid_strict(const struct timespec *ts) +{ + if (!timespec_valid(ts)) + return false; /* Disallow values that could overflow ktime_t */ if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX) return false; diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 104d549f9df1..12843e9f6d59 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -385,7 +385,7 @@ int do_settimeofday(const struct timespec *tv) struct timespec ts_delta; unsigned long flags; - if (!timespec_valid(tv)) + if (!timespec_valid_strict(tv)) return -EINVAL; write_seqlock_irqsave(&timekeeper.lock, flags); @@ -431,7 +431,7 @@ int timekeeping_inject_offset(struct timespec *ts) timekeeping_forward_now(); tmp = timespec_add(timekeeper.xtime, *ts); - if (!timespec_valid(&tmp)) { + if (!timespec_valid_strict(&tmp)) { ret = -EINVAL; goto error; } @@ -608,7 +608,7 @@ void __init timekeeping_init(void) struct timespec now, boot; read_persistent_clock(&now); - if (!timespec_valid(&now)) { + if (!timespec_valid_strict(&now)) { pr_warn("WARNING: Persistent clock returned invalid value!\n" " Check your CMOS/BIOS settings.\n"); now.tv_sec = 0; @@ -616,7 +616,7 @@ void __init timekeeping_init(void) } read_boot_clock(&boot); - if (!timespec_valid(&boot)) { + if (!timespec_valid_strict(&boot)) { pr_warn("WARNING: Boot clock returned invalid value!\n" " Check your CMOS/BIOS settings.\n"); boot.tv_sec = 0; @@ -667,7 +667,7 @@ static void update_sleep_time(struct timespec t) */ static void __timekeeping_inject_sleeptime(struct timespec *delta) { - if (!timespec_valid(delta)) { + if (!timespec_valid_strict(delta)) { printk(KERN_WARNING "__timekeeping_inject_sleeptime: Invalid " "sleep delta value!\n"); return; -- GitLab From a31c99713bb3e130d34039a7a073a9d815af90a0 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 6 Jul 2012 23:27:57 -0300 Subject: [PATCH 0541/1799] media: Avoid sysfs oops when an rc_dev's raw device is absent commit 720bb6436ff30fccad05cf5bdf961ea5b1f5686d upstream. For some reason, when the lirc daemon learns that a usb remote control has been unplugged, it wants to read the sysfs attributes of the disappearing device. This is useful for uncovering transient inconsistencies, but less so for keeping the system running when such inconsistencies exist. Under some circumstances (like every time I unplug my dvb stick from my laptop), lirc catches an rc_dev whose raw event handler has been removed (presumably by ir_raw_event_unregister), and proceeds to interrogate the raw protocols supported by the NULL pointer. This patch avoids the NULL dereference, and ignores the issue of how this state of affairs came about in the first place. Version 2 incorporates changes recommended by Mauro Carvalho Chehab (-ENODEV instead of -EINVAL, and a signed-off-by). Signed-off-by: Douglas Bagnall Signed-off-by: Mauro Carvalho Chehab Cc: Herton Ronaldo Krzesinski Signed-off-by: Greg Kroah-Hartman --- drivers/media/rc/rc-main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 6e16b09c24a9..cabc19c10515 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -775,10 +775,11 @@ static ssize_t show_protocols(struct device *device, if (dev->driver_type == RC_DRIVER_SCANCODE) { enabled = dev->rc_map.rc_type; allowed = dev->allowed_protos; - } else { + } else if (dev->raw) { enabled = dev->raw->enabled_protocols; allowed = ir_raw_get_allowed_protocols(); - } + } else + return -ENODEV; IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", (long long)allowed, -- GitLab From 17361b3edc6e84fbbc996ad9bb350be41739f457 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 2 Jul 2012 18:51:38 +0100 Subject: [PATCH 0542/1799] pch_uart: Fix missing break for 16 byte fifo commit 9bc03743fff0770dc5a5324ba92e67cc377f16ca upstream. Otherwise we fall back to the wrong value. Reported-by: Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=44091 Signed-off-by: Alan Cox Signed-off-by: Tomoya MORINAGA Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index c2816f494807..44cf438356e0 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1255,6 +1255,7 @@ static int pch_uart_startup(struct uart_port *port) break; case 16: fifo_size = PCH_UART_HAL_FIFO16; + break; case 1: default: fifo_size = PCH_UART_HAL_FIFO_DIS; -- GitLab From 439ec7b975d17a097414671ef2aaa6037448c3f6 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Fri, 6 Jul 2012 17:19:42 +0900 Subject: [PATCH 0543/1799] pch_uart: Fix rx error interrupt setting issue commit 9539dfb7ac1c84522fe1f79bb7dac2990f3de44a upstream. Rx Error interrupt(E.G. parity error) is not enabled. So, when parity error occurs, error interrupt is not occurred. As a result, the received data is not dropped. This patch adds enable/disable rx error interrupt code. Signed-off-by: Tomoya MORINAGA Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 44cf438356e0..20001b749b26 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -754,7 +754,8 @@ static void pch_dma_rx_complete(void *arg) tty_flip_buffer_push(tty); tty_kref_put(tty); async_tx_ack(priv->desc_rx); - pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT); + pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT | + PCH_UART_HAL_RX_ERR_INT); } static void pch_dma_tx_complete(void *arg) @@ -809,7 +810,8 @@ static int handle_rx_to(struct eg20t_port *priv) int rx_size; int ret; if (!priv->start_rx) { - pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT); + pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT | + PCH_UART_HAL_RX_ERR_INT); return 0; } buf = &priv->rxbuf; @@ -1071,11 +1073,13 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) case PCH_UART_IID_RDR: /* Received Data Ready */ if (priv->use_dma) { pch_uart_hal_disable_interrupt(priv, - PCH_UART_HAL_RX_INT); + PCH_UART_HAL_RX_INT | + PCH_UART_HAL_RX_ERR_INT); ret = dma_handle_rx(priv); if (!ret) pch_uart_hal_enable_interrupt(priv, - PCH_UART_HAL_RX_INT); + PCH_UART_HAL_RX_INT | + PCH_UART_HAL_RX_ERR_INT); } else { ret = handle_rx(priv); } @@ -1199,7 +1203,8 @@ static void pch_uart_stop_rx(struct uart_port *port) struct eg20t_port *priv; priv = container_of(port, struct eg20t_port, port); priv->start_rx = 0; - pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT); + pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT | + PCH_UART_HAL_RX_ERR_INT); priv->int_dis_flag = 1; } @@ -1293,7 +1298,8 @@ static int pch_uart_startup(struct uart_port *port) pch_request_dma(port); priv->start_rx = 1; - pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT); + pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT | + PCH_UART_HAL_RX_ERR_INT); uart_update_timeout(port, CS8, default_baud); return 0; -- GitLab From 3dcb53637949c288a1ff2a06ee3c0a212ace6ef1 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Fri, 6 Jul 2012 17:19:43 +0900 Subject: [PATCH 0544/1799] pch_uart: Fix parity setting issue commit 38bd2a1ac736901d1cf4971c78ef952ba92ef78b upstream. Parity Setting value is reverse. E.G. In case of setting ODD parity, EVEN value is set. This patch inverts "if" condition. Signed-off-by: Tomoya MORINAGA Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 20001b749b26..103a25f77d14 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1357,7 +1357,7 @@ static void pch_uart_set_termios(struct uart_port *port, stb = PCH_UART_HAL_STB1; if (termios->c_cflag & PARENB) { - if (!(termios->c_cflag & PARODD)) + if (termios->c_cflag & PARODD) parity = PCH_UART_HAL_PARITY_ODD; else parity = PCH_UART_HAL_PARITY_EVEN; -- GitLab From e85f60c9fc3d5ecc66e6598c0e487aa5c4b7feeb Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 13 Jul 2012 14:28:42 -0500 Subject: [PATCH 0545/1799] powerpc/85xx: p1022ds: disable the NAND flash node if video is enabled commit 6269f2584a359766f53005c676daff8aee60cbed upstream. The Freescale P1022 has a unique pin muxing "feature" where the DIU video controller's video signals are muxed with 24 of the local bus address signals. When the DIU is enabled, the bulk of the local bus is disabled, preventing access to memory-mapped devices like NAND flash and the pixis FPGA. Therefore, if the DIU is going to be enabled, then memory-mapped devices on the localbus, like NAND flash, need to be disabled. This patch is similar to "powerpc/85xx: p1022ds: disable the NOR flash node if video is enabled", except that it disables the NAND flash node instead. This PIXIS node needs to remain enabled because it is used by platform code to switch into indirect mode. Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/85xx/p1022_ds.c | 38 ++++++++++++++++++++------ 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index 978330ccdde6..f867ae42fae5 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -435,6 +435,8 @@ static void __init disable_one_node(struct device_node *np, struct property *new prom_update_property(np, new, old); else prom_add_property(np, new); + + pr_info("p1022ds: disabling %s node\n", np->full_name); } /* TRUE if there is a "video=fslfb" command-line parameter. */ @@ -499,28 +501,46 @@ static void __init p1022_ds_setup_arch(void) diu_ops.valid_monitor_port = p1022ds_valid_monitor_port; /* - * Disable the NOR flash node if there is video=fslfb... command-line - * parameter. When the DIU is active, NOR flash is unavailable, so we - * have to disable the node before the MTD driver loads. + * Disable the NOR and NAND flash nodes if there is video=fslfb... + * command-line parameter. When the DIU is active, the localbus is + * unavailable, so we have to disable these nodes before the MTD + * driver loads. */ if (fslfb) { struct device_node *np = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc"); if (np) { - np = of_find_compatible_node(np, NULL, "cfi-flash"); - if (np) { + struct device_node *np2; + + of_node_get(np); + np2 = of_find_compatible_node(np, NULL, "cfi-flash"); + if (np2) { static struct property nor_status = { .name = "status", .value = "disabled", .length = sizeof("disabled"), }; - pr_info("p1022ds: disabling %s node", - np->full_name); - disable_one_node(np, &nor_status); - of_node_put(np); + disable_one_node(np2, &nor_status); + of_node_put(np2); + } + + of_node_get(np); + np2 = of_find_compatible_node(np, NULL, + "fsl,elbc-fcm-nand"); + if (np2) { + static struct property nand_status = { + .name = "status", + .value = "disabled", + .length = sizeof("disabled"), + }; + + disable_one_node(np2, &nand_status); + of_node_put(np2); } + + of_node_put(np); } } -- GitLab From cb2184097168d9ee97126d8284a501759f6d1367 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 23 Jul 2012 15:43:32 -0500 Subject: [PATCH 0546/1799] powerpc/85xx: p1022ds: fix DIU/LBC switching with NAND enabled commit 896c01cb4bb3cfc2c0ea9873fa7a9f8bd0a7c8d8 upstream. In order for indirect mode on the PIXIS to work properly, both chip selects need to be set to GPCM mode, otherwise writes to the chip select base addresses will not actually post to the local bus -- they'll go to the NAND controller instead. Therefore, we need to set BR0 and BR1 to GPCM mode before switching to indirect mode. Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/85xx/p1022_ds.c | 64 +++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index f867ae42fae5..f80887f40f02 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -208,6 +208,7 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) u8 __iomem *lbc_lcs0_ba = NULL; u8 __iomem *lbc_lcs1_ba = NULL; phys_addr_t cs0_addr, cs1_addr; + u32 br0, or0, br1, or1; const __be32 *iprop; unsigned int num_laws; u8 b; @@ -256,11 +257,70 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) } num_laws = be32_to_cpup(iprop); - cs0_addr = lbc_br_to_phys(ecm, num_laws, in_be32(&lbc->bank[0].br)); - cs1_addr = lbc_br_to_phys(ecm, num_laws, in_be32(&lbc->bank[1].br)); + /* + * Indirect mode requires both BR0 and BR1 to be set to "GPCM", + * otherwise writes to these addresses won't actually appear on the + * local bus, and so the PIXIS won't see them. + * + * In FCM mode, writes go to the NAND controller, which does not pass + * them to the localbus directly. So we force BR0 and BR1 into GPCM + * mode, since we don't care about what's behind the localbus any + * more. + */ + br0 = in_be32(&lbc->bank[0].br); + br1 = in_be32(&lbc->bank[1].br); + or0 = in_be32(&lbc->bank[0].or); + or1 = in_be32(&lbc->bank[1].or); + + /* Make sure CS0 and CS1 are programmed */ + if (!(br0 & BR_V) || !(br1 & BR_V)) { + pr_err("p1022ds: CS0 and/or CS1 is not programmed\n"); + goto exit; + } + + /* + * Use the existing BRx/ORx values if it's already GPCM. Otherwise, + * force the values to simple 32KB GPCM windows with the most + * conservative timing. + */ + if ((br0 & BR_MSEL) != BR_MS_GPCM) { + br0 = (br0 & BR_BA) | BR_V; + or0 = 0xFFFF8000 | 0xFF7; + out_be32(&lbc->bank[0].br, br0); + out_be32(&lbc->bank[0].or, or0); + } + if ((br1 & BR_MSEL) != BR_MS_GPCM) { + br1 = (br1 & BR_BA) | BR_V; + or1 = 0xFFFF8000 | 0xFF7; + out_be32(&lbc->bank[1].br, br1); + out_be32(&lbc->bank[1].or, or1); + } + + cs0_addr = lbc_br_to_phys(ecm, num_laws, br0); + if (!cs0_addr) { + pr_err("p1022ds: could not determine physical address for CS0" + " (BR0=%08x)\n", br0); + goto exit; + } + cs1_addr = lbc_br_to_phys(ecm, num_laws, br1); + if (!cs0_addr) { + pr_err("p1022ds: could not determine physical address for CS1" + " (BR1=%08x)\n", br1); + goto exit; + } lbc_lcs0_ba = ioremap(cs0_addr, 1); + if (!lbc_lcs0_ba) { + pr_err("p1022ds: could not ioremap CS0 address %llx\n", + (unsigned long long)cs0_addr); + goto exit; + } lbc_lcs1_ba = ioremap(cs1_addr, 1); + if (!lbc_lcs1_ba) { + pr_err("p1022ds: could not ioremap CS1 address %llx\n", + (unsigned long long)cs1_addr); + goto exit; + } /* Make sure we're in indirect mode first. */ if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) != -- GitLab From 61df44523230af4f6aaeb4b0aa8131c74cc47ec3 Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Tue, 19 Jun 2012 14:00:18 -0700 Subject: [PATCH 0547/1799] pch_uart: Add eg20t_port lock field, avoid recursive spinlocks commit 2588aba002d14e938c2f56d299ecf3e7ce1302a5 upstream. pch_uart_interrupt() takes priv->port.lock which leads to two recursive spinlock calls if low_latency==1 or CONFIG_PREEMPT_RT_FULL=y (one otherwise): pch_uart_interrupt spin_lock_irqsave(priv->port.lock, flags) case PCH_UART_IID_RDR_TO (data ready) handle_rx_to push_rx tty_port_tty_get spin_lock_irqsave(&port->lock, flags) <--- already hold this lock ... tty_flip_buffer_push ... flush_to_ldisc spin_lock_irqsave(&tty->buf.lock) spin_lock_irqsave(&tty->buf.lock) disc->ops->receive_buf(tty, char_buf) n_tty_receive_buf tty->ops->flush_chars() uart_flush_chars uart_start spin_lock_irqsave(&port->lock) <--- already hold this lock Avoid this by using a dedicated lock to protect the eg20t_port structure and IO access to its membase. This is more consistent with the 8250 driver. Ensure priv->lock is always take prior to priv->port.lock when taken at the same time. V2: Remove inadvertent whitespace change. V3: Account for oops_in_progress for the private lock in pch_console_write(). Note: Like the 8250 driver, if a printk is introduced anywhere inside the pch_console_write() critical section, the kernel will hang on a recursive spinlock on the private lock. The oops case is handled by using a trylock in the oops_in_progress case. Signed-off-by: Darren Hart CC: Tomoya MORINAGA CC: Feng Tang CC: Alexander Stein Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 38 ++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 103a25f77d14..7d4751474da1 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -252,6 +252,9 @@ struct eg20t_port { dma_addr_t rx_buf_dma; struct dentry *debugfs; + + /* protect the eg20t_port private structure and io access to membase */ + spinlock_t lock; }; /** @@ -1058,7 +1061,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) unsigned int iid; unsigned long flags; - spin_lock_irqsave(&priv->port.lock, flags); + spin_lock_irqsave(&priv->lock, flags); handled = 0; while ((iid = pch_uart_hal_get_iid(priv)) > 1) { switch (iid) { @@ -1111,7 +1114,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) priv->int_dis_flag = 0; } - spin_unlock_irqrestore(&priv->port.lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_RETVAL(handled); } @@ -1223,9 +1226,9 @@ static void pch_uart_break_ctl(struct uart_port *port, int ctl) unsigned long flags; priv = container_of(port, struct eg20t_port, port); - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&priv->lock, flags); pch_uart_hal_set_break(priv, ctl); - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } /* Grab any interrupt resources and initialise any low level driver state. */ @@ -1375,7 +1378,8 @@ static void pch_uart_set_termios(struct uart_port *port, baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&priv->lock, flags); + spin_lock(&port->lock); uart_update_timeout(port, termios->c_cflag, baud); rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb); @@ -1388,7 +1392,8 @@ static void pch_uart_set_termios(struct uart_port *port, tty_termios_encode_baud_rate(termios, baud, baud); out: - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock(&port->lock); + spin_unlock_irqrestore(&priv->lock, flags); } static const char *pch_uart_type(struct uart_port *port) @@ -1538,8 +1543,9 @@ pch_console_write(struct console *co, const char *s, unsigned int count) { struct eg20t_port *priv; unsigned long flags; + int priv_locked = 1; + int port_locked = 1; u8 ier; - int locked = 1; priv = pch_uart_ports[co->index]; @@ -1547,12 +1553,16 @@ pch_console_write(struct console *co, const char *s, unsigned int count) local_irq_save(flags); if (priv->port.sysrq) { - /* serial8250_handle_port() already took the lock */ - locked = 0; + spin_lock(&priv->lock); + /* serial8250_handle_port() already took the port lock */ + port_locked = 0; } else if (oops_in_progress) { - locked = spin_trylock(&priv->port.lock); - } else + priv_locked = spin_trylock(&priv->lock); + port_locked = spin_trylock(&priv->port.lock); + } else { + spin_lock(&priv->lock); spin_lock(&priv->port.lock); + } /* * First save the IER then disable the interrupts @@ -1570,8 +1580,10 @@ pch_console_write(struct console *co, const char *s, unsigned int count) wait_for_xmitr(priv, BOTH_EMPTY); iowrite8(ier, priv->membase + UART_IER); - if (locked) + if (port_locked) spin_unlock(&priv->port.lock); + if (priv_locked) + spin_unlock(&priv->lock); local_irq_restore(flags); } @@ -1669,6 +1681,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, pci_enable_msi(pdev); pci_set_master(pdev); + spin_lock_init(&priv->lock); + iobase = pci_resource_start(pdev, 0); mapbase = pci_resource_start(pdev, 1); priv->mapbase = mapbase; -- GitLab From 11cbc507a8451655bd0445a0ca8f9018ce8d20a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sat, 19 May 2012 07:20:31 +0000 Subject: [PATCH 0548/1799] net: qmi_wwan: Add Vodafone/Huawei K5005 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 88c16dc3bb61a1c1e9d4c78f45cc2107bc8d5249 upstream. Tested-by: Thomas Schäfer Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/qmi_wwan.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index c2ae4266617d..4be2d7f91740 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -407,6 +407,14 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 8, /* NOTE: This is the *slave* interface of the CDC Union! */ .driver_info = (unsigned long)&qmi_wwan_info, }, + { /* Vodafone/Huawei K5005 (12d1:14c8) and similar modems */ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = HUAWEI_VENDOR_ID, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 56, /* NOTE: This is the *slave* interface of the CDC Union! */ + .driver_info = (unsigned long)&qmi_wwan_info, + }, { /* Huawei E392, E398 and possibly others in "Windows mode" * using a combined control and data interface without any CDC * functional descriptors -- GitLab From 4bf003851ca52d2b1cb6f96817f7fe335e1fd849 Mon Sep 17 00:00:00 2001 From: "Andrew Bird (Sphere Systems)" Date: Sat, 19 May 2012 22:28:37 +0000 Subject: [PATCH 0549/1799] USB: qmi_wwan: Add ZTE (Vodafone) K3765-Z MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 8965c98fdebedce077257241957b205515dd1a5f upstream. Add the ZTE (Vodafone) K3765-Z to the whitelist. This requires the previous patch to make the whitelist with forced interface 4 generic or the device fails to initialise. After applying this patch and loading the Option driver without usb-modeswitch's bind all interfaces trick, a wwan0 net interface and /dev/cdc-wdm0 device file were created. Using Bjorn Mork's perl connection script a connection was made to a mobile network using QMI and the network interface's IPv4 address was configured OK. Signed-off-by: Andrew Bird Acked-by: Bjørn Mork Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/qmi_wwan.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 4be2d7f91740..6e06fbb20b3f 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -480,6 +480,15 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_force_int4, }, + { /* ZTE (Vodafone) K3765-Z */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x2002, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int4, + }, { /* ZTE (Vodafone) K4505-Z */ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x19d2, -- GitLab From bf5ebae622cc4b0df483488ec8648831705f6465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 23 May 2012 23:19:32 +0000 Subject: [PATCH 0550/1799] net: qmi_wwan: Add Sierra Wireless device IDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 5e071b5d1aa6928f8d695c15f52a949d70b8d7fb upstream. Some additional Gobi3K IDs found in the BSD/GPL licensed out-of-tree GobiNet driver from Sierra Wireless. Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/qmi_wwan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 6e06fbb20b3f..739e56d305b8 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -548,6 +548,8 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ {QMI_GOBI_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ + {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ + {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ { } /* END */ }; MODULE_DEVICE_TABLE(usb, products); -- GitLab From e7f558cc5068b40428b048d8e6e338fef29fd5ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 5 Jul 2012 01:13:33 +0000 Subject: [PATCH 0551/1799] net: qmi_wwan: add ZTE MF60 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 6fecd35d4cd79fc75e8290abb86734c18500d2a2 upstream. Adding a device with limited QMI support. It does not support normal QMI_WDS commands for connection management. Instead, sending a QMI_CTL SET_INSTANCE_ID command is required to enable the network interface: 01 0f 00 00 00 00 00 00 20 00 04 00 01 01 00 00 A number of QMI_DMS and QMI_NAS commands are also supported for optional device management. Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/qmi_wwan.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 739e56d305b8..f2df274103ec 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -346,6 +346,15 @@ static const struct driver_info qmi_wwan_force_int1 = { .data = BIT(1), /* interface whitelist bitmap */ }; +static const struct driver_info qmi_wwan_force_int2 = { + .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind_shared, + .manage_power = qmi_wwan_manage_power, + .data = BIT(2), /* interface whitelist bitmap */ +}; + static const struct driver_info qmi_wwan_force_int3 = { .description = "Qualcomm WWAN/QMI device", .flags = FLAG_WWAN, @@ -498,6 +507,15 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_force_int4, }, + { /* ZTE MF60 */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x1402, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int2, + }, { /* Sierra Wireless MC77xx in QMI mode */ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x1199, -- GitLab From e7861ce75b60e23d4d0a0b08c6f20fb3dc236c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 12 Jul 2012 01:18:26 +0000 Subject: [PATCH 0552/1799] net: qmi_wwan: add ZTE MF821D MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit db8dacf953a70274172236957a4b97d4fdb376f0 upstream. Sold by O2 (telefonica germany) under the name "LTE4G" Tested-by: Thomas Schäfer Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/qmi_wwan.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index f2df274103ec..23378fb14aed 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -453,6 +453,15 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_force_int4, }, + { /* ZTE MF821D */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x0326, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int4, + }, { /* ZTE (Vodafone) K3520-Z */ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x19d2, -- GitLab From 8d3362715e0c0d29274b1689d87914e7c64f0032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 23 Aug 2012 12:13:57 +0200 Subject: [PATCH 0553/1799] net: qmi_wwan: add Sierra Wireless devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 9b469a60d68b13c288d5c3fc23de29d9d482dbe6 upstream. Add 6 new devices and one modified device, based on information from laptop vendor Windows drivers. Sony provides a driver with two new devices using a Gobi 2k+ layout (1199:68a5 and 1199:68a9). The Sony driver also adds a non-standard QMI/net interface to the already supported 1199:9011 Gobi device. We do not know whether this is an alternate interface number or an additional interface which might be present, but that doesn't really matter. Lenovo provides a driver supporting 4 new devices: - MC7770 (1199:901b) with standard Gobi 2k+ layout - MC7700 (0f3d:68a2) with layout similar to MC7710 - MC7750 (114f:68a2) with layout similar to MC7710 - EM7700 (1199:901c) with layout similar to MC7710 Note regaring the three devices similar to MC7710: The Windows drivers only support interface #8 on these devices. The MC7710 can support QMI/net functions on interface #19 and #20 as well, and this driver is verified to work on interface #19 (a firmware bug is suspected to prevent #20 from working). We do not enable these additional interfaces until they either show up in a Windows driver or are verified to work in some other way. Therefore limiting the new devices to interface #8 for now. [bmork: backported to 3.4: use driver whitelisting] Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/qmi_wwan.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 23378fb14aed..b1c3740c9fd3 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -534,6 +534,33 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_sierra, }, + { /* Sierra Wireless MC7700 */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0f3d, + .idProduct = 0x68a2, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_sierra, + }, + { /* Sierra Wireless MC7750 */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x114f, + .idProduct = 0x68a2, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_sierra, + }, + { /* Sierra Wireless EM7700 */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x1199, + .idProduct = 0x901c, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_sierra, + }, /* Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ @@ -561,6 +588,8 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */ {QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */ {QMI_GOBI_DEVICE(0x05c6, 0x9275)}, /* iRex Technologies Gobi 2000 Modem device (VR307) */ + {QMI_GOBI_DEVICE(0x1199, 0x68a5)}, /* Sierra Wireless Modem */ + {QMI_GOBI_DEVICE(0x1199, 0x68a9)}, /* Sierra Wireless Modem */ {QMI_GOBI_DEVICE(0x1199, 0x9001)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9002)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9003)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ @@ -577,6 +606,8 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ + {QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ + { } /* END */ }; MODULE_DEVICE_TABLE(usb, products); -- GitLab From 642550436c8b3a933550468996ef547630344a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 23 Aug 2012 12:13:58 +0200 Subject: [PATCH 0554/1799] net: qmi_wwan: new devices: UML290 and K5006-Z MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 10cbc1d97a7c7f9ae862fffe27b771ef0da9c461 upstream. Newer firmware versions for the Pantech UML290 use a different subclass ID. The Windows driver match on both IDs, so we do that as well. The ZTE (Vodafone) K5006-Z is a new device. Signed-off-by: Bjørn Mork Cc: Dan Williams Cc: Thomas Schäfer [bmork: backported to 3.4: use driver whitelisting] Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/qmi_wwan.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index b1c3740c9fd3..8669c77fa7c3 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -444,6 +444,15 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_shared, }, + { /* Pantech UML290 - newer firmware */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x106c, + .idProduct = 0x3718, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xf1, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_shared, + }, { /* ZTE MF820D */ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x19d2, @@ -516,6 +525,15 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_force_int4, }, + { /* ZTE (Vodafone) K5006-Z */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x1018, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int3, + }, { /* ZTE MF60 */ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x19d2, -- GitLab From 49194d4e7d8c14fb83f213c54a476685f8389c70 Mon Sep 17 00:00:00 2001 From: Satoru Moriya Date: Tue, 29 May 2012 15:06:47 -0700 Subject: [PATCH 0555/1799] mm: avoid swapping out with swappiness==0 commit fe35004fbf9eaf67482b074a2e032abb9c89b1dd upstream. Sometimes we'd like to avoid swapping out anonymous memory. In particular, avoid swapping out pages of important process or process groups while there is a reasonable amount of pagecache on RAM so that we can satisfy our customers' requirements. OTOH, we can control how aggressive the kernel will swap memory pages with /proc/sys/vm/swappiness for global and /sys/fs/cgroup/memory/memory.swappiness for each memcg. But with current reclaim implementation, the kernel may swap out even if we set swappiness=0 and there is pagecache in RAM. This patch changes the behavior with swappiness==0. If we set swappiness==0, the kernel does not swap out completely (for global reclaim until the amount of free pages and filebacked pages in a zone has been reduced to something very very small (nr_free + nr_filebacked < high watermark)). Signed-off-by: Satoru Moriya Acked-by: Minchan Kim Reviewed-by: Rik van Riel Acked-by: Jerome Marchand Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/vmscan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index be5bc0af2e76..e989ee22f100 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1983,10 +1983,10 @@ static void get_scan_count(struct mem_cgroup_zone *mz, struct scan_control *sc, * proportional to the fraction of recently scanned pages on * each list that were recently referenced and in active use. */ - ap = (anon_prio + 1) * (reclaim_stat->recent_scanned[0] + 1); + ap = anon_prio * (reclaim_stat->recent_scanned[0] + 1); ap /= reclaim_stat->recent_rotated[0] + 1; - fp = (file_prio + 1) * (reclaim_stat->recent_scanned[1] + 1); + fp = file_prio * (reclaim_stat->recent_scanned[1] + 1); fp /= reclaim_stat->recent_rotated[1] + 1; spin_unlock_irq(&mz->zone->lru_lock); @@ -1999,7 +1999,7 @@ static void get_scan_count(struct mem_cgroup_zone *mz, struct scan_control *sc, unsigned long scan; scan = zone_nr_lru_pages(mz, lru); - if (priority || noswap) { + if (priority || noswap || !vmscan_swappiness(mz, sc)) { scan >>= priority; if (!scan && force_scan) scan = SWAP_CLUSTER_MAX; -- GitLab From 77d13a088343c507a8d5bb924abc730c603f1f6b Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Wed, 8 Aug 2012 08:27:03 -0500 Subject: [PATCH 0556/1799] irq_remap: disable IRQ remapping if any IOAPIC lacks an IOMMU commit 32ab31e01e2def6f48294d872d9bb42573aae00f upstream. The ACPI tables in the Macbook Air 5,1 define a single IOAPIC with id 2, but the only remapping unit described in the DMAR table matches id 0. Interrupt remapping fails as a result, and the kernel panics with the message "timer doesn't work through Interrupt-remapped IO-APIC." To fix this, check each IOAPIC for a corresponding IOMMU. If an IOMMU is not found, do not allow IRQ remapping to be enabled. v2: Move check to parse_ioapics_under_ir(), raise log level to KERN_ERR, and add FW_BUG to the log message v3: Skip check if IOMMU doesn't support interrupt remapping and remove existing check that the IOMMU count equals the IOAPIC count Acked-by: Suresh Siddha Signed-off-by: Seth Forshee Acked-by: Yinghai Lu Signed-off-by: Joerg Roedel Acked-by: Cho, Yu-Chen Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intr_remapping.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/intr_remapping.c b/drivers/iommu/intr_remapping.c index 6777ca049471..73ca321f330a 100644 --- a/drivers/iommu/intr_remapping.c +++ b/drivers/iommu/intr_remapping.c @@ -752,6 +752,7 @@ int __init parse_ioapics_under_ir(void) { struct dmar_drhd_unit *drhd; int ir_supported = 0; + int ioapic_idx; for_each_drhd_unit(drhd) { struct intel_iommu *iommu = drhd->iommu; @@ -764,13 +765,20 @@ int __init parse_ioapics_under_ir(void) } } - if (ir_supported && ir_ioapic_num != nr_ioapics) { - printk(KERN_WARNING - "Not all IO-APIC's listed under remapping hardware\n"); - return -1; + if (!ir_supported) + return 0; + + for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) { + int ioapic_id = mpc_ioapic_id(ioapic_idx); + if (!map_ioapic_to_ir(ioapic_id)) { + pr_err(FW_BUG "ioapic %d has no mapping iommu, " + "interrupt remapping will be disabled\n", + ioapic_id); + return -1; + } } - return ir_supported; + return 1; } int __init ir_dev_scope_init(void) -- GitLab From 1d22d5660b961c6b36fa361e1e394f64b068c763 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 12 Sep 2012 09:05:22 +0200 Subject: [PATCH 0557/1799] UBI: fix a horrible memory deallocation bug commit 78b495c39add820ab66ab897af9bd77a5f2e91f6 upstream UBI was mistakingly using 'kfree()' instead of 'kmem_cache_free()' when freeing "attach eraseblock" structures in vtbl.c. Thankfully, this happened only when we were doing auto-format, so many systems were unaffected. However, there are still many users affected. It is strange, but the system did not crash and nothing bad happened when the SLUB memory allocator was used. However, in case of SLOB we observed an crash right away. This problem was introduced in 2.6.39 by commit "6c1e875 UBI: add slab cache for ubi_scan_leb objects" Reported-by: Richard Genoud Signed-off-by: Artem Bityutskiy Signed-off-by: Richard Genoud Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/ubi/vtbl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 17cec0c01544..c015fc0a76d8 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -346,7 +346,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si, */ err = ubi_scan_add_used(ubi, si, new_seb->pnum, new_seb->ec, vid_hdr, 0); - kfree(new_seb); + kmem_cache_free(si->scan_leb_slab, new_seb); ubi_free_vid_hdr(ubi, vid_hdr); return err; @@ -359,7 +359,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si, list_add(&new_seb->u.list, &si->erase); goto retry; } - kfree(new_seb); + kmem_cache_free(si->scan_leb_slab, new_seb); out_free: ubi_free_vid_hdr(ubi, vid_hdr); return err; -- GitLab From 6a4ebdb6be2ac2ad0e03ca9131573a1f0eadd7d5 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Tue, 3 Jul 2012 16:46:41 +0400 Subject: [PATCH 0558/1799] NFSd: introduce nfsd_destroy() helper commit 19f7e2ca44dfc3c1b3f499fc46801f98d403500f upstream. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfsctl.c | 8 ++------ fs/nfsd/nfsd.h | 9 +++++++++ fs/nfsd/nfssvc.c | 14 +++----------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 3ab12eb2967f..d014727fc8f2 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -663,9 +663,7 @@ static ssize_t __write_ports_addfd(char *buf) err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); if (err < 0) { - if (nfsd_serv->sv_nrthreads == 1) - svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); + nfsd_destroy(net); return err; } @@ -734,9 +732,7 @@ static ssize_t __write_ports_addxprt(char *buf) svc_xprt_put(xprt); } out_err: - if (nfsd_serv->sv_nrthreads == 1) - svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); + nfsd_destroy(net); return err; } diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 1671429ffa66..e3339ca2b65c 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -73,6 +73,15 @@ int nfsd_nrpools(void); int nfsd_get_nrthreads(int n, int *); int nfsd_set_nrthreads(int n, int *); +static inline void nfsd_destroy(struct net *net) +{ + int destroy = (nfsd_serv->sv_nrthreads == 1); + + if (destroy) + svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_serv); +} + #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) #ifdef CONFIG_NFSD_V2_ACL extern struct svc_version nfsd_acl_version2; diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index bcda12a3f082..a7042fc1b090 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -427,11 +427,7 @@ int nfsd_set_nrthreads(int n, int *nthreads) if (err) break; } - - if (nfsd_serv->sv_nrthreads == 1) - svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); - + nfsd_destroy(net); return err; } @@ -478,9 +474,7 @@ nfsd_svc(unsigned short port, int nrservs) if (error < 0 && !nfsd_up_before) nfsd_shutdown(); out_destroy: - if (nfsd_serv->sv_nrthreads == 1) - svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); /* Release server */ + nfsd_destroy(net); /* Release server */ out: mutex_unlock(&nfsd_mutex); return error; @@ -682,9 +676,7 @@ int nfsd_pool_stats_release(struct inode *inode, struct file *file) mutex_lock(&nfsd_mutex); /* this function really, really should have been called svc_put() */ - if (nfsd_serv->sv_nrthreads == 1) - svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); + nfsd_destroy(net); mutex_unlock(&nfsd_mutex); return ret; } -- GitLab From c717dcaf750cd0a43609d8c2016a380e542b28ed Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Tue, 3 Jul 2012 16:46:41 +0400 Subject: [PATCH 0559/1799] NFSd: set nfsd_serv to NULL after service destruction commit 57c8b13e3cd0f94944c9691ce7f58e5fcef8a12d upstream. In nfsd_destroy(): if (destroy) svc_shutdown_net(nfsd_serv, net); svc_destroy(nfsd_server); svc_shutdown_net(nfsd_serv, net) calls nfsd_last_thread(), which sets nfsd_serv to NULL, causing a NULL dereference on the following line. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfsd.h | 2 ++ fs/nfsd/nfssvc.c | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index e3339ca2b65c..1336a6512cdc 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -80,6 +80,8 @@ static inline void nfsd_destroy(struct net *net) if (destroy) svc_shutdown_net(nfsd_serv, net); svc_destroy(nfsd_serv); + if (destroy) + nfsd_serv = NULL; } #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index a7042fc1b090..b6f8e65f85bd 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -254,8 +254,6 @@ static void nfsd_shutdown(void) static void nfsd_last_thread(struct svc_serv *serv, struct net *net) { - /* When last nfsd thread exits we need to do some clean-up */ - nfsd_serv = NULL; nfsd_shutdown(); svc_rpcb_cleanup(serv, net); @@ -332,6 +330,7 @@ static int nfsd_get_default_max_blksize(void) int nfsd_create_serv(void) { int error; + struct net *net = current->nsproxy->net_ns; WARN_ON(!mutex_is_locked(&nfsd_mutex)); if (nfsd_serv) { @@ -346,7 +345,7 @@ int nfsd_create_serv(void) if (nfsd_serv == NULL) return -ENOMEM; - error = svc_bind(nfsd_serv, current->nsproxy->net_ns); + error = svc_bind(nfsd_serv, net); if (error < 0) { svc_destroy(nfsd_serv); return error; @@ -557,12 +556,13 @@ nfsd(void *vrqstp) nfsdstats.th_cnt --; out: - if (rqstp->rq_server->sv_nrthreads == 1) - svc_shutdown_net(rqstp->rq_server, &init_net); + rqstp->rq_server = NULL; /* Release the thread */ svc_exit_thread(rqstp); + nfsd_destroy(&init_net); + /* Release module */ mutex_unlock(&nfsd_mutex); module_put_and_exit(0); -- GitLab From 34b6567e91b3ff6209c16b3868ec95e0e1cddc1f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 19 Jul 2012 13:52:53 -0700 Subject: [PATCH 0560/1799] kthread_worker: reorganize to prepare for flush_kthread_work() reimplementation commit 9a2e03d8ed518a61154f18d83d6466628e519f94 upstream. Make the following two non-functional changes. * Separate out insert_kthread_work() from queue_kthread_work(). * Relocate struct kthread_flush_work and kthread_flush_work_fn() definitions above flush_kthread_work(). v2: Added lockdep_assert_held() in insert_kthread_work() as suggested by Andy Walls. Signed-off-by: Tejun Heo Acked-by: Andy Walls Cc: Colin Cross Signed-off-by: Greg Kroah-Hartman --- kernel/kthread.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/kernel/kthread.c b/kernel/kthread.c index 3d3de633702e..4bfbff36d447 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -378,6 +378,19 @@ int kthread_worker_fn(void *worker_ptr) } EXPORT_SYMBOL_GPL(kthread_worker_fn); +/* insert @work before @pos in @worker */ +static void insert_kthread_work(struct kthread_worker *worker, + struct kthread_work *work, + struct list_head *pos) +{ + lockdep_assert_held(&worker->lock); + + list_add_tail(&work->node, pos); + work->queue_seq++; + if (likely(worker->task)) + wake_up_process(worker->task); +} + /** * queue_kthread_work - queue a kthread_work * @worker: target kthread_worker @@ -395,10 +408,7 @@ bool queue_kthread_work(struct kthread_worker *worker, spin_lock_irqsave(&worker->lock, flags); if (list_empty(&work->node)) { - list_add_tail(&work->node, &worker->work_list); - work->queue_seq++; - if (likely(worker->task)) - wake_up_process(worker->task); + insert_kthread_work(worker, work, &worker->work_list); ret = true; } spin_unlock_irqrestore(&worker->lock, flags); @@ -406,6 +416,18 @@ bool queue_kthread_work(struct kthread_worker *worker, } EXPORT_SYMBOL_GPL(queue_kthread_work); +struct kthread_flush_work { + struct kthread_work work; + struct completion done; +}; + +static void kthread_flush_work_fn(struct kthread_work *work) +{ + struct kthread_flush_work *fwork = + container_of(work, struct kthread_flush_work, work); + complete(&fwork->done); +} + /** * flush_kthread_work - flush a kthread_work * @work: work to flush @@ -436,18 +458,6 @@ void flush_kthread_work(struct kthread_work *work) } EXPORT_SYMBOL_GPL(flush_kthread_work); -struct kthread_flush_work { - struct kthread_work work; - struct completion done; -}; - -static void kthread_flush_work_fn(struct kthread_work *work) -{ - struct kthread_flush_work *fwork = - container_of(work, struct kthread_flush_work, work); - complete(&fwork->done); -} - /** * flush_kthread_worker - flush all current works on a kthread_worker * @worker: worker to flush -- GitLab From 97ed537eaa6ff11c9a1df342364e25d0996bc117 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 19 Jul 2012 13:52:53 -0700 Subject: [PATCH 0561/1799] kthread_worker: reimplement flush_kthread_work() to allow freeing the work item being executed commit 46f3d976213452350f9d10b0c2780c2681f7075b upstream. kthread_worker provides minimalistic workqueue-like interface for users which need a dedicated worker thread (e.g. for realtime priority). It has basic queue, flush_work, flush_worker operations which mostly match the workqueue counterparts; however, due to the way flush_work() is implemented, it has a noticeable difference of not allowing work items to be freed while being executed. While the current users of kthread_worker are okay with the current behavior, the restriction does impede some valid use cases. Also, removing this difference isn't difficult and actually makes the code easier to understand. This patch reimplements flush_kthread_work() such that it uses a flush_work item instead of queue/done sequence numbers. Signed-off-by: Tejun Heo Cc: Colin Cross Signed-off-by: Greg Kroah-Hartman --- include/linux/kthread.h | 8 ++----- kernel/kthread.c | 48 +++++++++++++++++++++++------------------ 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 0714b24c0e45..22ccf9dee177 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -49,8 +49,6 @@ extern int tsk_fork_get_node(struct task_struct *tsk); * can be queued and flushed using queue/flush_kthread_work() * respectively. Queued kthread_works are processed by a kthread * running kthread_worker_fn(). - * - * A kthread_work can't be freed while it is executing. */ struct kthread_work; typedef void (*kthread_work_func_t)(struct kthread_work *work); @@ -59,15 +57,14 @@ struct kthread_worker { spinlock_t lock; struct list_head work_list; struct task_struct *task; + struct kthread_work *current_work; }; struct kthread_work { struct list_head node; kthread_work_func_t func; wait_queue_head_t done; - atomic_t flushing; - int queue_seq; - int done_seq; + struct kthread_worker *worker; }; #define KTHREAD_WORKER_INIT(worker) { \ @@ -79,7 +76,6 @@ struct kthread_work { .node = LIST_HEAD_INIT((work).node), \ .func = (fn), \ .done = __WAIT_QUEUE_HEAD_INITIALIZER((work).done), \ - .flushing = ATOMIC_INIT(0), \ } #define DEFINE_KTHREAD_WORKER(worker) \ diff --git a/kernel/kthread.c b/kernel/kthread.c index 4bfbff36d447..b579af57ea10 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -360,16 +360,12 @@ int kthread_worker_fn(void *worker_ptr) struct kthread_work, node); list_del_init(&work->node); } + worker->current_work = work; spin_unlock_irq(&worker->lock); if (work) { __set_current_state(TASK_RUNNING); work->func(work); - smp_wmb(); /* wmb worker-b0 paired with flush-b1 */ - work->done_seq = work->queue_seq; - smp_mb(); /* mb worker-b1 paired with flush-b0 */ - if (atomic_read(&work->flushing)) - wake_up_all(&work->done); } else if (!freezing(current)) schedule(); @@ -386,7 +382,7 @@ static void insert_kthread_work(struct kthread_worker *worker, lockdep_assert_held(&worker->lock); list_add_tail(&work->node, pos); - work->queue_seq++; + work->worker = worker; if (likely(worker->task)) wake_up_process(worker->task); } @@ -436,25 +432,35 @@ static void kthread_flush_work_fn(struct kthread_work *work) */ void flush_kthread_work(struct kthread_work *work) { - int seq = work->queue_seq; + struct kthread_flush_work fwork = { + KTHREAD_WORK_INIT(fwork.work, kthread_flush_work_fn), + COMPLETION_INITIALIZER_ONSTACK(fwork.done), + }; + struct kthread_worker *worker; + bool noop = false; + +retry: + worker = work->worker; + if (!worker) + return; - atomic_inc(&work->flushing); + spin_lock_irq(&worker->lock); + if (work->worker != worker) { + spin_unlock_irq(&worker->lock); + goto retry; + } - /* - * mb flush-b0 paired with worker-b1, to make sure either - * worker sees the above increment or we see done_seq update. - */ - smp_mb__after_atomic_inc(); + if (!list_empty(&work->node)) + insert_kthread_work(worker, &fwork.work, work->node.next); + else if (worker->current_work == work) + insert_kthread_work(worker, &fwork.work, worker->work_list.next); + else + noop = true; - /* A - B <= 0 tests whether B is in front of A regardless of overflow */ - wait_event(work->done, seq - work->done_seq <= 0); - atomic_dec(&work->flushing); + spin_unlock_irq(&worker->lock); - /* - * rmb flush-b1 paired with worker-b0, to make sure our caller - * sees every change made by work->func(). - */ - smp_mb__after_atomic_dec(); + if (!noop) + wait_for_completion(&fwork.done); } EXPORT_SYMBOL_GPL(flush_kthread_work); -- GitLab From feab18eb28ec4c93c0762b7407b616d19ab9ad8b Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 25 Apr 2012 18:22:40 +0400 Subject: [PATCH 0562/1799] LockD: pass service to per-net up and down functions commit 4db77695bf5738bdafa83d1b58b64cbecc6f55e7 upstream. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields Cc: Jason Wessel Signed-off-by: Greg Kroah-Hartman --- fs/lockd/svc.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 3250f280a171..58ddc38cfccd 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -251,10 +251,9 @@ static int make_socks(struct svc_serv *serv, struct net *net) return err; } -static int lockd_up_net(struct net *net) +static int lockd_up_net(struct svc_serv *serv, struct net *net) { struct lockd_net *ln = net_generic(net, lockd_net_id); - struct svc_serv *serv = nlmsvc_rqst->rq_server; int error; if (ln->nlmsvc_users++) @@ -276,10 +275,9 @@ static int lockd_up_net(struct net *net) return error; } -static void lockd_down_net(struct net *net) +static void lockd_down_net(struct svc_serv *serv, struct net *net) { struct lockd_net *ln = net_generic(net, lockd_net_id); - struct svc_serv *serv = nlmsvc_rqst->rq_server; if (ln->nlmsvc_users) { if (--ln->nlmsvc_users == 0) { @@ -307,7 +305,7 @@ int lockd_up(struct net *net) * Check whether we're already up and running. */ if (nlmsvc_rqst) { - error = lockd_up_net(net); + error = lockd_up_net(nlmsvc_rqst->rq_server, net); goto out; } @@ -378,7 +376,7 @@ int lockd_up(struct net *net) return error; err_start: - lockd_down_net(net); + lockd_down_net(serv, net); goto destroy_and_out; } EXPORT_SYMBOL_GPL(lockd_up); @@ -390,7 +388,7 @@ void lockd_down(struct net *net) { mutex_lock(&nlmsvc_mutex); - lockd_down_net(net); + lockd_down_net(nlmsvc_rqst->rq_server, net); if (nlmsvc_users) { if (--nlmsvc_users) goto out; -- GitLab From 0f36cbb3364497fce45f40f295847f2de7cceeb7 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Sun, 23 Sep 2012 22:56:00 +0200 Subject: [PATCH 0563/1799] USB: ohci-at91: fix null pointer in ohci_hcd_at91_overcurrent_irq commit 01bb6501779ed0b6dc6c55be34b49eaa6306fdd8 upstream. Fixes the following NULL pointer dereference: [ 7.740000] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver [ 7.810000] Unable to handle kernel NULL pointer dereference at virtual address 00000028 [ 7.810000] pgd = c3a38000 [ 7.810000] [00000028] *pgd=23a8c831, *pte=00000000, *ppte=00000000 [ 7.810000] Internal error: Oops: 17 [#1] PREEMPT ARM [ 7.810000] Modules linked in: ohci_hcd(+) regmap_i2c snd_pcm usbcore snd_page_alloc at91_cf snd_timer pcmcia_rsrc snd soundcore gpio_keys regmap_spi pcmcia_core usb_common nls_base [ 7.810000] CPU: 0 Not tainted (3.6.0-rc6-mpa+ #264) [ 7.810000] PC is at __gpio_to_irq+0x18/0x40 [ 7.810000] LR is at ohci_hcd_at91_overcurrent_irq+0x24/0xb4 [ohci_hcd] [ 7.810000] pc : [] lr : [] psr: 40000093 [ 7.810000] sp : c3a11c40 ip : c3a11c50 fp : c3a11c4c [ 7.810000] r10: 00000000 r9 : c02dcd6e r8 : fefff400 [ 7.810000] r7 : 00000000 r6 : c02cc928 r5 : 00000030 r4 : c02dd168 [ 7.810000] r3 : c02e7350 r2 : ffffffea r1 : c02cc928 r0 : 00000000 [ 7.810000] Flags: nZcv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user [ 7.810000] Control: c000717f Table: 23a38000 DAC: 00000015 [ 7.810000] Process modprobe (pid: 285, stack limit = 0xc3a10270) [ 7.810000] Stack: (0xc3a11c40 to 0xc3a12000) [ 7.810000] 1c40: c3a11c6c c3a11c50 bf08f694 c01392cc c3a11c84 c2c38b00 c3806900 00000030 [ 7.810000] 1c60: c3a11ca4 c3a11c70 c0051264 bf08f680 c3a11cac c3a11c80 c003e764 c3806900 [ 7.810000] 1c80: c2c38b00 c02cb05c c02cb000 fefff400 c3806930 c3a11cf4 c3a11cbc c3a11ca8 [ 7.810000] 1ca0: c005142c c005123c c3806900 c3805a00 c3a11cd4 c3a11cc0 c0053f24 c00513e4 [ 7.810000] 1cc0: c3a11cf4 00000030 c3a11cec c3a11cd8 c005120c c0053e88 00000000 00000000 [ 7.810000] 1ce0: c3a11d1c c3a11cf0 c00124d0 c00511e0 01400000 00000001 00000012 00000000 [ 7.810000] 1d00: ffffffff c3a11d94 00000030 00000000 c3a11d34 c3a11d20 c005120c c0012438 [ 7.810000] 1d20: c001dac4 00000012 c3a11d4c c3a11d38 c0009b08 c00511e0 c00523fc 60000013 [ 7.810000] 1d40: c3a11d5c c3a11d50 c0008510 c0009ab4 c3a11ddc c3a11d60 c0008eb4 c00084f0 [ 7.810000] 1d60: 00000000 00000030 00000000 00000080 60000013 bf08f670 c3806900 c2c38b00 [ 7.810000] 1d80: 00000030 c3806930 00000000 c3a11ddc c3a11d88 c3a11da8 c0054190 c00523fc [ 7.810000] 1da0: 60000013 ffffffff c3a11dec c3a11db8 00000000 c2c38b00 bf08f670 c3806900 [ 7.810000] 1dc0: 00000000 00000080 c02cc928 00000030 c3a11e0c c3a11de0 c0052764 c00520d8 [ 7.810000] 1de0: c3a11dfc 00000000 00000000 00000002 bf090f61 00000004 c02cc930 c02cc928 [ 7.810000] 1e00: c3a11e4c c3a11e10 bf090978 c005269c bf090f61 c02cc928 bf093000 c02dd170 [ 7.810000] 1e20: c3a11e3c c02cc930 c02cc930 bf0911d0 bf0911d0 bf093000 c3a10000 00000000 [ 7.810000] 1e40: c3a11e5c c3a11e50 c0155b7c bf090808 c3a11e7c c3a11e60 c0154690 c0155b6c [ 7.810000] 1e60: c02cc930 c02cc964 bf0911d0 c3a11ea0 c3a11e9c c3a11e80 c015484c c01545e8 [ 7.810000] 1e80: 00000000 00000000 c01547e4 bf0911d0 c3a11ec4 c3a11ea0 c0152e58 c01547f4 [ 7.810000] 1ea0: c381b88c c384ab10 c2c10540 bf0911d0 00000000 c02d7518 c3a11ed4 c3a11ec8 [ 7.810000] 1ec0: c01544c0 c0152e0c c3a11efc c3a11ed8 c01536cc c01544b0 bf091075 c3a11ee8 [ 7.810000] 1ee0: bf049af0 bf09120c bf0911d0 00000000 c3a11f1c c3a11f00 c0154e9c c0153628 [ 7.810000] 1f00: bf049af0 bf09120c 000ae190 00000000 c3a11f2c c3a11f20 c0155f58 c0154e04 [ 7.810000] 1f20: c3a11f44 c3a11f30 bf093054 c0155f1c 00000000 00006a4f c3a11f7c c3a11f48 [ 7.810000] 1f40: c0008638 bf093010 bf09120c 000ae190 00000000 c00093c4 00006a4f bf09120c [ 7.810000] 1f60: 000ae190 00000000 c00093c4 00000000 c3a11fa4 c3a11f80 c004fdc4 c000859c [ 7.810000] 1f80: c3a11fa4 000ae190 00006a4f 00016eb8 000ad018 00000080 00000000 c3a11fa8 [ 7.810000] 1fa0: c0009260 c004fd58 00006a4f 00016eb8 000ae190 00006a4f 000ae100 00000000 [ 7.810000] 1fc0: 00006a4f 00016eb8 000ad018 00000080 000adba0 000ad208 00000000 000ad3d8 [ 7.810000] 1fe0: beaf7ae8 beaf7ad8 000172b8 b6e4e940 20000010 000ae190 00000000 00000000 [ 7.810000] Backtrace: [ 7.810000] [] (__gpio_to_irq+0x0/0x40) from [] (ohci_hcd_at91_overcurrent_irq+0x24/0xb4 [ohci_hcd]) [ 7.810000] [] (ohci_hcd_at91_overcurrent_irq+0x0/0xb4 [ohci_hcd]) from [] (handle_irq_event_percpu+0x38/0x1a8) [ 7.810000] r6:00000030 r5:c3806900 r4:c2c38b00 [ 7.810000] [] (handle_irq_event_percpu+0x0/0x1a8) from [] (handle_irq_event+0x58/0x7c) [ 7.810000] [] (handle_irq_event+0x0/0x7c) from [] (handle_simple_irq+0xac/0xd8) [ 7.810000] r5:c3805a00 r4:c3806900 [ 7.810000] [] (handle_simple_irq+0x0/0xd8) from [] (generic_handle_irq+0x3c/0x48) [ 7.810000] r4:00000030 [ 7.810000] [] (generic_handle_irq+0x0/0x48) from [] (gpio_irq_handler+0xa8/0xfc) [ 7.810000] r4:00000000 [ 7.810000] [] (gpio_irq_handler+0x0/0xfc) from [] (generic_handle_irq+0x3c/0x48) [ 7.810000] [] (generic_handle_irq+0x0/0x48) from [] (handle_IRQ+0x64/0x88) [ 7.810000] r4:00000012 [ 7.810000] [] (handle_IRQ+0x0/0x88) from [] (at91_aic_handle_irq+0x30/0x38) [ 7.810000] r5:60000013 r4:c00523fc [ 7.810000] [] (at91_aic_handle_irq+0x0/0x38) from [] (__irq_svc+0x34/0x60) [ 7.810000] Exception stack(0xc3a11d60 to 0xc3a11da8) [ 7.810000] 1d60: 00000000 00000030 00000000 00000080 60000013 bf08f670 c3806900 c2c38b00 [ 7.810000] 1d80: 00000030 c3806930 00000000 c3a11ddc c3a11d88 c3a11da8 c0054190 c00523fc [ 7.810000] 1da0: 60000013 ffffffff [ 7.810000] [] (__setup_irq+0x0/0x458) from [] (request_threaded_irq+0xd8/0x134) [ 7.810000] [] (request_threaded_irq+0x0/0x134) from [] (ohci_hcd_at91_drv_probe+0x180/0x41c [ohci_hcd]) [ 7.810000] [] (ohci_hcd_at91_drv_probe+0x0/0x41c [ohci_hcd]) from [] (platform_drv_probe+0x20/0x24) [ 7.810000] [] (platform_drv_probe+0x0/0x24) from [] (driver_probe_device+0xb8/0x20c) [ 7.810000] [] (driver_probe_device+0x0/0x20c) from [] (__driver_attach+0x68/0x88) [ 7.810000] r7:c3a11ea0 r6:bf0911d0 r5:c02cc964 r4:c02cc930 [ 7.810000] [] (__driver_attach+0x0/0x88) from [] (bus_for_each_dev+0x5c/0x9c) [ 7.810000] r6:bf0911d0 r5:c01547e4 r4:00000000 [ 7.810000] [] (bus_for_each_dev+0x0/0x9c) from [] (driver_attach+0x20/0x28) [ 7.810000] r7:c02d7518 r6:00000000 r5:bf0911d0 r4:c2c10540 [ 7.810000] [] (driver_attach+0x0/0x28) from [] (bus_add_driver+0xb4/0x22c) [ 7.810000] [] (bus_add_driver+0x0/0x22c) from [] (driver_register+0xa8/0x144) [ 7.810000] r7:00000000 r6:bf0911d0 r5:bf09120c r4:bf049af0 [ 7.810000] [] (driver_register+0x0/0x144) from [] (platform_driver_register+0x4c/0x60) [ 7.810000] r7:00000000 r6:000ae190 r5:bf09120c r4:bf049af0 [ 7.810000] [] (platform_driver_register+0x0/0x60) from [] (ohci_hcd_mod_init+0x54/0x8c [ohci_hcd]) [ 7.810000] [] (ohci_hcd_mod_init+0x0/0x8c [ohci_hcd]) from [] (do_one_initcall+0xac/0x174) [ 7.810000] r4:00006a4f [ 7.810000] [] (do_one_initcall+0x0/0x174) from [] (sys_init_module+0x7c/0x1a0) [ 7.810000] [] (sys_init_module+0x0/0x1a0) from [] (ret_fast_syscall+0x0/0x2c) [ 7.810000] r7:00000080 r6:000ad018 r5:00016eb8 r4:00006a4f [ 7.810000] Code: e24cb004 e59f3028 e1a02000 e7930180 (e5903028) [ 7.810000] ---[ end trace 85aa37ed128143b5 ]--- [ 7.810000] Kernel panic - not syncing: Fatal exception in interrupt Commit 6fffb77c (USB: ohci-at91: fix PIO handling in relation with number of ports) started setting unused pins to EINVAL. But this exposed a bug in the ohci_hcd_at91_overcurrent_irq function where the gpio was used without being checked to see if it is valid. This patches fixed the issue by adding the gpio valid check. Signed-off-by: Joachim Eastwood Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-at91.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 50bd3f1e3307..7841b0aa4072 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -466,7 +466,8 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) /* From the GPIO notifying the over-current situation, find * out the corresponding port */ at91_for_each_port(port) { - if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { + if (gpio_is_valid(pdata->overcurrent_pin[port]) && + gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { gpio = pdata->overcurrent_pin[port]; break; } -- GitLab From 1437cb571cacaf18ce2da7dd8c858fac57806d37 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 26 Sep 2012 13:09:53 -0400 Subject: [PATCH 0564/1799] USB: Fix race condition when removing host controllers commit 0d00dc2611abbe6ad244d50569c2ee82ce42846c upstream. This patch (as1607) fixes a race that can occur if a USB host controller is removed while a process is reading the /sys/kernel/debug/usb/devices file. The usb_device_read() routine uses the bus->root_hub pointer to determine whether or not the root hub is registered. The is not a valid test, because the pointer is set before the root hub gets registered and remains set even after the root hub is unregistered and deallocated. As a result, usb_device_read() or usb_device_dump() can access freed memory, causing an oops. The patch changes the test to use the hcd->rh_registered flag, which does get set and cleared at the appropriate times. It also makes sure to hold the usb_bus_list_lock mutex while setting the flag, so that usb_device_read() will become aware of new root hubs as soon as they are registered. Signed-off-by: Alan Stern Reported-by: Don Zickus Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devices.c | 2 +- drivers/usb/core/hcd.c | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index d95696584762..3440812b4a84 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -624,7 +624,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, /* print devices for all busses */ list_for_each_entry(bus, &usb_bus_list, bus_list) { /* recurse through all children of the root hub */ - if (!bus->root_hub) + if (!bus_to_hcd(bus)->rh_registered) continue; usb_lock_device(bus->root_hub); ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 140d3e11f212..e2cc8df3d87b 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1002,10 +1002,7 @@ static int register_root_hub(struct usb_hcd *hcd) if (retval) { dev_err (parent_dev, "can't register root hub for %s, %d\n", dev_name(&usb_dev->dev), retval); - } - mutex_unlock(&usb_bus_list_lock); - - if (retval == 0) { + } else { spin_lock_irq (&hcd_root_hub_lock); hcd->rh_registered = 1; spin_unlock_irq (&hcd_root_hub_lock); @@ -1014,6 +1011,7 @@ static int register_root_hub(struct usb_hcd *hcd) if (HCD_DEAD(hcd)) usb_hc_died (hcd); /* This time clean up */ } + mutex_unlock(&usb_bus_list_lock); return retval; } -- GitLab From d20ff72cdeb4cbb586a1ee1a3f4f1bbade52414a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 26 Sep 2012 11:57:30 +0100 Subject: [PATCH 0565/1799] ASoC: wm2000: Correct register size commit d0e12f3ff3472cbd8f52d3c0e6ee07a841787c40 upstream. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm2000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index a75c3766aede..ae6f26f25a67 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -692,7 +692,7 @@ static int wm2000_resume(struct snd_soc_codec *codec) #endif static const struct regmap_config wm2000_regmap = { - .reg_bits = 8, + .reg_bits = 16, .val_bits = 8, }; -- GitLab From 66801463734e49416a9b013d3eb8f9eb8cd851e0 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 20 Sep 2012 10:48:03 +0200 Subject: [PATCH 0566/1799] gpio-lpc32xx: Fix value handling of gpio_direction_output() commit b1268d3737c6316016026245eef276eda6b0a621 upstream. For GPIOs of gpio-lpc32xx, gpio_direction_output() ignores the value argument (initial value of output). This patch fixes this by setting the level accordingly. Signed-off-by: Roland Stigge Acked-by: Alexandre Pereira da Silva Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpio-lpc32xx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 61c2d08d37b6..e42e4b84016e 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -304,6 +304,7 @@ static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin, { struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + __set_gpio_level_p012(group, pin, value); __set_gpio_dir_p012(group, pin, 0); return 0; @@ -314,6 +315,7 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin, { struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + __set_gpio_level_p3(group, pin, value); __set_gpio_dir_p3(group, pin, 0); return 0; @@ -322,6 +324,9 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin, static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin, int value) { + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + + __set_gpo_level_p3(group, pin, value); return 0; } -- GitLab From bd1d3d8331af11cc1abf5e907a9a963037530281 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 25 Sep 2012 16:17:43 +1000 Subject: [PATCH 0567/1799] drm/udl: limit modes to the sku pixel limits. commit 3a75885848996baab5276ff37ebf7295c3c753f0 upstream. Otherwise when X starts we commonly get a black screen scanning out nothing, its wierd dpms on/off from userspace brings it back, With this on F18, multi-seat works again with my 1920x1200 monitor which is above the sku limit for the device I have. Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/udl/udl_connector.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index ba055e9ca007..8d9dc44f1f94 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -69,6 +69,13 @@ static int udl_get_modes(struct drm_connector *connector) static int udl_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { + struct udl_device *udl = connector->dev->dev_private; + if (!udl->sku_pixel_limit) + return 0; + + if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit) + return MODE_VIRTUAL_Y; + return 0; } -- GitLab From 03c4c80ee30ae2c965cd838dd0f21c97a877366d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 13 Aug 2012 13:22:35 +0300 Subject: [PATCH 0568/1799] drm/i915: fall back to bit-banging if GMBUS fails in CRT EDID reads commit f1a2f5b7c5f0941d23eef0a095c0b99bf8d051e6 upstream. GMBUS was enabled over bit-banging as the default in commits: commit c3dfefa0a6d235bd465309e12f4c56ea16e71111 Author: Daniel Vetter Date: Tue Feb 14 22:37:25 2012 +0100 drm/i915: reenable gmbus on gen3+ again and commit 0fb3f969c8683505fb7323c06bf8a999a5a45a15 Author: Daniel Vetter Date: Fri Mar 2 19:38:30 2012 +0100 drm/i915: enable gmbus on gen2 Unfortunately, GMBUS seems to fail on some CRT displays. Add a bit-banging fallback to CRT EDID reads. LKML-Reference: <201207251020.47637.maciej.rutecki@gmail.com> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45881 Signed-off-by: Jani Nikula Tested-by: Alex Ferrando Cc: stable@vger.kernel.org (for 3.4+3.5) Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_crt.c | 36 +++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 90b9793fd5da..342ffb7ec3d2 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -266,6 +266,36 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) return ret; } +static struct edid *intel_crt_get_edid(struct drm_connector *connector, + struct i2c_adapter *i2c) +{ + struct edid *edid; + + edid = drm_get_edid(connector, i2c); + + if (!edid && !intel_gmbus_is_forced_bit(i2c)) { + DRM_DEBUG_KMS("CRT GMBUS EDID read failed, retry using GPIO bit-banging\n"); + intel_gmbus_force_bit(i2c, true); + edid = drm_get_edid(connector, i2c); + intel_gmbus_force_bit(i2c, false); + } + + return edid; +} + +/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */ +static int intel_crt_ddc_get_modes(struct drm_connector *connector, + struct i2c_adapter *adapter) +{ + struct edid *edid; + + edid = intel_crt_get_edid(connector, adapter); + if (!edid) + return 0; + + return intel_connector_update_modes(connector, edid); +} + static bool intel_crt_detect_ddc(struct drm_connector *connector) { struct intel_crt *crt = intel_attached_crt(connector); @@ -279,7 +309,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector) struct edid *edid; bool is_digital = false; - edid = drm_get_edid(connector, + edid = intel_crt_get_edid(connector, &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); /* * This may be a DVI-I connector with a shared DDC @@ -477,13 +507,13 @@ static int intel_crt_get_modes(struct drm_connector *connector) struct drm_i915_private *dev_priv = dev->dev_private; int ret; - ret = intel_ddc_get_modes(connector, + ret = intel_crt_ddc_get_modes(connector, &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); if (ret || !IS_G4X(dev)) return ret; /* Try to probe digital port for output in DVI-I -> VGA mode. */ - return intel_ddc_get_modes(connector, + return intel_crt_ddc_get_modes(connector, &dev_priv->gmbus[GMBUS_PORT_DPB].adapter); } -- GitLab From 9a266f619f8b9994b0c2bd9bb79605ddfa4ac32a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 23 Sep 2012 19:33:55 +0300 Subject: [PATCH 0569/1799] vmwgfx: corruption in vmw_event_fence_action_create() commit 68c4fce737c4b963e336435f225621dc21138397 upstream. We don't allocate enough data for this struct. As soon as we start modifying event->event on the next lines, then we're going beyond the end of the memory we allocated. Signed-off-by: Dan Carpenter Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index f2fb8f15e2f1..7e0743358dff 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -1018,7 +1018,7 @@ int vmw_event_fence_action_create(struct drm_file *file_priv, } - event = kzalloc(sizeof(event->event), GFP_KERNEL); + event = kzalloc(sizeof(*event), GFP_KERNEL); if (unlikely(event == NULL)) { DRM_ERROR("Failed to allocate an event.\n"); ret = -ENOMEM; -- GitLab From 446d14d4c51010379f7f12f3616773e7e7fb47d9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Sep 2012 09:06:10 -0700 Subject: [PATCH 0570/1799] Revert: drm/i915: correctly order the ring init sequence This reverts commit 57ecc93ce680b1ace1f9e79d588dabe32353202c which really is commit 0d8957c8a90bbb5d34fab9a304459448a5131e06 upstream as it has been reported to cause problems in the 3.4.y kernel series. Reported-by: Herton Ronaldo Krzesinski Cc: Andreas Sturmlechner Cc: Jani Nikula Cc: Yang Guang Cc: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_ringbuffer.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 12a9e5fd9252..302d3d54fb41 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -258,6 +258,8 @@ static int init_ring_common(struct intel_ring_buffer *ring) I915_WRITE_HEAD(ring, 0); ring->write_tail(ring, 0); + /* Initialize the ring. */ + I915_WRITE_START(ring, obj->gtt_offset); head = I915_READ_HEAD(ring) & HEAD_ADDR; /* G45 ring initialization fails to reset head to zero */ @@ -283,11 +285,6 @@ static int init_ring_common(struct intel_ring_buffer *ring) } } - /* Initialize the ring. This must happen _after_ we've cleared the ring - * registers with the above sequence (the readback of the HEAD registers - * also enforces ordering), otherwise the hw might lose the new ring - * register values. */ - I915_WRITE_START(ring, obj->gtt_offset); I915_WRITE_CTL(ring, ((ring->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID); -- GitLab From 9effb1b2599c3ae0be3c5bf3f6187667fe2a6e70 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 13 Jul 2012 19:15:40 +0100 Subject: [PATCH 0571/1799] ARM: 7467/1: mutex: use generic xchg-based implementation for ARMv6+ commit a76d7bd96d65fa5119adba97e1b58d95f2e78829 upstream. The open-coded mutex implementation for ARMv6+ cores suffers from a severe lack of barriers, so in the uncontended case we don't actually protect any accesses performed during the critical section. Furthermore, the code is largely a duplication of the ARMv6+ atomic_dec code but optimised to remove a branch instruction, as the mutex fastpath was previously inlined. Now that this is executed out-of-line, we can reuse the atomic access code for the locking (in fact, we use the xchg code as this produces shorter critical sections). This patch uses the generic xchg based implementation for mutexes on ARMv6+, which introduces barriers to the lock/unlock operations and also has the benefit of removing a fair amount of inline assembly code. Acked-by: Arnd Bergmann Acked-by: Nicolas Pitre Reported-by: Shan Kang Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/mutex.h | 119 ++--------------------------------- 1 file changed, 4 insertions(+), 115 deletions(-) diff --git a/arch/arm/include/asm/mutex.h b/arch/arm/include/asm/mutex.h index 93226cf23ae0..b1479fd04a95 100644 --- a/arch/arm/include/asm/mutex.h +++ b/arch/arm/include/asm/mutex.h @@ -7,121 +7,10 @@ */ #ifndef _ASM_MUTEX_H #define _ASM_MUTEX_H - -#if __LINUX_ARM_ARCH__ < 6 -/* On pre-ARMv6 hardware the swp based implementation is the most efficient. */ -# include -#else - /* - * Attempting to lock a mutex on ARMv6+ can be done with a bastardized - * atomic decrement (it is not a reliable atomic decrement but it satisfies - * the defined semantics for our purpose, while being smaller and faster - * than a real atomic decrement or atomic swap. The idea is to attempt - * decrementing the lock value only once. If once decremented it isn't zero, - * or if its store-back fails due to a dispute on the exclusive store, we - * simply bail out immediately through the slow path where the lock will be - * reattempted until it succeeds. + * On pre-ARMv6 hardware this results in a swp-based implementation, + * which is the most efficient. For ARMv6+, we emit a pair of exclusive + * accesses instead. */ -static inline void -__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) -{ - int __ex_flag, __res; - - __asm__ ( - - "ldrex %0, [%2] \n\t" - "sub %0, %0, #1 \n\t" - "strex %1, %0, [%2] " - - : "=&r" (__res), "=&r" (__ex_flag) - : "r" (&(count)->counter) - : "cc","memory" ); - - __res |= __ex_flag; - if (unlikely(__res != 0)) - fail_fn(count); -} - -static inline int -__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) -{ - int __ex_flag, __res; - - __asm__ ( - - "ldrex %0, [%2] \n\t" - "sub %0, %0, #1 \n\t" - "strex %1, %0, [%2] " - - : "=&r" (__res), "=&r" (__ex_flag) - : "r" (&(count)->counter) - : "cc","memory" ); - - __res |= __ex_flag; - if (unlikely(__res != 0)) - __res = fail_fn(count); - return __res; -} - -/* - * Same trick is used for the unlock fast path. However the original value, - * rather than the result, is used to test for success in order to have - * better generated assembly. - */ -static inline void -__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *)) -{ - int __ex_flag, __res, __orig; - - __asm__ ( - - "ldrex %0, [%3] \n\t" - "add %1, %0, #1 \n\t" - "strex %2, %1, [%3] " - - : "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag) - : "r" (&(count)->counter) - : "cc","memory" ); - - __orig |= __ex_flag; - if (unlikely(__orig != 0)) - fail_fn(count); -} - -/* - * If the unlock was done on a contended lock, or if the unlock simply fails - * then the mutex remains locked. - */ -#define __mutex_slowpath_needs_to_unlock() 1 - -/* - * For __mutex_fastpath_trylock we use another construct which could be - * described as a "single value cmpxchg". - * - * This provides the needed trylock semantics like cmpxchg would, but it is - * lighter and less generic than a true cmpxchg implementation. - */ -static inline int -__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) -{ - int __ex_flag, __res, __orig; - - __asm__ ( - - "1: ldrex %0, [%3] \n\t" - "subs %1, %0, #1 \n\t" - "strexeq %2, %1, [%3] \n\t" - "movlt %0, #0 \n\t" - "cmpeq %2, #0 \n\t" - "bgt 1b " - - : "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag) - : "r" (&count->counter) - : "cc", "memory" ); - - return __orig; -} - -#endif +#include #endif -- GitLab From 1c7eb28096b50831697a9cf6f8bf1af0e5b234bc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 2 Oct 2012 10:35:08 -0700 Subject: [PATCH 0572/1799] Linux 3.4.12 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 22345c016221..bcf5bc455a94 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 11 +SUBLEVEL = 12 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 9316bed3701438b79644e80cc4dd4903a40c756b Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 17 Sep 2012 22:23:30 +0200 Subject: [PATCH 0573/1799] vfs: dcache: fix deadlock in tree traversal commit 8110e16d42d587997bcaee0c864179e6d93603fe upstream. IBM reported a deadlock in select_parent(). This was found to be caused by taking rename_lock when already locked when restarting the tree traversal. There are two cases when the traversal needs to be restarted: 1) concurrent d_move(); this can only happen when not already locked, since taking rename_lock protects against concurrent d_move(). 2) racing with final d_put() on child just at the moment of ascending to parent; rename_lock doesn't protect against this rare race, so it can happen when already locked. Because of case 2, we need to be able to handle restarting the traversal when rename_lock is already held. This patch fixes all three callers of try_to_ascend(). IBM reported that the deadlock is gone with this patch. [ I rewrote the patch to be smaller and just do the "goto again" if the lock was already held, but credit goes to Miklos for the real work. - Linus ] Signed-off-by: Miklos Szeredi Cc: Al Viro Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/dcache.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/dcache.c b/fs/dcache.c index 10fab2666274..f104945dcc7d 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1116,6 +1116,8 @@ int have_submounts(struct dentry *parent) return 1; rename_retry: + if (locked) + goto again; locked = 1; write_seqlock(&rename_lock); goto again; @@ -1218,6 +1220,8 @@ static int select_parent(struct dentry *parent, struct list_head *dispose) rename_retry: if (found) return found; + if (locked) + goto again; locked = 1; write_seqlock(&rename_lock); goto again; @@ -2963,6 +2967,8 @@ void d_genocide(struct dentry *root) return; rename_retry: + if (locked) + goto again; locked = 1; write_seqlock(&rename_lock); goto again; -- GitLab From f9954ca80cc595852db6e913e65808819b9dc413 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Wed, 26 Sep 2012 23:45:42 +0100 Subject: [PATCH 0574/1799] dm: handle requests beyond end of device instead of using BUG_ON commit ba1cbad93dd47223b1f3b8edd50dd9ef2abcb2ed upstream. The access beyond the end of device BUG_ON that was introduced to dm_request_fn via commit 29e4013de7ad950280e4b2208 ("dm: implement REQ_FLUSH/FUA support for request-based dm") was an overly drastic (but simple) response to this situation. I have received a report that this BUG_ON was hit and now think it would be better to use dm_kill_unmapped_request() to fail the clone and original request with -EIO. map_request() will assign the valid target returned by dm_table_find_target to tio->ti. But when the target isn't valid tio->ti is never assigned (because map_request isn't called); so add a check for tio->ti != NULL to dm_done(). Reported-by: Mike Christie Signed-off-by: Mike Snitzer Signed-off-by: Jun'ichi Nomura Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm.c | 56 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index e24143cc2040..9ff3019790d7 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -865,10 +865,14 @@ static void dm_done(struct request *clone, int error, bool mapped) { int r = error; struct dm_rq_target_io *tio = clone->end_io_data; - dm_request_endio_fn rq_end_io = tio->ti->type->rq_end_io; + dm_request_endio_fn rq_end_io = NULL; - if (mapped && rq_end_io) - r = rq_end_io(tio->ti, clone, error, &tio->info); + if (tio->ti) { + rq_end_io = tio->ti->type->rq_end_io; + + if (mapped && rq_end_io) + r = rq_end_io(tio->ti, clone, error, &tio->info); + } if (r <= 0) /* The target wants to complete the I/O */ @@ -1566,15 +1570,6 @@ static int map_request(struct dm_target *ti, struct request *clone, int r, requeued = 0; struct dm_rq_target_io *tio = clone->end_io_data; - /* - * Hold the md reference here for the in-flight I/O. - * We can't rely on the reference count by device opener, - * because the device may be closed during the request completion - * when all bios are completed. - * See the comment in rq_completed() too. - */ - dm_get(md); - tio->ti = ti; r = ti->type->map_rq(ti, clone, &tio->info); switch (r) { @@ -1606,6 +1601,26 @@ static int map_request(struct dm_target *ti, struct request *clone, return requeued; } +static struct request *dm_start_request(struct mapped_device *md, struct request *orig) +{ + struct request *clone; + + blk_start_request(orig); + clone = orig->special; + atomic_inc(&md->pending[rq_data_dir(clone)]); + + /* + * Hold the md reference here for the in-flight I/O. + * We can't rely on the reference count by device opener, + * because the device may be closed during the request completion + * when all bios are completed. + * See the comment in rq_completed() too. + */ + dm_get(md); + + return clone; +} + /* * q->request_fn for request-based dm. * Called with the queue lock held. @@ -1635,14 +1650,21 @@ static void dm_request_fn(struct request_queue *q) pos = blk_rq_pos(rq); ti = dm_table_find_target(map, pos); - BUG_ON(!dm_target_is_valid(ti)); + if (!dm_target_is_valid(ti)) { + /* + * Must perform setup, that dm_done() requires, + * before calling dm_kill_unmapped_request + */ + DMERR_LIMIT("request attempted access beyond the end of device"); + clone = dm_start_request(md, rq); + dm_kill_unmapped_request(clone, -EIO); + continue; + } if (ti->type->busy && ti->type->busy(ti)) goto delay_and_out; - blk_start_request(rq); - clone = rq->special; - atomic_inc(&md->pending[rq_data_dir(clone)]); + clone = dm_start_request(md, rq); spin_unlock(q->queue_lock); if (map_request(ti, clone, md)) @@ -1662,8 +1684,6 @@ static void dm_request_fn(struct request_queue *q) blk_delay_queue(q, HZ / 10); out: dm_table_put(map); - - return; } int dm_underlying_device_busy(struct request_queue *q) -- GitLab From 7d77f4776e3fc8770f90244f1f5d1c9181b834c7 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Wed, 26 Sep 2012 23:45:43 +0100 Subject: [PATCH 0575/1799] dm table: clear add_random unless all devices have it set commit c3c4555edd10dbc0b388a0125b9c50de5e79af05 upstream. Always clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not have it set. Otherwise devices with predictable characteristics may contribute entropy. QUEUE_FLAG_ADD_RANDOM specifies whether or not queue IO timings contribute to the random pool. For bio-based targets this flag is always 0 because such devices have no real queue. For request-based devices this flag was always set to 1 by default. Now set it according to the flags on underlying devices. If there is at least one device which should not contribute, set the flag to zero: If a device, such as fast SSD storage, is not suitable for supplying entropy, a request-based queue stacked over it will not be either. Because the checking logic is exactly same as for the rotational flag, share the iteration function with device_is_nonrot(). Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-table.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 2e227fbf1622..f220a695a4b1 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1351,17 +1351,25 @@ static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev, return q && blk_queue_nonrot(q); } -static bool dm_table_is_nonrot(struct dm_table *t) +static int device_is_not_random(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) +{ + struct request_queue *q = bdev_get_queue(dev->bdev); + + return q && !blk_queue_add_random(q); +} + +static bool dm_table_all_devices_attribute(struct dm_table *t, + iterate_devices_callout_fn func) { struct dm_target *ti; unsigned i = 0; - /* Ensure that all underlying device are non-rotational. */ while (i < dm_table_get_num_targets(t)) { ti = dm_table_get_target(t, i++); if (!ti->type->iterate_devices || - !ti->type->iterate_devices(ti, device_is_nonrot, NULL)) + !ti->type->iterate_devices(ti, func, NULL)) return 0; } @@ -1393,13 +1401,23 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, if (!dm_table_discard_zeroes_data(t)) q->limits.discard_zeroes_data = 0; - if (dm_table_is_nonrot(t)) + /* Ensure that all underlying devices are non-rotational. */ + if (dm_table_all_devices_attribute(t, device_is_nonrot)) queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); else queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q); dm_table_set_integrity(t); + /* + * Determine whether or not this queue's I/O timings contribute + * to the entropy pool, Only request-based targets use this. + * Clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not + * have it set. + */ + if (blk_queue_add_random(q) && dm_table_all_devices_attribute(t, device_is_not_random)) + queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, q); + /* * QUEUE_FLAG_STACKABLE must be set after all queue settings are * visible to other CPUs because, once the flag is set, incoming bios -- GitLab From c0b50b292c41e0a1c6a1ef6df665fe7fb8eac2e1 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 26 Sep 2012 23:45:48 +0100 Subject: [PATCH 0576/1799] dm verity: fix overflow check commit 1d55f6bcc0331d744cd5b56c4ee79e3809438161 upstream. This patch fixes sector_t overflow checking in dm-verity. Without this patch, the code checks for overflow only if sector_t is smaller than long long, not if sector_t and long long have the same size. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-verity.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index fa365d39b612..68bf5c37c3fe 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -718,8 +718,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) v->hash_dev_block_bits = ffs(num) - 1; if (sscanf(argv[5], "%llu%c", &num_ll, &dummy) != 1 || - num_ll << (v->data_dev_block_bits - SECTOR_SHIFT) != - (sector_t)num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) { + (sector_t)(num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) + >> (v->data_dev_block_bits - SECTOR_SHIFT) != num_ll) { ti->error = "Invalid data blocks"; r = -EINVAL; goto bad; @@ -733,8 +733,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) } if (sscanf(argv[6], "%llu%c", &num_ll, &dummy) != 1 || - num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT) != - (sector_t)num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT)) { + (sector_t)(num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT)) + >> (v->hash_dev_block_bits - SECTOR_SHIFT) != num_ll) { ti->error = "Invalid hash start"; r = -EINVAL; goto bad; -- GitLab From 47c8e86e3869d7b7d159b069ad80cc621c2b1199 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 19 Aug 2012 21:54:58 +0200 Subject: [PATCH 0577/1799] usb: gadget: dummy_hcd: fixup error probe path commit 1b68a4ca2d038addb7314211d122fb6d7002b38b upstream. If USB2 host controller probes fine but USB3 does not then we don't remove the USB controller properly and lock up the system while the HUB code will try to enumerate the USB2 controller and access memory which is no longer available in case the dummy_hcd was compiled as a module. This is a problem since 448b6eb1 ("USB: Make sure to fetch the BOS desc for roothubs.) if used in USB3 mode because dummy does not provide this descriptor and explodes later. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/dummy_hcd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 170cbe89d9f8..2d277a2bc335 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -2505,10 +2505,8 @@ static int dummy_hcd_probe(struct platform_device *pdev) hs_hcd->has_tt = 1; retval = usb_add_hcd(hs_hcd, 0, 0); - if (retval != 0) { - usb_put_hcd(hs_hcd); - return retval; - } + if (retval) + goto put_usb2_hcd; if (mod_data.is_super_speed) { ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev, @@ -2527,6 +2525,8 @@ static int dummy_hcd_probe(struct platform_device *pdev) put_usb3_hcd: usb_put_hcd(ss_hcd); dealloc_usb2_hcd: + usb_remove_hcd(hs_hcd); +put_usb2_hcd: usb_put_hcd(hs_hcd); the_controller.hs_hcd = the_controller.ss_hcd = NULL; return retval; -- GitLab From 58bd65bfa47cf7dec02c8a1e2201dad0003acfb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 19 Sep 2012 22:02:12 +0200 Subject: [PATCH 0578/1799] USB: option: blacklist QMI interface on ZTE MF683 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 160c9425ac52cb30502be2d9c5e848cec91bb115 upstream. Interface #5 on ZTE MF683 is a QMI/wwan interface. Signed-off-by: Bjørn Mork Cc: Shawn J. Goff Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index a49099da93e3..57de73462f0d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -870,7 +870,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) }, -- GitLab From e59f498dc3f7679f236b2aec4a6c23173de78a65 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Sun, 23 Sep 2012 09:57:25 +0200 Subject: [PATCH 0579/1799] USB: ftdi_sio: add TIAO USB Multi-Protocol Adapter (TUMPA) support commit 54575b05af36959dfb6a49a3e9ca0c2b456b7126 upstream. TIAO/DIYGADGET USB Multi-Protocol Adapter (TUMPA) is an FTDI FT2232H based device which provides an easily accessible JTAG, SPI, I2C, serial breakout. http://www.diygadget.com/tiao-usb-multi-protocol-adapter-jtag-spi-i2c-serial.html http://www.tiaowiki.com/w/TIAO_USB_Multi_Protocol_Adapter_User%27s_Manual FTDI FT2232H provides two serial channels (A and B), but on the TUMPA channel A is dedicated to JTAG/SPI while channel B can be used for UART/RS-232: use the ftdi_jtag_quirk to expose only channel B as a usb-serial interface to userspace. Signed-off-by: Antonio Ospite Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio_ids.h | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 4d2b7d31fc67..25bb93503963 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -584,6 +584,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, /* * ELV devices: */ diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 41fe5826100c..57c12ef6625e 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -517,6 +517,11 @@ */ #define FTDI_TAVIR_STK500_PID 0xFA33 /* STK500 AVR programmer */ +/* + * TIAO product ids (FTDI_VID) + * http://www.tiaowiki.com/w/Main_Page + */ +#define FTDI_TIAO_UMPA_PID 0x8a98 /* TIAO/DIYGADGET USB Multi-Protocol Adapter */ /********************************/ -- GitLab From 28939e9a0972df8eff635a92c0c0a62efe97d9a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 19 Sep 2012 22:02:03 +0200 Subject: [PATCH 0580/1799] USB: qcaux: add Pantech vendor class match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c638eb2872b3af079501e7ee44cbb8a5cce9b4b5 upstream. The three Pantech devices UML190 (106c:3716), UML290 (106c:3718) and P4200 (106c:3721) all use the same subclasses to identify vendor specific functions. Replace the existing device specific entries with generic vendor matching, adding support for the P4200. Signed-off-by: Bjørn Mork Cc: Thomas Schäfer Acked-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcaux.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index 966245680f55..b223381da32a 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -36,8 +36,6 @@ #define UTSTARCOM_PRODUCT_UM175_V1 0x3712 #define UTSTARCOM_PRODUCT_UM175_V2 0x3714 #define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715 -#define PANTECH_PRODUCT_UML190_VZW 0x3716 -#define PANTECH_PRODUCT_UML290_VZW 0x3718 /* CMOTECH devices */ #define CMOTECH_VENDOR_ID 0x16d8 @@ -68,11 +66,9 @@ static struct usb_device_id id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) }, /* NMEA */ - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) }, /* WMC */ - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, /* DIAG */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) }, /* NMEA */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) }, /* WMC */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) }, /* DIAG */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); -- GitLab From 1d64560a29d149803a119527ad6b3d80b83a85a8 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Sat, 22 Sep 2012 18:11:19 +0530 Subject: [PATCH 0581/1799] usb: host: xhci: Fix Null pointer dereferencing with 71c731a for non-x86 systems commit 457a73d346187c2cc5d599072f38676f18f130e0 upstream. In 71c731a: usb: host: xhci: Fix Compliance Mode on SN65LVPE502CP Hardware when extracting DMI strings (vendor or product_name) to mark them as quirk we may get NULL pointer in case of non-x86 systems which won't define CONFIG_DMI. Hence susbsequent strstr() calls crash while driver probing. So, returning 'false' here in case we get a NULL vendor or product_name. This is tested with ARM (exynos) system. This patch should be backported to stable kernels as old as 3.6, that contain the commit 71c731a296f1b08a3724bd1b514b64f1bda87a23 "usb: host: xhci: Fix Compliance Mode on SN65LVPE502CP Hardware" Signed-off-by: Vivek Gautam Signed-off-by: Sarah Sharp Reported-by: Sebastian Gottschall (DD-WRT) Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 6467d79d760d..495c7a3a9971 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -470,6 +470,8 @@ static bool compliance_mode_recovery_timer_quirk_check(void) dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR); + if (!dmi_product_name || !dmi_sys_vendor) + return false; if (!(strstr(dmi_sys_vendor, "Hewlett-Packard"))) return false; -- GitLab From f7d978ef5d1cdbbb7bd7dba5fb995d56b7640b37 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 16 Sep 2012 04:18:50 +0100 Subject: [PATCH 0582/1799] staging: speakup_soft: Fix reading of init string commit 40fe4f89671fb3c7ded94190fb267402a38b0261 upstream. softsynth_read() reads a character at a time from the init string; when it finds the null terminator it sets the initialized flag but then repeats the last character. Additionally, if the read() buffer is not big enough for the init string, the next read() will start reading from the beginning again. So the caller may never progress to reading anything else. Replace the simple initialized flag with the current position in the init string, carried over between calls. Switch to reading real data once this reaches the null terminator. (This assumes that the length of the init string can't change, which seems to be the case. Really, the string and position belong together in a per-file private struct.) Tested-by: Samuel Thibault Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/speakup_soft.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c index 42cdafeea35e..b5130c8bcb64 100644 --- a/drivers/staging/speakup/speakup_soft.c +++ b/drivers/staging/speakup/speakup_soft.c @@ -40,7 +40,7 @@ static int softsynth_is_alive(struct spk_synth *synth); static unsigned char get_index(void); static struct miscdevice synth_device; -static int initialized; +static int init_pos; static int misc_registered; static struct var_t vars[] = { @@ -194,7 +194,7 @@ static int softsynth_close(struct inode *inode, struct file *fp) unsigned long flags; spk_lock(flags); synth_soft.alive = 0; - initialized = 0; + init_pos = 0; spk_unlock(flags); /* Make sure we let applications go before leaving */ speakup_start_ttys(); @@ -239,13 +239,8 @@ static ssize_t softsynth_read(struct file *fp, char *buf, size_t count, ch = '\x18'; } else if (synth_buffer_empty()) { break; - } else if (!initialized) { - if (*init) { - ch = *init; - init++; - } else { - initialized = 1; - } + } else if (init[init_pos]) { + ch = init[init_pos++]; } else { ch = synth_buffer_getc(); } -- GitLab From 0f2c427a4f4a994526bea7ce3855284fc5a7940a Mon Sep 17 00:00:00 2001 From: Christopher Brannon Date: Fri, 22 Jun 2012 08:16:34 -0500 Subject: [PATCH 0583/1799] tty: keyboard.c: Remove locking from vt_get_leds. commit 157a4b311c45c9aba75a990464d9680867dc8805 upstream. There are three call sites for this function, and all three are called within a keyboard handler. kbd_event_lock is already held within keyboard handlers, so attempting to lock it in vt_get_leds causes deadlock. Signed-off-by: Christopher Brannon Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/keyboard.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 3b0c4e32ed7b..a6d5d51fcbc5 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1053,13 +1053,10 @@ static int kbd_update_leds_helper(struct input_handle *handle, void *data) */ int vt_get_leds(int console, int flag) { - unsigned long flags; struct kbd_struct * kbd = kbd_table + console; int ret; - spin_lock_irqsave(&kbd_event_lock, flags); ret = vc_kbd_led(kbd, flag); - spin_unlock_irqrestore(&kbd_event_lock, flags); return ret; } -- GitLab From 28675586f391fc14960de13c63359b25542ddec4 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 26 Sep 2012 14:01:31 -0500 Subject: [PATCH 0584/1799] staging: r8712u: Do not queue cloned skb commit fa16e5ea25d7dd83f663f333e70713aa2fa5dffe upstream. Some post-3.4 kernels have a problem when a cloned skb is used in the RX path. This patch handles one such case for r8712u. The patch was suggested by Eric Dumazet. Signed-off-by: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index fa6dc9c09b3f..887a80709ab8 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -1126,6 +1126,9 @@ static void recv_tasklet(void *priv) recvbuf2recvframe(padapter, pskb); skb_reset_tail_pointer(pskb); pskb->len = 0; - skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); + if (!skb_cloned(pskb)) + skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); + else + consume_skb(pskb); } } -- GitLab From b5697de62b79060f59a5d7780aa4c16fdcfaa929 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 24 Sep 2012 17:20:52 +0100 Subject: [PATCH 0585/1799] staging: comedi: s626: don't dereference insn->data commit b655c2c4782ed3e2e71d2608154e295a3e860311 upstream. `s626_enc_insn_config()` is incorrectly dereferencing `insn->data` which is a pointer to user memory. It should be dereferencing the separate `data` parameter that points to a copy of the data in kernel memory. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/s626.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 23fc64b9988e..c72128f30f17 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -2370,7 +2370,7 @@ static int s626_enc_insn_config(struct comedi_device *dev, /* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */ k->SetMode(dev, k, Setup, TRUE); - Preload(dev, k, *(insn->data)); + Preload(dev, k, data[0]); k->PulseIndex(dev, k); SetLatchSource(dev, k, valueSrclatch); k->SetEnable(dev, k, (uint16_t) (enab != 0)); -- GitLab From 4483c56613f9ca0cff15d231975b240d3f3e8a10 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 27 Sep 2012 17:45:27 +0100 Subject: [PATCH 0586/1799] staging: comedi: jr3_pci: fix iomem dereference commit e1878957b4676a17cf398f7f5723b365e9a2ca48 upstream. Correct a direct dereference of I/O memory to use an appropriate I/O memory access function. Note that the pointer being dereferenced is not currently tagged with `__iomem` but I plan to correct that for 3.7. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/jr3_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 6a79ba10630d..d7e63419e617 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -905,7 +905,7 @@ static int jr3_pci_attach(struct comedi_device *dev, } /* Reset DSP card */ - devpriv->iobase->channel[0].reset = 0; + writel(0, &devpriv->iobase->channel[0].reset); result = comedi_load_firmware(dev, "jr3pci.idm", jr3_download_firmware); dev_dbg(dev->hw_dev, "Firmare load %d\n", result); -- GitLab From 19dcf415184e1ef6d9641d76e3248d3b2677b3df Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 18 Sep 2012 19:46:58 +0100 Subject: [PATCH 0587/1799] staging: comedi: don't dereference user memory for INSN_INTTRIG commit 5d06e3df280bd230e2eadc16372e62818c63e894 upstream. `parse_insn()` is dereferencing the user-space pointer `insn->data` directly when handling the `INSN_INTTRIG` comedi instruction. It shouldn't be using `insn->data` at all; it should be using the separate `data` pointer passed to the function. Fix it. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index a796964bfff4..28811890d703 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -843,7 +843,7 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, ret = -EAGAIN; break; } - ret = s->async->inttrig(dev, s, insn->data[0]); + ret = s->async->inttrig(dev, s, data[0]); if (ret >= 0) ret = 1; break; -- GitLab From f810716cd61810278caee8eefed22e8706e49125 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 19 Sep 2012 19:37:39 +0100 Subject: [PATCH 0588/1799] staging: comedi: fix memory leak for saved channel list commit c8cad4c89ee3b15935c532210ae6ebb5c0a2734d upstream. When `do_cmd_ioctl()` allocates memory for the kernel copy of a channel list, it frees any previously allocated channel list in `async->cmd.chanlist` and replaces it with the new one. However, if the device is ever removed (or "detached") the cleanup code in `cleanup_device()` in "drivers.c" does not free this memory so it is lost. A sensible place to free the kernel copy of the channel list is in `do_become_nonbusy()` as at that point the comedi asynchronous command associated with the channel list is no longer valid. Free the channel list in `do_become_nonbusy()` instead of `do_cmd_ioctl()` and clear the pointer to prevent it being freed more than once. Note that `cleanup_device()` could be called at an inappropriate time while the comedi device is open, but that's a separate bug not related to this this patch. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 28811890d703..b719460c4ecf 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1088,7 +1088,6 @@ static int do_cmd_ioctl(struct comedi_device *dev, goto cleanup; } - kfree(async->cmd.chanlist); async->cmd = user_cmd; async->cmd.data = NULL; /* load channel/gain list */ @@ -1833,6 +1832,8 @@ void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s) if (async) { comedi_reset_async_buf(async); async->inttrig = NULL; + kfree(async->cmd.chanlist); + async->cmd.chanlist = NULL; } else { printk(KERN_ERR "BUG: (?) do_become_nonbusy called with async=0\n"); -- GitLab From e2a43abf3d9c6a3828d9a02c3de0d8bf16bd4b90 Mon Sep 17 00:00:00 2001 From: Stanislav Kozina Date: Thu, 16 Aug 2012 12:01:47 +0100 Subject: [PATCH 0589/1799] Remove BUG_ON from n_tty_read() commit e9490e93c1978b6669f3e993caa3189be13ce459 upstream. Change the BUG_ON to WARN_ON and return in case of tty->read_buf==NULL. We want to track a couple of long standing reports of this but at the same time we can avoid killing the box. Signed-off-by: Stanislav Kozina Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 94b6eda87afd..2303a02e9dc5 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1727,7 +1727,8 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, do_it_again: - BUG_ON(!tty->read_buf); + if (WARN_ON(!tty->read_buf)) + return -EAGAIN; c = job_control(tty, file); if (c < 0) -- GitLab From 804f6a4a4745ce54f3afa76b3d2270b385f565f8 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 7 Aug 2012 21:47:39 +0200 Subject: [PATCH 0590/1799] TTY: ttyprintk, don't touch behind tty->write_buf commit ee8b593affdf893012e57f4c54a21984d1b0d92e upstream. If a user provides a buffer larger than a tty->write_buf chunk and passes '\r' at the end of the buffer, we touch an out-of-bound memory. Add a check there to prevent this. Signed-off-by: Jiri Slaby Cc: Samo Pogacnik Signed-off-by: Greg Kroah-Hartman --- drivers/char/ttyprintk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index 46b77ede84c0..a7c6d6a07d3c 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -67,7 +67,7 @@ static int tpk_printk(const unsigned char *buf, int count) tmp[tpk_curr + 1] = '\0'; printk(KERN_INFO "%s%s", tpk_tag, tmp); tpk_curr = 0; - if (buf[i + 1] == '\n') + if ((i + 1) < count && buf[i + 1] == '\n') i++; break; case '\n': -- GitLab From bba5a67bba4c56ab0ce632d7a3e1a651d9162b9e Mon Sep 17 00:00:00 2001 From: Vikram Pandita Date: Thu, 6 Sep 2012 15:45:37 +0300 Subject: [PATCH 0591/1799] serial: omap: fix software flow control commit 957ee7270d632245b43f6feb0e70d9a5e9ea6cf6 upstream. Software flow control register bits were not defined correctly. Also clarify the IXON and IXOFF logic to reflect what userspace wants. Tested-by: Shubhrajyoti D Signed-off-by: Vikram Pandita Signed-off-by: Shubhrajyoti D Acked-by: Tony Lindgren Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-omap/include/plat/omap-serial.h | 4 ++-- drivers/tty/serial/omap-serial.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index 9ff444469f3d..c369c9d242a8 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -42,10 +42,10 @@ #define OMAP_UART_WER_MOD_WKUP 0X7F /* Enable XON/XOFF flow control on output */ -#define OMAP_UART_SW_TX 0x04 +#define OMAP_UART_SW_TX 0x8 /* Enable XON/XOFF flow control on input */ -#define OMAP_UART_SW_RX 0x04 +#define OMAP_UART_SW_RX 0x2 #define OMAP_UART_SYSC_RESET 0X07 #define OMAP_UART_TCR_TRIG 0X0F diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index d00b38eb268e..6189923eb193 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -649,19 +649,19 @@ serial_omap_configure_xonxoff /* * IXON Flag: - * Enable XON/XOFF flow control on output. - * Transmit XON1, XOFF1 + * Flow control for OMAP.TX + * OMAP.RX should listen for XON/XOFF */ if (termios->c_iflag & IXON) - up->efr |= OMAP_UART_SW_TX; + up->efr |= OMAP_UART_SW_RX; /* * IXOFF Flag: - * Enable XON/XOFF flow control on input. - * Receiver compares XON1, XOFF1. + * Flow control for OMAP.RX + * OMAP.TX should send XON/XOFF */ if (termios->c_iflag & IXOFF) - up->efr |= OMAP_UART_SW_RX; + up->efr |= OMAP_UART_SW_TX; serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); -- GitLab From c5500c74ff1414578161b796557b382d5cbaf024 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 26 Sep 2012 17:21:36 +0200 Subject: [PATCH 0592/1799] serial: pl011: handle corruption at high clock speeds commit c5dd553b9fd069892c9e2de734f4f604e280fa7a upstream. This works around a few glitches in the ST version of the PL011 serial driver when using very high baud rates, as we do in the Ux500: 3, 3.25, 4 and 4.05 Mbps. Problem Observed/rootcause: When using high baud-rates, and the baudrate*8 is getting close to the provided clock frequency (so a division factor close to 1), when using bursts of characters (so they are abutted), then it seems as if there is not enough time to detect the beginning of the start-bit which is a timing reference for the entire character, and thus the sampling moment of character bits is moving towards the end of each bit, instead of the middle. Fix: Increase slightly the RX baud rate of the UART above the theoretical baudrate by 5%. This will definitely give more margin time to the UART_RX to correctly sample the data at the middle of the bit period. Also fix the ages old copy-paste error in the very stressed comment, it's referencing the registers used in the PL010 driver rather than the PL011 ones. Signed-off-by: Guillaume Jaunet Signed-off-by: Christophe Arnal Signed-off-by: Matthias Locher Signed-off-by: Rajanikanth HV Cc: Bibek Basu Cc: Par-Gunnar Hjalmdahl Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 3d569cd68f58..b69356c227c4 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1654,13 +1654,26 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, old_cr &= ~ST_UART011_CR_OVSFACT; } + /* + * Workaround for the ST Micro oversampling variants to + * increase the bitrate slightly, by lowering the divisor, + * to avoid delayed sampling of start bit at high speeds, + * else we see data corruption. + */ + if (uap->vendor->oversampling) { + if ((baud >= 3000000) && (baud < 3250000) && (quot > 1)) + quot -= 1; + else if ((baud > 3250000) && (quot > 2)) + quot -= 2; + } /* Set baud rate */ writew(quot & 0x3f, port->membase + UART011_FBRD); writew(quot >> 6, port->membase + UART011_IBRD); /* * ----------v----------v----------v----------v----- - * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L + * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER + * UART011_FBRD & UART011_IBRD. * ----------^----------^----------^----------^----- */ writew(lcr_h, port->membase + uap->lcrh_rx); -- GitLab From 268b7d491c88845b410b2dfc84af54075db35c4d Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Fri, 21 Sep 2012 21:04:34 -0300 Subject: [PATCH 0593/1799] serial: set correct baud_base for EXSYS EX-41092 Dual 16950 commit 26e8220adb0aec43b7acafa0f1431760eee28522 upstream. Apparently the same card model has two IDs, so this patch complements the commit 39aced68d664291db3324d0fcf0985ab5626aac2 adding the missing one. Signed-off-by: Flavio Leitner Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 9 +++++++-- include/linux/pci_ids.h | 1 - 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 3614973c9990..40747feed34c 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1125,6 +1125,8 @@ pci_xr17c154_setup(struct serial_private *priv, #define PCI_SUBDEVICE_ID_OCTPRO422 0x0208 #define PCI_SUBDEVICE_ID_POCTAL232 0x0308 #define PCI_SUBDEVICE_ID_POCTAL422 0x0408 +#define PCI_SUBDEVICE_ID_SIIG_DUAL_00 0x2500 +#define PCI_SUBDEVICE_ID_SIIG_DUAL_30 0x2530 #define PCI_VENDOR_ID_ADVANTECH 0x13fe #define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66 #define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620 @@ -3187,8 +3189,11 @@ static struct pci_device_id serial_pci_tbl[] = { * For now just used the hex ID 0x950a. */ { PCI_VENDOR_ID_OXSEMI, 0x950a, - PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0, - pbn_b0_2_115200 }, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_00, + 0, 0, pbn_b0_2_115200 }, + { PCI_VENDOR_ID_OXSEMI, 0x950a, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_30, + 0, 0, pbn_b0_2_115200 }, { PCI_VENDOR_ID_OXSEMI, 0x950a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_2_1130000 }, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 19ca550ff665..bf7934f4268f 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1846,7 +1846,6 @@ #define PCI_DEVICE_ID_SIIG_8S_20x_650 0x2081 #define PCI_DEVICE_ID_SIIG_8S_20x_850 0x2082 #define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL 0x2050 -#define PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL 0x2530 #define PCI_VENDOR_ID_RADISYS 0x1331 -- GitLab From 37b6d804b3b5e2a255d2182ce00e1f25c568d7e9 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 5 Sep 2012 14:37:35 -0700 Subject: [PATCH 0594/1799] tools/hv: Fix file handle leak commit d5ab482799e7c4c4b7c0aa67e8710dce28115d03 upstream. Match up each fopen() with an fclose(). Signed-off-by: Ben Hutchings Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- tools/hv/hv_kvp_daemon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index d9834b362943..a08213b2250b 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -144,7 +144,7 @@ static void kvp_update_file(int pool) sizeof(struct kvp_record), kvp_file_info[pool].num_records, filep); - fflush(filep); + fclose(filep); kvp_release_lock(pool); } @@ -191,6 +191,7 @@ static void kvp_update_mem_state(int pool) kvp_file_info[pool].records = record; kvp_file_info[pool].num_records = records_read; + fclose(filep); kvp_release_lock(pool); } static int kvp_file_init(void) -- GitLab From de5d66e635460e27d678df99f9cb97e263d3bbe7 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 5 Sep 2012 14:37:36 -0700 Subject: [PATCH 0595/1799] tools/hv: Fix exit() error code commit 6bb22fea25624ab593eee376fa5fb82d1b13f45a upstream. Linux native exit codes are 8-bit unsigned values. exit(-1) results in an exit code of 255, which is usually reserved for shells reporting 'command not found'. Use the portable value EXIT_FAILURE. (Not that this matters much for a daemon.) Signed-off-by: Ben Hutchings Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- tools/hv/hv_kvp_daemon.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index a08213b2250b..edab6e90038a 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -106,7 +106,7 @@ static void kvp_acquire_lock(int pool) if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) { syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool); - exit(-1); + exit(EXIT_FAILURE); } } @@ -118,7 +118,7 @@ static void kvp_release_lock(int pool) if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) { perror("fcntl"); syslog(LOG_ERR, "Failed to release the lock pool: %d", pool); - exit(-1); + exit(EXIT_FAILURE); } } @@ -137,7 +137,7 @@ static void kvp_update_file(int pool) if (!filep) { kvp_release_lock(pool); syslog(LOG_ERR, "Failed to open file, pool: %d", pool); - exit(-1); + exit(EXIT_FAILURE); } bytes_written = fwrite(kvp_file_info[pool].records, @@ -163,7 +163,7 @@ static void kvp_update_mem_state(int pool) if (!filep) { kvp_release_lock(pool); syslog(LOG_ERR, "Failed to open file, pool: %d", pool); - exit(-1); + exit(EXIT_FAILURE); } while (!feof(filep)) { readp = &record[records_read]; @@ -180,7 +180,7 @@ static void kvp_update_mem_state(int pool) if (record == NULL) { syslog(LOG_ERR, "malloc failed"); - exit(-1); + exit(EXIT_FAILURE); } continue; } @@ -209,7 +209,7 @@ static int kvp_file_init(void) if (access("/var/opt/hyperv", F_OK)) { if (mkdir("/var/opt/hyperv", S_IRUSR | S_IWUSR | S_IROTH)) { syslog(LOG_ERR, " Failed to create /var/opt/hyperv"); - exit(-1); + exit(EXIT_FAILURE); } } @@ -658,13 +658,13 @@ int main(void) if (kvp_file_init()) { syslog(LOG_ERR, "Failed to initialize the pools"); - exit(-1); + exit(EXIT_FAILURE); } fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (fd < 0) { syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); - exit(-1); + exit(EXIT_FAILURE); } addr.nl_family = AF_NETLINK; addr.nl_pad = 0; @@ -676,7 +676,7 @@ int main(void) if (error < 0) { syslog(LOG_ERR, "bind failed; error:%d", error); close(fd); - exit(-1); + exit(EXIT_FAILURE); } sock_opt = addr.nl_groups; setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt)); @@ -696,7 +696,7 @@ int main(void) if (len < 0) { syslog(LOG_ERR, "netlink_send failed; error:%d", len); close(fd); - exit(-1); + exit(EXIT_FAILURE); } pfd.fd = fd; @@ -864,7 +864,7 @@ int main(void) len = netlink_send(fd, incoming_cn_msg); if (len < 0) { syslog(LOG_ERR, "net_link send failed; error:%d", len); - exit(-1); + exit(EXIT_FAILURE); } } -- GitLab From 1eafb0280d1275629da54c350c7d9842f7785577 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 5 Sep 2012 14:37:37 -0700 Subject: [PATCH 0596/1799] tools/hv: Check for read/write errors commit 436473bc2173499ae274d0f50111d1e355006caf upstream. hv_kvp_daemon currently does not check whether fread() or fwrite() succeed. Add the necessary checks. Also, remove the incorrect use of feof() before fread(). Signed-off-by: Ben Hutchings Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- tools/hv/hv_kvp_daemon.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index edab6e90038a..2984ffb7bac7 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -144,7 +144,12 @@ static void kvp_update_file(int pool) sizeof(struct kvp_record), kvp_file_info[pool].num_records, filep); - fclose(filep); + if (ferror(filep) || fclose(filep)) { + kvp_release_lock(pool); + syslog(LOG_ERR, "Failed to write file, pool: %d", pool); + exit(EXIT_FAILURE); + } + kvp_release_lock(pool); } @@ -165,12 +170,17 @@ static void kvp_update_mem_state(int pool) syslog(LOG_ERR, "Failed to open file, pool: %d", pool); exit(EXIT_FAILURE); } - while (!feof(filep)) { + for (;;) { readp = &record[records_read]; records_read += fread(readp, sizeof(struct kvp_record), ENTRIES_PER_BLOCK * num_blocks, filep); + if (ferror(filep)) { + syslog(LOG_ERR, "Failed to read file, pool: %d", pool); + exit(EXIT_FAILURE); + } + if (!feof(filep)) { /* * We have more data to read. @@ -233,12 +243,18 @@ static int kvp_file_init(void) fclose(filep); return 1; } - while (!feof(filep)) { + for (;;) { readp = &record[records_read]; records_read += fread(readp, sizeof(struct kvp_record), ENTRIES_PER_BLOCK, filep); + if (ferror(filep)) { + syslog(LOG_ERR, "Failed to read file, pool: %d", + i); + exit(EXIT_FAILURE); + } + if (!feof(filep)) { /* * We have more data to read. -- GitLab From dc8276b241ad415b2602c4a7309e5b518bb09c32 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 26 Sep 2012 12:32:02 -0500 Subject: [PATCH 0597/1799] b43legacy: Fix crash on unload when firmware not available commit 2d838bb608e2d1f6cb4280e76748cb812dc822e7 upstream. When b43legacy is loaded without the firmware being available, a following unload generates a kernel NULL pointer dereference BUG as follows: [ 214.330789] BUG: unable to handle kernel NULL pointer dereference at 0000004c [ 214.330997] IP: [] drain_workqueue+0x15/0x170 [ 214.331179] *pde = 00000000 [ 214.331311] Oops: 0000 [#1] SMP [ 214.331471] Modules linked in: b43legacy(-) ssb pcmcia mac80211 cfg80211 af_packet mperf arc4 ppdev sr_mod cdrom sg shpchp yenta_socket pcmcia_rsrc pci_hotplug pcmcia_core battery parport_pc parport floppy container ac button edd autofs4 ohci_hcd ehci_hcd usbcore usb_common thermal processor scsi_dh_rdac scsi_dh_hp_sw scsi_dh_emc scsi_dh_alua scsi_dh fan thermal_sys hwmon ata_generic pata_ali libata [last unloaded: cfg80211] [ 214.333421] Pid: 3639, comm: modprobe Not tainted 3.6.0-rc6-wl+ #163 Source Technology VIC 9921/ALI Based Notebook [ 214.333580] EIP: 0060:[] EFLAGS: 00010246 CPU: 0 [ 214.333687] EIP is at drain_workqueue+0x15/0x170 [ 214.333788] EAX: c162ac40 EBX: cdfb8360 ECX: 0000002a EDX: 00002a2a [ 214.333890] ESI: 00000000 EDI: 00000000 EBP: cd767e7c ESP: cd767e5c [ 214.333957] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 [ 214.333957] CR0: 8005003b CR2: 0000004c CR3: 0c96a000 CR4: 00000090 [ 214.333957] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 214.333957] DR6: ffff0ff0 DR7: 00000400 [ 214.333957] Process modprobe (pid: 3639, ti=cd766000 task=cf802e90 task.ti=cd766000) [ 214.333957] Stack: [ 214.333957] 00000292 cd767e74 c12c5e09 00000296 00000296 cdfb8360 cdfb9220 00000000 [ 214.333957] cd767e90 c104c4fd cdfb8360 cdfb9220 cd682800 cd767ea4 d0c10184 cd682800 [ 214.333957] cd767ea4 cba31064 cd767eb8 d0867908 cba31064 d087e09c cd96f034 cd767ec4 [ 214.333957] Call Trace: [ 214.333957] [] ? skb_dequeue+0x49/0x60 [ 214.333957] [] destroy_workqueue+0xd/0x150 [ 214.333957] [] ieee80211_unregister_hw+0xc4/0x100 [mac80211] [ 214.333957] [] b43legacy_remove+0x78/0x80 [b43legacy] [ 214.333957] [] ssb_device_remove+0x1d/0x30 [ssb] [ 214.333957] [] __device_release_driver+0x5a/0xb0 [ 214.333957] [] driver_detach+0x87/0x90 [ 214.333957] [] bus_remove_driver+0x6c/0xe0 [ 214.333957] [] driver_unregister+0x40/0x70 [ 214.333957] [] ssb_driver_unregister+0xb/0x10 [ssb] [ 214.333957] [] b43legacy_exit+0xd/0xf [b43legacy] [ 214.333957] [] sys_delete_module+0x14e/0x2b0 [ 214.333957] [] ? vfs_write+0xf7/0x150 [ 214.333957] [] ? tty_write_lock+0x50/0x50 [ 214.333957] [] ? sys_write+0x38/0x70 [ 214.333957] [] syscall_call+0x7/0xb [ 214.333957] Code: bc 27 00 00 00 00 a1 74 61 56 c1 55 89 e5 e8 a3 fc ff ff 5d c3 90 55 89 e5 57 56 89 c6 53 b8 40 ac 62 c1 83 ec 14 e8 bb b7 34 00 <8b> 46 4c 8d 50 01 85 c0 89 56 4c 75 03 83 0e 40 80 05 40 ac 62 [ 214.333957] EIP: [] drain_workqueue+0x15/0x170 SS:ESP 0068:cd767e5c [ 214.333957] CR2: 000000000000004c [ 214.341110] ---[ end trace c7e90ec026d875a6 ]---Index: wireless-testing/drivers/net/wireless/b43legacy/main.c The problem is fixed by making certain that the ucode pointer is not NULL before deregistering the driver in mac80211. Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/b43legacy/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index a98db30b7acb..0f30c07e9198 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3892,6 +3892,8 @@ static void b43legacy_remove(struct ssb_device *dev) cancel_work_sync(&wl->firmware_load); B43legacy_WARN_ON(!wl); + if (!wldev->fw.ucode) + return; /* NULL if fw never loaded */ if (wl->current_dev == wldev) ieee80211_unregister_hw(wl->hw); -- GitLab From ed02004f896be60f6d5dc3af403999f56a3e6d37 Mon Sep 17 00:00:00 2001 From: Khalid Aziz Date: Mon, 10 Sep 2012 12:52:42 -0600 Subject: [PATCH 0598/1799] firmware: Add missing attributes to EFI variable attribute print out from sysfs commit 7083909023bbe29b3176e92d2d089def1aa7aa1e upstream. Some of the EFI variable attributes are missing from print out from /sys/firmware/efi/vars/*/attributes. This patch adds those in. It also updates code to use pre-defined constants for masking current value of attributes. Signed-off-by: Khalid Aziz Reviewed-by: Kees Cook Acked-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/efivars.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 47408e802ab6..d10c9873dd9a 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -435,12 +435,23 @@ efivar_attr_read(struct efivar_entry *entry, char *buf) if (status != EFI_SUCCESS) return -EIO; - if (var->Attributes & 0x1) + if (var->Attributes & EFI_VARIABLE_NON_VOLATILE) str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n"); - if (var->Attributes & 0x2) + if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n"); - if (var->Attributes & 0x4) + if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n"); + if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) + str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n"); + if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) + str += sprintf(str, + "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n"); + if (var->Attributes & + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) + str += sprintf(str, + "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n"); + if (var->Attributes & EFI_VARIABLE_APPEND_WRITE) + str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n"); return str - buf; } -- GitLab From 59b91d284b24d4ec17f917421b169fcb40805544 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 19 Sep 2012 16:27:26 -0700 Subject: [PATCH 0599/1799] xhci: Intel Panther Point BEI quirk. commit 80fab3b244a22e0ca539d2439bdda50e81e5666f upstream. When a device with an isochronous endpoint is behind a hub plugged into the Intel Panther Point xHCI host controller, and the driver submits multiple frames per URB, the xHCI driver will set the Block Event Interrupt (BEI) flag on all but the last TD for the URB. This causes the host controller to place an event on the event ring, but not send an interrupt. When the last TD for the URB completes, BEI is cleared, and we get an interrupt for the whole URB. However, under a Panther Point xHCI host controller, if the parent hub is unplugged when one or more events from transfers with BEI set are on the event ring, a port status change event is placed on the event ring, but no interrupt is generated. This means URBs stop completing, and the USB device disconnect is not noticed. Something like a USB headset will cause mplayer to hang when the device is disconnected. If another transfer is sent (such as running `sudo lsusb -v`), the next transfer event seems to "unstick" the event ring, the xHCI driver gets an interrupt, and the disconnect is reported to the USB core. The fix is not to use the BEI flag under the Panther Point xHCI host. This will impact power consumption and system responsiveness, because the xHCI driver will receive an interrupt for every frame in all isochronous URBs instead of once per URB. Intel chipset developers confirm that this bug will be hit if the BEI flag is used on any endpoint, not just ones that are behind a hub. This patch should be backported to kernels as old as 3.0, that contain the commit 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support EHCI/xHCI port switching." Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 1 + drivers/usb/host/xhci-ring.c | 4 +++- drivers/usb/host/xhci.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index f1527404617c..4211017b8892 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -99,6 +99,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) * PPT chipsets. */ xhci->quirks |= XHCI_SPURIOUS_REBOOT; + xhci->quirks |= XHCI_AVOID_BEI; } if (pdev->vendor == PCI_VENDOR_ID_ETRON && pdev->device == PCI_DEVICE_ID_ASROCK_P67) { diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 203ba315c72a..17383aa69248 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3400,7 +3400,9 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } else { td->last_trb = ep_ring->enqueue; field |= TRB_IOC; - if (xhci->hci_version == 0x100) { + if (xhci->hci_version == 0x100 && + !(xhci->quirks & + XHCI_AVOID_BEI)) { /* Set BEI bit except for the last td */ if (i < num_tds - 1) field |= TRB_BEI; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 6e77f3b5a7fb..eeeef474ce68 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1488,6 +1488,7 @@ struct xhci_hcd { #define XHCI_TRUST_TX_LENGTH (1 << 10) #define XHCI_SPURIOUS_REBOOT (1 << 13) #define XHCI_COMP_MODE_QUIRK (1 << 14) +#define XHCI_AVOID_BEI (1 << 15) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ -- GitLab From 1976fffe9dc839e9d25c903a65723600f7641a50 Mon Sep 17 00:00:00 2001 From: Elric Fu Date: Wed, 27 Jun 2012 16:30:57 +0800 Subject: [PATCH 0600/1799] xHCI: add cmd_ring_state commit c181bc5b5d5c79b71203cd10cef97f802fb6f9c1 upstream. Adding cmd_ring_state for command ring. It helps to verify the current command ring state for controlling the command ring operations. This patch should be backported to kernels as old as 3.0. The commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an assertion to check for virt_dev=0 bug." papers over the NULL pointer dereference that I now believe is related to a timed out Set Address command. This (and the four patches that follow it) contain the real fix that also allows VIA USB 3.0 hubs to consistently re-enumerate during the plug/unplug stress tests. Signed-off-by: Elric Fu Signed-off-by: Sarah Sharp Tested-by: Miroslav Sabljic Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 3 +++ drivers/usb/host/xhci.c | 6 ++++-- drivers/usb/host/xhci.h | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 17383aa69248..f98dfedbc64c 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -280,6 +280,9 @@ static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, /* Ring the host controller doorbell after placing a command on the ring */ void xhci_ring_cmd_db(struct xhci_hcd *xhci) { + if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING)) + return; + xhci_dbg(xhci, "// Ding dong!\n"); xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]); /* Flush PCI posted writes */ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 495c7a3a9971..e209b6828981 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -105,9 +105,10 @@ int xhci_halt(struct xhci_hcd *xhci) ret = handshake(xhci, &xhci->op_regs->status, STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); - if (!ret) + if (!ret) { xhci->xhc_state |= XHCI_STATE_HALTED; - else + xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; + } else xhci_warn(xhci, "Host not halted after %u microseconds.\n", XHCI_MAX_HALT_USEC); return ret; @@ -583,6 +584,7 @@ static int xhci_run_finished(struct xhci_hcd *xhci) return -ENODEV; } xhci->shared_hcd->state = HC_STATE_RUNNING; + xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; if (xhci->quirks & XHCI_NEC_HOST) xhci_ring_cmd_db(xhci); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index eeeef474ce68..75722b70bba3 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1417,6 +1417,10 @@ struct xhci_hcd { /* data structures */ struct xhci_device_context_array *dcbaa; struct xhci_ring *cmd_ring; + unsigned int cmd_ring_state; +#define CMD_RING_STATE_RUNNING (1 << 0) +#define CMD_RING_STATE_ABORTED (1 << 1) +#define CMD_RING_STATE_STOPPED (1 << 2) unsigned int cmd_ring_reserved_trbs; struct xhci_ring *event_ring; struct xhci_erst erst; -- GitLab From 2818247b6565b7adfbcd53b74509448a8e1fad84 Mon Sep 17 00:00:00 2001 From: Elric Fu Date: Wed, 27 Jun 2012 16:31:12 +0800 Subject: [PATCH 0601/1799] xHCI: add aborting command ring function commit b92cc66c047ff7cf587b318fe377061a353c120f upstream. Software have to abort command ring and cancel command when a command is failed or hang. Otherwise, the command ring will hang up and can't handle the others. An example of a command that may hang is the Address Device Command, because waiting for a SET_ADDRESS request to be acknowledged by a USB device is outside of the xHC's ability to control. To cancel a command, software will initialize a command descriptor for the cancel command, and add it into a cancel_cmd_list of xhci. Sarah: Fixed missing newline on "Have the command ring been stopped?" debugging statement. This patch should be backported to kernels as old as 3.0, that contain the commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an assertion to check for virt_dev=0 bug." That commit papers over a NULL pointer dereference, and this patch fixes the underlying issue that caused the NULL pointer dereference. Signed-off-by: Elric Fu Signed-off-by: Sarah Sharp Tested-by: Miroslav Sabljic Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 7 +++ drivers/usb/host/xhci-ring.c | 108 +++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci.c | 2 +- drivers/usb/host/xhci.h | 12 ++++ 4 files changed, 128 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 6b908249b019..cbed50ad9c12 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1772,6 +1772,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) { struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); struct dev_info *dev_info, *next; + struct xhci_cd *cur_cd, *next_cd; unsigned long flags; int size; int i, j, num_ports; @@ -1793,6 +1794,11 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci_ring_free(xhci, xhci->cmd_ring); xhci->cmd_ring = NULL; xhci_dbg(xhci, "Freed command ring\n"); + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + } for (i = 1; i < MAX_HC_SLOTS; ++i) xhci_free_virt_device(xhci, i); @@ -2338,6 +2344,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci->cmd_ring = xhci_ring_alloc(xhci, 1, 1, TYPE_COMMAND, flags); if (!xhci->cmd_ring) goto fail; + INIT_LIST_HEAD(&xhci->cancel_cmd_list); xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring); xhci_dbg(xhci, "First segment DMA is 0x%llx\n", (unsigned long long)xhci->cmd_ring->first_seg->dma); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index f98dfedbc64c..729330e1ac35 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -289,6 +289,114 @@ void xhci_ring_cmd_db(struct xhci_hcd *xhci) xhci_readl(xhci, &xhci->dba->doorbell[0]); } +static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) +{ + u64 temp_64; + int ret; + + xhci_dbg(xhci, "Abort command ring\n"); + + if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING)) { + xhci_dbg(xhci, "The command ring isn't running, " + "Have the command ring been stopped?\n"); + return 0; + } + + temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + if (!(temp_64 & CMD_RING_RUNNING)) { + xhci_dbg(xhci, "Command ring had been stopped\n"); + return 0; + } + xhci->cmd_ring_state = CMD_RING_STATE_ABORTED; + xhci_write_64(xhci, temp_64 | CMD_RING_ABORT, + &xhci->op_regs->cmd_ring); + + /* Section 4.6.1.2 of xHCI 1.0 spec says software should + * time the completion od all xHCI commands, including + * the Command Abort operation. If software doesn't see + * CRR negated in a timely manner (e.g. longer than 5 + * seconds), then it should assume that the there are + * larger problems with the xHC and assert HCRST. + */ + ret = handshake(xhci, &xhci->op_regs->cmd_ring, + CMD_RING_RUNNING, 0, 5 * 1000 * 1000); + if (ret < 0) { + xhci_err(xhci, "Stopped the command ring failed, " + "maybe the host is dead\n"); + xhci->xhc_state |= XHCI_STATE_DYING; + xhci_quiesce(xhci); + xhci_halt(xhci); + return -ESHUTDOWN; + } + + return 0; +} + +static int xhci_queue_cd(struct xhci_hcd *xhci, + struct xhci_command *command, + union xhci_trb *cmd_trb) +{ + struct xhci_cd *cd; + cd = kzalloc(sizeof(struct xhci_cd), GFP_ATOMIC); + if (!cd) + return -ENOMEM; + INIT_LIST_HEAD(&cd->cancel_cmd_list); + + cd->command = command; + cd->cmd_trb = cmd_trb; + list_add_tail(&cd->cancel_cmd_list, &xhci->cancel_cmd_list); + + return 0; +} + +/* + * Cancel the command which has issue. + * + * Some commands may hang due to waiting for acknowledgement from + * usb device. It is outside of the xHC's ability to control and + * will cause the command ring is blocked. When it occurs software + * should intervene to recover the command ring. + * See Section 4.6.1.1 and 4.6.1.2 + */ +int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, + union xhci_trb *cmd_trb) +{ + int retval = 0; + unsigned long flags; + + spin_lock_irqsave(&xhci->lock, flags); + + if (xhci->xhc_state & XHCI_STATE_DYING) { + xhci_warn(xhci, "Abort the command ring," + " but the xHCI is dead.\n"); + retval = -ESHUTDOWN; + goto fail; + } + + /* queue the cmd desriptor to cancel_cmd_list */ + retval = xhci_queue_cd(xhci, command, cmd_trb); + if (retval) { + xhci_warn(xhci, "Queuing command descriptor failed.\n"); + goto fail; + } + + /* abort command ring */ + retval = xhci_abort_cmd_ring(xhci); + if (retval) { + xhci_err(xhci, "Abort command ring failed\n"); + if (unlikely(retval == -ESHUTDOWN)) { + spin_unlock_irqrestore(&xhci->lock, flags); + usb_hc_died(xhci_to_hcd(xhci)->primary_hcd); + xhci_dbg(xhci, "xHCI host controller is dead.\n"); + return retval; + } + } + +fail: + spin_unlock_irqrestore(&xhci->lock, flags); + return retval; +} + void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index e209b6828981..9cc368731c84 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -52,7 +52,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB"); * handshake done). There are two failure modes: "usec" have passed (major * hardware flakeout), or the register reads as all-ones (hardware removed). */ -static int handshake(struct xhci_hcd *xhci, void __iomem *ptr, +int handshake(struct xhci_hcd *xhci, void __iomem *ptr, u32 mask, u32 done, int usec) { u32 result; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 75722b70bba3..6456a56e6d2b 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1252,6 +1252,13 @@ struct xhci_td { union xhci_trb *last_trb; }; +/* command descriptor */ +struct xhci_cd { + struct list_head cancel_cmd_list; + struct xhci_command *command; + union xhci_trb *cmd_trb; +}; + struct xhci_dequeue_state { struct xhci_segment *new_deq_seg; union xhci_trb *new_deq_ptr; @@ -1421,6 +1428,7 @@ struct xhci_hcd { #define CMD_RING_STATE_RUNNING (1 << 0) #define CMD_RING_STATE_ABORTED (1 << 1) #define CMD_RING_STATE_STOPPED (1 << 2) + struct list_head cancel_cmd_list; unsigned int cmd_ring_reserved_trbs; struct xhci_ring *event_ring; struct xhci_erst erst; @@ -1699,6 +1707,8 @@ static inline void xhci_unregister_plat(void) /* xHCI host controller glue */ typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); +int handshake(struct xhci_hcd *xhci, void __iomem *ptr, + u32 mask, u32 done, int usec); void xhci_quiesce(struct xhci_hcd *xhci); int xhci_halt(struct xhci_hcd *xhci); int xhci_reset(struct xhci_hcd *xhci); @@ -1789,6 +1799,8 @@ void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, struct xhci_dequeue_state *deq_state); void xhci_stop_endpoint_command_watchdog(unsigned long arg); +int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, + union xhci_trb *cmd_trb); void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, unsigned int stream_id); -- GitLab From 75382341d888ba0132c5eeb94711840acf972034 Mon Sep 17 00:00:00 2001 From: Elric Fu Date: Wed, 27 Jun 2012 16:31:52 +0800 Subject: [PATCH 0602/1799] xHCI: cancel command after command timeout commit 6e4468b9a0793dfb53eb80d9fe52c739b13b27fd upstream. The patch is used to cancel command when the command isn't acknowledged and a timeout occurs. This patch should be backported to kernels as old as 3.0, that contain the commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an assertion to check for virt_dev=0 bug." That commit papers over a NULL pointer dereference, and this patch fixes the underlying issue that caused the NULL pointer dereference. Signed-off-by: Elric Fu Signed-off-by: Sarah Sharp Tested-by: Miroslav Sabljic Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 26 +++++++++++++++++++------- drivers/usb/host/xhci.h | 3 +++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 9cc368731c84..dc24c37b1ad5 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2525,6 +2525,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, struct completion *cmd_completion; u32 *cmd_status; struct xhci_virt_device *virt_dev; + union xhci_trb *cmd_trb; spin_lock_irqsave(&xhci->lock, flags); virt_dev = xhci->devs[udev->slot_id]; @@ -2570,6 +2571,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, } init_completion(cmd_completion); + cmd_trb = xhci->cmd_ring->dequeue; if (!ctx_change) ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma, udev->slot_id, must_succeed); @@ -2591,14 +2593,17 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, /* Wait for the configure endpoint command to complete */ timeleft = wait_for_completion_interruptible_timeout( cmd_completion, - USB_CTRL_SET_TIMEOUT); + XHCI_CMD_DEFAULT_TIMEOUT); if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for %s command\n", timeleft == 0 ? "Timeout" : "Signal", ctx_change == 0 ? "configure endpoint" : "evaluate context"); - /* FIXME cancel the configure endpoint command */ + /* cancel the configure endpoint command */ + ret = xhci_cancel_cmd(xhci, command, cmd_trb); + if (ret < 0) + return ret; return -ETIME; } @@ -3547,8 +3552,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) unsigned long flags; int timeleft; int ret; + union xhci_trb *cmd_trb; spin_lock_irqsave(&xhci->lock, flags); + cmd_trb = xhci->cmd_ring->dequeue; ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0); if (ret) { spin_unlock_irqrestore(&xhci->lock, flags); @@ -3560,12 +3567,12 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) /* XXX: how much time for xHC slot assignment? */ timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev, - USB_CTRL_SET_TIMEOUT); + XHCI_CMD_DEFAULT_TIMEOUT); if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for a slot\n", timeleft == 0 ? "Timeout" : "Signal"); - /* FIXME cancel the enable slot request */ - return 0; + /* cancel the enable slot request */ + return xhci_cancel_cmd(xhci, NULL, cmd_trb); } if (!xhci->slot_id) { @@ -3626,6 +3633,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_slot_ctx *slot_ctx; struct xhci_input_control_ctx *ctrl_ctx; u64 temp_64; + union xhci_trb *cmd_trb; if (!udev->slot_id) { xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id); @@ -3664,6 +3672,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); spin_lock_irqsave(&xhci->lock, flags); + cmd_trb = xhci->cmd_ring->dequeue; ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma, udev->slot_id); if (ret) { @@ -3676,7 +3685,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) /* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */ timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev, - USB_CTRL_SET_TIMEOUT); + XHCI_CMD_DEFAULT_TIMEOUT); /* FIXME: From section 4.3.4: "Software shall be responsible for timing * the SetAddress() "recovery interval" required by USB and aborting the * command on a timeout. @@ -3684,7 +3693,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for address device command\n", timeleft == 0 ? "Timeout" : "Signal"); - /* FIXME cancel the address device command */ + /* cancel the address device command */ + ret = xhci_cancel_cmd(xhci, NULL, cmd_trb); + if (ret < 0) + return ret; return -ETIME; } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 6456a56e6d2b..5361fd8dfeaa 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1252,6 +1252,9 @@ struct xhci_td { union xhci_trb *last_trb; }; +/* xHCI command default timeout value */ +#define XHCI_CMD_DEFAULT_TIMEOUT (5 * HZ) + /* command descriptor */ struct xhci_cd { struct list_head cancel_cmd_list; -- GitLab From c4f132c4c23d6b822242c98def8be15182c24ff4 Mon Sep 17 00:00:00 2001 From: Elric Fu Date: Wed, 27 Jun 2012 16:55:43 +0800 Subject: [PATCH 0603/1799] xHCI: handle command after aborting the command ring commit b63f4053cc8aa22a98e3f9a97845afe6c15d0a0d upstream. According to xHCI spec section 4.6.1.1 and section 4.6.1.2, after aborting a command on the command ring, xHC will generate a command completion event with its completion code set to Command Ring Stopped at least. If a command is currently executing at the time of aborting a command, xHC also generate a command completion event with its completion code set to Command Abort. When the command ring is stopped, software may remove, add, or rearrage Command Descriptors. To cancel a command, software will initialize a command descriptor for the cancel command, and add it into a cancel_cmd_list of xhci. When the command ring is stopped, software will find the command trbs described by command descriptors in cancel_cmd_list and modify it to No Op command. If software can't find the matched trbs, we can think it had been finished. This patch should be backported to kernels as old as 3.0, that contain the commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an assertion to check for virt_dev=0 bug." That commit papers over a NULL pointer dereference, and this patch fixes the underlying issue that caused the NULL pointer dereference. Signed-off-by: Elric Fu Signed-off-by: Sarah Sharp Tested-by: Miroslav Sabljic Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 171 +++++++++++++++++++++++++++++++++-- 1 file changed, 165 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 729330e1ac35..a23d71bba754 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1170,6 +1170,20 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci, } } +/* Complete the command and detele it from the devcie's command queue. + */ +static void xhci_complete_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, + struct xhci_command *command, u32 status) +{ + command->status = status; + list_del(&command->cmd_list); + if (command->completion) + complete(command->completion); + else + xhci_free_command(xhci, command); +} + + /* Check to see if a command in the device's command queue matches this one. * Signal the completion or free the command, and return 1. Return 0 if the * completed command isn't at the head of the command list. @@ -1188,15 +1202,144 @@ static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, if (xhci->cmd_ring->dequeue != command->command_trb) return 0; - command->status = GET_COMP_CODE(le32_to_cpu(event->status)); - list_del(&command->cmd_list); - if (command->completion) - complete(command->completion); - else - xhci_free_command(xhci, command); + xhci_complete_cmd_in_cmd_wait_list(xhci, command, + GET_COMP_CODE(le32_to_cpu(event->status))); return 1; } +/* + * Finding the command trb need to be cancelled and modifying it to + * NO OP command. And if the command is in device's command wait + * list, finishing and freeing it. + * + * If we can't find the command trb, we think it had already been + * executed. + */ +static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd) +{ + struct xhci_segment *cur_seg; + union xhci_trb *cmd_trb; + u32 cycle_state; + + if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue) + return; + + /* find the current segment of command ring */ + cur_seg = find_trb_seg(xhci->cmd_ring->first_seg, + xhci->cmd_ring->dequeue, &cycle_state); + + /* find the command trb matched by cd from command ring */ + for (cmd_trb = xhci->cmd_ring->dequeue; + cmd_trb != xhci->cmd_ring->enqueue; + next_trb(xhci, xhci->cmd_ring, &cur_seg, &cmd_trb)) { + /* If the trb is link trb, continue */ + if (TRB_TYPE_LINK_LE32(cmd_trb->generic.field[3])) + continue; + + if (cur_cd->cmd_trb == cmd_trb) { + + /* If the command in device's command list, we should + * finish it and free the command structure. + */ + if (cur_cd->command) + xhci_complete_cmd_in_cmd_wait_list(xhci, + cur_cd->command, COMP_CMD_STOP); + + /* get cycle state from the origin command trb */ + cycle_state = le32_to_cpu(cmd_trb->generic.field[3]) + & TRB_CYCLE; + + /* modify the command trb to NO OP command */ + cmd_trb->generic.field[0] = 0; + cmd_trb->generic.field[1] = 0; + cmd_trb->generic.field[2] = 0; + cmd_trb->generic.field[3] = cpu_to_le32( + TRB_TYPE(TRB_CMD_NOOP) | cycle_state); + break; + } + } +} + +static void xhci_cancel_cmd_in_cd_list(struct xhci_hcd *xhci) +{ + struct xhci_cd *cur_cd, *next_cd; + + if (list_empty(&xhci->cancel_cmd_list)) + return; + + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + xhci_cmd_to_noop(xhci, cur_cd); + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + } +} + +/* + * traversing the cancel_cmd_list. If the command descriptor according + * to cmd_trb is found, the function free it and return 1, otherwise + * return 0. + */ +static int xhci_search_cmd_trb_in_cd_list(struct xhci_hcd *xhci, + union xhci_trb *cmd_trb) +{ + struct xhci_cd *cur_cd, *next_cd; + + if (list_empty(&xhci->cancel_cmd_list)) + return 0; + + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + if (cur_cd->cmd_trb == cmd_trb) { + if (cur_cd->command) + xhci_complete_cmd_in_cmd_wait_list(xhci, + cur_cd->command, COMP_CMD_STOP); + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + return 1; + } + } + + return 0; +} + +/* + * If the cmd_trb_comp_code is COMP_CMD_ABORT, we just check whether the + * trb pointed by the command ring dequeue pointer is the trb we want to + * cancel or not. And if the cmd_trb_comp_code is COMP_CMD_STOP, we will + * traverse the cancel_cmd_list to trun the all of the commands according + * to command descriptor to NO-OP trb. + */ +static int handle_stopped_cmd_ring(struct xhci_hcd *xhci, + int cmd_trb_comp_code) +{ + int cur_trb_is_good = 0; + + /* Searching the cmd trb pointed by the command ring dequeue + * pointer in command descriptor list. If it is found, free it. + */ + cur_trb_is_good = xhci_search_cmd_trb_in_cd_list(xhci, + xhci->cmd_ring->dequeue); + + if (cmd_trb_comp_code == COMP_CMD_ABORT) + xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; + else if (cmd_trb_comp_code == COMP_CMD_STOP) { + /* traversing the cancel_cmd_list and canceling + * the command according to command descriptor + */ + xhci_cancel_cmd_in_cd_list(xhci); + + xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; + /* + * ring command ring doorbell again to restart the + * command ring + */ + if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) + xhci_ring_cmd_db(xhci); + } + return cur_trb_is_good; +} + static void handle_cmd_completion(struct xhci_hcd *xhci, struct xhci_event_cmd *event) { @@ -1222,6 +1365,22 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, xhci->error_bitmask |= 1 << 5; return; } + + if ((GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_ABORT) || + (GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_STOP)) { + /* If the return value is 0, we think the trb pointed by + * command ring dequeue pointer is a good trb. The good + * trb means we don't want to cancel the trb, but it have + * been stopped by host. So we should handle it normally. + * Otherwise, driver should invoke inc_deq() and return. + */ + if (handle_stopped_cmd_ring(xhci, + GET_COMP_CODE(le32_to_cpu(event->status)))) { + inc_deq(xhci, xhci->cmd_ring); + return; + } + } + switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3]) & TRB_TYPE_BITMASK) { case TRB_TYPE(TRB_ENABLE_SLOT): -- GitLab From e3a63e8c061c486ce46d8d825b3fdd45c14140de Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Fri, 14 Sep 2012 13:05:49 -0400 Subject: [PATCH 0604/1799] Increase XHCI suspend timeout to 16ms commit a6e097dfdfd189b6929af6efa1d289af61858386 upstream. The Intel XHCI specification says that after clearing the run/stop bit the controller may take up to 16ms to halt. We've seen a device take 14ms, which with the current timeout of 10ms causes the kernel to abort the suspend. Increasing the timeout to the recommended value fixes the problem. This patch should be backported to kernels as old as 2.6.37, that contain the commit 5535b1d5f8885695c6ded783c692e3c0d0eda8ca "USB: xHCI: PCI power management implementation". Signed-off-by: Michael Spang Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index dc24c37b1ad5..f75623155308 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -890,7 +890,7 @@ int xhci_suspend(struct xhci_hcd *xhci) command &= ~CMD_RUN; xhci_writel(xhci, command, &xhci->op_regs->command); if (handshake(xhci, &xhci->op_regs->status, - STS_HALT, STS_HALT, 100*100)) { + STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) { xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n"); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; -- GitLab From 92d9a683c431081038d715585e7da9d953cb09f2 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Sat, 22 Sep 2012 00:14:28 +0530 Subject: [PATCH 0605/1799] ath9k: Disable ASPM only for AR9285 commit 046b6802c8d3c8a57448485513bf7291633e0fa3 upstream. Currently, ASPM is disabled for all WLAN+BT combo chipsets when BTCOEX is enabled. This is incorrect since the workaround is required only for WB195, which is a AR9285+AR3011 combo solution. Fix this by checking for the HW version when enabling the workaround. Signed-off-by: Sujith Manoharan Tested-by: Paul Stewart Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index e44097a7529a..0e7d6c188ccf 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -122,8 +122,9 @@ static void ath_pci_aspm_init(struct ath_common *common) if (!parent) return; - if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) { - /* Bluetooth coexistance requires disabling ASPM. */ + if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) && + (AR_SREV_9285(ah))) { + /* Bluetooth coexistance requires disabling ASPM for AR9285. */ pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm); aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm); -- GitLab From aa821c51dc6167556a3dc39fc518754f8650265c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Sep 2012 11:34:50 +1000 Subject: [PATCH 0606/1799] coredump: prevent double-free on an error path in core dumper commit f34f9d186df35e5c39163444c43b4fc6255e39c5 upstream. In !CORE_DUMP_USE_REGSET case, if elf_note_info_init fails to allocate memory for info->fields, it frees already allocated stuff and returns error to its caller, fill_note_info. Which in turn returns error to its caller, elf_core_dump. Which jumps to cleanup label and calls free_note_info, which will happily try to free all info->fields again. BOOM. This is the fix. Signed-off-by: Oleg Nesterov Signed-off-by: Denys Vlasenko Cc: Venu Byravarasu Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- fs/binfmt_elf.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 16f735417072..a009b9e322ac 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1698,30 +1698,19 @@ static int elf_note_info_init(struct elf_note_info *info) return 0; info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL); if (!info->psinfo) - goto notes_free; + return 0; info->prstatus = kmalloc(sizeof(*info->prstatus), GFP_KERNEL); if (!info->prstatus) - goto psinfo_free; + return 0; info->fpu = kmalloc(sizeof(*info->fpu), GFP_KERNEL); if (!info->fpu) - goto prstatus_free; + return 0; #ifdef ELF_CORE_COPY_XFPREGS info->xfpu = kmalloc(sizeof(*info->xfpu), GFP_KERNEL); if (!info->xfpu) - goto fpu_free; + return 0; #endif return 1; -#ifdef ELF_CORE_COPY_XFPREGS - fpu_free: - kfree(info->fpu); -#endif - prstatus_free: - kfree(info->prstatus); - psinfo_free: - kfree(info->psinfo); - notes_free: - kfree(info->notes); - return 0; } static int fill_note_info(struct elfhdr *elf, int phdrs, -- GitLab From 3e6ef23fbf8c22163602cd52729de2fe370fba8f Mon Sep 17 00:00:00 2001 From: xiaojin Date: Mon, 13 Aug 2012 13:43:15 +0100 Subject: [PATCH 0607/1799] n_gsm.c: Implement 3GPP27.010 DLC start-up procedure in MUX commit 7e8ac7b23b67416700dfb8b4136a4e81ce675b48 upstream. In 3GPP27.010 5.8.1, it defined: The TE multiplexer initiates the establishment of the multiplexer control channel by sending a SABM frame on DLCI 0 using the procedures of clause 5.4.1. Once the multiplexer channel is established other DLCs may be established using the procedures of clause 5.4.1. This patch implement 5.8.1 in MUX level, it make sure DLC0 is the first channel to be setup. [or for those not familiar with the specification: it was possible to try and open a data connection while the control channel was not yet fully open, which is a spec violation and confuses some modems] Signed-off-by: xiaojin Tested-by: Yin, Fengwei [tweaked the order we check things and error code] Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c43b683b6eb8..0a73b59f797d 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2889,6 +2889,10 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) gsm = gsm_mux[mux]; if (gsm->dead) return -EL2HLT; + /* If DLCI 0 is not yet fully open return an error. This is ok from a locking + perspective as we don't have to worry about this if DLCI0 is lost */ + if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) + return -EL2NSYNC; dlci = gsm->dlci[line]; if (dlci == NULL) dlci = gsm_dlci_alloc(gsm, line); -- GitLab From b0a3c588df225ee719bd82ab303d02f7cc0d5805 Mon Sep 17 00:00:00 2001 From: Russ Gorby Date: Mon, 13 Aug 2012 13:43:36 +0100 Subject: [PATCH 0608/1799] n_gsm: uplink SKBs accumulate on list commit 192b6041e75bb4a2aae73834037038cea139a92d upstream. gsm_dlci_data_kick will not call any output function if tx_bytes > THRESH_LO furthermore it will call the output function only once if tx_bytes == 0 If the size of the IP writes are on the order of THRESH_LO we can get into a situation where skbs accumulate on the outbound list being starved for events to call the output function. gsm_dlci_data_kick now calls the sweep function when tx_bytes==0 Signed-off-by: Russ Gorby Tested-by: Kappel, LaurentX Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 0a73b59f797d..1720055ca97b 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -971,16 +971,19 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm) static void gsm_dlci_data_kick(struct gsm_dlci *dlci) { unsigned long flags; + int sweep; spin_lock_irqsave(&dlci->gsm->tx_lock, flags); /* If we have nothing running then we need to fire up */ + sweep = (dlci->gsm->tx_bytes < TX_THRESH_LO); if (dlci->gsm->tx_bytes == 0) { if (dlci->net) gsm_dlci_data_output_framed(dlci->gsm, dlci); else gsm_dlci_data_output(dlci->gsm, dlci); - } else if (dlci->gsm->tx_bytes < TX_THRESH_LO) - gsm_dlci_data_sweep(dlci->gsm); + } + if (sweep) + gsm_dlci_data_sweep(dlci->gsm); spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags); } -- GitLab From 119bd47785006d185e8247f63f44c43eaf345ed9 Mon Sep 17 00:00:00 2001 From: Russ Gorby Date: Mon, 13 Aug 2012 13:44:40 +0100 Subject: [PATCH 0609/1799] n_gsm: added interlocking for gsm_data_lock for certain code paths commit 5e44708f75b0f8712da715d6babb0c21089b2317 upstream. There were some locking holes in the management of the MUX's message queue for 2 code paths: 1) gsmld_write_wakeup 2) receipt of CMD_FCON flow-control message In both cases gsm_data_kick is called w/o locking so it can collide with other other instances of gsm_data_kick (pulling messages tx_tail) or potentially other instances of __gsm_data_queu (adding messages to tx_head) Changed to take the tx_lock in these 2 cases Signed-off-by: Russ Gorby Tested-by: Yin, Fengwei Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 1720055ca97b..671fbc2d7935 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1193,6 +1193,8 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, u8 *data, int clen) { u8 buf[1]; + unsigned long flags; + switch (command) { case CMD_CLD: { struct gsm_dlci *dlci = gsm->dlci[0]; @@ -1218,7 +1220,9 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, gsm->constipated = 0; gsm_control_reply(gsm, CMD_FCOFF, NULL, 0); /* Kick the link in case it is idling */ + spin_lock_irqsave(&gsm->tx_lock, flags); gsm_data_kick(gsm); + spin_unlock_irqrestore(&gsm->tx_lock, flags); break; case CMD_MSC: /* Out of band modem line change indicator for a DLCI */ @@ -2380,12 +2384,12 @@ static void gsmld_write_wakeup(struct tty_struct *tty) /* Queue poll */ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + spin_lock_irqsave(&gsm->tx_lock, flags); gsm_data_kick(gsm); if (gsm->tx_bytes < TX_THRESH_LO) { - spin_lock_irqsave(&gsm->tx_lock, flags); gsm_dlci_data_sweep(gsm); - spin_unlock_irqrestore(&gsm->tx_lock, flags); } + spin_unlock_irqrestore(&gsm->tx_lock, flags); } /** -- GitLab From 1168fb4bf41d55b04c07d82cb5c1e0fde9be3cf9 Mon Sep 17 00:00:00 2001 From: Russ Gorby Date: Mon, 13 Aug 2012 13:45:30 +0100 Subject: [PATCH 0610/1799] n_gsm: memory leak in uplink error path commit 88ed2a60610974443335c924d7cb8e5dcf9dbdc1 upstream. Uplink (TX) network data will go through gsm_dlci_data_output_framed there is a bug where if memory allocation fails, the skb which has already been pulled off the list will be lost. In addition TX skbs were being processed in LIFO order Fixed the memory leak, and changed to FIFO order processing Signed-off-by: Russ Gorby Tested-by: Kappel, LaurentX Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 671fbc2d7935..90dff8233efd 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -875,7 +875,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, /* dlci->skb is locked by tx_lock */ if (dlci->skb == NULL) { - dlci->skb = skb_dequeue(&dlci->skb_list); + dlci->skb = skb_dequeue_tail(&dlci->skb_list); if (dlci->skb == NULL) return 0; first = 1; @@ -899,8 +899,11 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, /* FIXME: need a timer or something to kick this so it can't get stuck with no work outstanding and no buffer free */ - if (msg == NULL) + if (msg == NULL) { + skb_queue_tail(&dlci->skb_list, dlci->skb); + dlci->skb = NULL; return -ENOMEM; + } dp = msg->data; if (dlci->adaption == 4) { /* Interruptible framed (Packetised Data) */ -- GitLab From 56a631f3bf36641133afeb3db7c1ec5721c8dd04 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sat, 18 Aug 2012 14:11:42 +0200 Subject: [PATCH 0611/1799] UBI: fix autoresize handling in R/O mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit abb3e01103eb4e2ea5c15e6fedbc74e08bd4cc2b upstream. Currently UBI fails in autoresize when it is in R/O mode (e.g., because the underlying MTD device is R/O). This patch fixes the issue - we just skip autoresize and print a warning. Reported-by: Pali Rohár Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/ubi/build.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 0fde9fc7d2e5..83bab2c79834 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -816,6 +816,11 @@ static int autoresize(struct ubi_device *ubi, int vol_id) struct ubi_volume *vol = ubi->volumes[vol_id]; int err, old_reserved_pebs = vol->reserved_pebs; + if (ubi->ro_mode) { + ubi_warn("skip auto-resize because of R/O mode"); + return 0; + } + /* * Clear the auto-resize flag in the volume in-memory copy of the * volume table, and 'ubi_resize_volume()' will propagate this change -- GitLab From 7d0fcfec4c491eb3c815929be5512ae8d1886553 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 27 Aug 2012 11:38:13 -0700 Subject: [PATCH 0612/1799] Yama: handle 32-bit userspace prctl commit 2e4930eb7c8fb20a39dfb5f8a8f80402710dcea8 upstream. When running a 64-bit kernel and receiving prctls from a 32-bit userspace, the "-1" used as an unsigned long will end up being misdetected. The kernel is looking for 0xffffffffffffffff instead of 0xffffffff. Since prctl lacks a distinct compat interface, Yama needs to handle this translation itself. As such, support either value as meaning PR_SET_PTRACER_ANY, to avoid breaking the ABI for 64-bit. Signed-off-by: Kees Cook Acked-by: John Johansen Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman --- security/yama/yama_lsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 573723843a04..1d6bf24c1172 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -138,7 +138,7 @@ static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3, if (arg2 == 0) { yama_ptracer_del(NULL, myself); rc = 0; - } else if (arg2 == PR_SET_PTRACER_ANY) { + } else if (arg2 == PR_SET_PTRACER_ANY || (int)arg2 == -1) { rc = yama_ptracer_add(NULL, myself); } else { struct task_struct *tracer; -- GitLab From 54ce2fb86f0b78808c7fcc1d581ebbf15ca36e91 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 30 Jul 2012 11:33:05 +1000 Subject: [PATCH 0613/1799] SCSI: ibmvscsi: Fix host config length field overflow commit 225c56960fcafeccc2b6304f96cd3f0dbf42a16a upstream. The length field in the host config packet is only 16-bit long, so passing it 0x10000 (64K which is our standard PAGE_SIZE) doesn't work and result in an empty config from the server. Signed-off-by: Benjamin Herrenschmidt Acked-by: Robert Jennings Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/ibmvscsi/ibmvscsi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 3a6c4742951e..337e8b33d9aa 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1541,6 +1541,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata, host_config = &evt_struct->iu.mad.host_config; + /* The transport length field is only 16-bit */ + length = min(0xffff, length); + /* Set up a lun reset SRP command */ memset(host_config, 0x00, sizeof(*host_config)); host_config->common.type = VIOSRP_HOST_CONFIG_TYPE; -- GitLab From 7b5c87e0163ad33aabb1a725b0b5444a7e0b5c73 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 26 Jul 2012 11:34:10 -0500 Subject: [PATCH 0614/1799] SCSI: hpsa: Use LUN reset instead of target reset commit 21e89afd325849eb38adccf382df16cc895911f9 upstream. It turns out Smart Array logical drives do not support target reset and when the target reset fails, the logical drive will be taken off line. Symptoms look like this: hpsa 0000:03:00.0: Abort request on C1:B0:T0:L0 hpsa 0000:03:00.0: resetting device 1:0:0:0 hpsa 0000:03:00.0: cp ffff880037c56000 is reported invalid (probably means target device no longer present) hpsa 0000:03:00.0: resetting device failed. sd 1:0:0:0: Device offlined - not ready after error recovery sd 1:0:0:0: rejecting I/O to offline device EXT3-fs error (device sdb1): read_block_bitmap: LUN reset is supported though, and is what we should be using. Target reset is also disruptive in shared SAS situations, for example, an external MSA1210m which does support target reset attached to Smart Arrays in multiple hosts -- a target reset from one host is disruptive to other hosts as all LUNs on the target will be reset and will abort all outstanding i/os back to all the attached hosts. So we should use LUN reset, not target reset. Tested this with Smart Array logical drives and with tape drives. Not sure how this bug survived since 2009, except it must be very rare for a Smart Array to require more than 30s to complete a request. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/hpsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 7c49e0ab90e4..8a5e25d2f21b 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2943,7 +2943,7 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.Timeout = 0; /* Don't time out */ memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); c->Request.CDB[0] = cmd; - c->Request.CDB[1] = 0x03; /* Reset target above */ + c->Request.CDB[1] = HPSA_RESET_TYPE_LUN; /* If bytes 4-7 are zero, it means reset the */ /* LunID device */ c->Request.CDB[4] = 0x00; -- GitLab From 0f0c5909d4cf6016c536fceddd5ca7bded0e5219 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 21 Sep 2012 15:09:47 +0800 Subject: [PATCH 0615/1799] can: mscan-mpc5xxx: fix return value check in mpc512x_can_get_clock() commit f61bd0585dfc7d99db4936d7467de4ca8e2f7ea0 upstream. In case of error, the function clk_get() returns ERR_PTR() and never returns NULL pointer. The NULL test in the error handling should be replaced with IS_ERR(). dpatch engine is used to auto generated this patch. (https://github.com/weiyj/dpatch) Signed-off-by: Wei Yongjun Acked-by: Wolfgang Grandegger Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/mscan/mpc5xxx_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index 5caa572d71e3..957f000263d0 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -181,7 +181,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, if (!clock_name || !strcmp(clock_name, "sys")) { sys_clk = clk_get(&ofdev->dev, "sys_clk"); - if (!sys_clk) { + if (IS_ERR(sys_clk)) { dev_err(&ofdev->dev, "couldn't get sys_clk\n"); goto exit_unmap; } @@ -204,7 +204,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, if (clocksrc < 0) { ref_clk = clk_get(&ofdev->dev, "ref_clk"); - if (!ref_clk) { + if (IS_ERR(ref_clk)) { dev_err(&ofdev->dev, "couldn't get ref_clk\n"); goto exit_unmap; } -- GitLab From abe988511dc075dab47ba9283c791299f7285aaa Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Sun, 30 Sep 2012 10:25:34 +0200 Subject: [PATCH 0616/1799] remoteproc: select VIRTIO to avoid build breakage commit 2ed6d29c725c4aead510b5c23f563795b265acf5 upstream. drivers/built-in.o: In function `rproc_virtio_finalize_features': remoteproc_virtio.c:(.text+0x2f9a02): undefined reference to `vring_transport_features' drivers/built-in.o: In function `rproc_virtio_del_vqs': remoteproc_virtio.c:(.text+0x2f9a74): undefined reference to `vring_del_virtqueue' drivers/built-in.o: In function `rproc_virtio_find_vqs': remoteproc_virtio.c:(.text+0x2f9c44): undefined reference to `vring_new_virtqueue' drivers/built-in.o: In function `rproc_add_virtio_dev': (.text+0x2f9e2c): undefined reference to `register_virtio_device' drivers/built-in.o: In function `rproc_vq_interrupt': (.text+0x2f9db7): undefined reference to `vring_interrupt' drivers/built-in.o: In function `rproc_remove_virtio_dev': (.text+0x2f9e9f): undefined reference to `unregister_virtio_device' Reported-by: Randy Dunlap Signed-off-by: Ohad Ben-Cohen Signed-off-by: Greg Kroah-Hartman --- drivers/remoteproc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index f8d818abf98c..811ff72df4db 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -5,6 +5,7 @@ config REMOTEPROC tristate depends on EXPERIMENTAL select FW_CONFIG + select VIRTIO config OMAP_REMOTEPROC tristate "OMAP remoteproc support" -- GitLab From cbc7a8263c6e2d8f7354b4c06e21607d6dffd6bd Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 25 Sep 2012 10:01:56 +0300 Subject: [PATCH 0617/1799] remoteproc: fix a potential NULL-dereference on cleanup commit 7168d914a782086e217214c57ddfc7cc4b738c0c upstream. We only need to allocate mapping if there is an IOMMU domain. Otherwise, when the mappings are released, the assumption that an IOMMU domain is there will crash and burn. Signed-off-by: Dan Carpenter [ohad: revise commit log] Signed-off-by: Ohad Ben-Cohen Signed-off-by: Greg Kroah-Hartman --- drivers/remoteproc/remoteproc_core.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 7591b9774d05..837cc40180aa 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -643,17 +643,10 @@ static int rproc_handle_carveout(struct rproc *rproc, dev_dbg(dev, "carveout rsc: da %x, pa %x, len %x, flags %x\n", rsc->da, rsc->pa, rsc->len, rsc->flags); - mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); - if (!mapping) { - dev_err(dev, "kzalloc mapping failed\n"); - return -ENOMEM; - } - carveout = kzalloc(sizeof(*carveout), GFP_KERNEL); if (!carveout) { dev_err(dev, "kzalloc carveout failed\n"); - ret = -ENOMEM; - goto free_mapping; + return -ENOMEM; } va = dma_alloc_coherent(dev, rsc->len, &dma, GFP_KERNEL); @@ -683,11 +676,18 @@ static int rproc_handle_carveout(struct rproc *rproc, * physical address in this case. */ if (rproc->domain) { + mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); + if (!mapping) { + dev_err(dev, "kzalloc mapping failed\n"); + ret = -ENOMEM; + goto dma_free; + } + ret = iommu_map(rproc->domain, rsc->da, dma, rsc->len, rsc->flags); if (ret) { dev_err(dev, "iommu_map failed: %d\n", ret); - goto dma_free; + goto free_mapping; } /* @@ -728,12 +728,12 @@ static int rproc_handle_carveout(struct rproc *rproc, return 0; +free_mapping: + kfree(mapping); dma_free: dma_free_coherent(dev, rsc->len, va, dma); free_carv: kfree(carveout); -free_mapping: - kfree(mapping); return ret; } -- GitLab From 350f3edb0a05c340853c75f4c5007a72ebd9e32f Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 30 Aug 2012 07:01:30 +0000 Subject: [PATCH 0618/1799] IPoIB: Fix use-after-free of multicast object commit bea1e22df494a729978e7f2c54f7bda328f74bc3 upstream. Fix a crash in ipoib_mcast_join_task(). (with help from Or Gerlitz) Commit c8c2afe360b7 ("IPoIB: Use rtnl lock/unlock when changing device flags") added a call to rtnl_lock() in ipoib_mcast_join_task(), which is run from the ipoib_workqueue, and hence the workqueue can't be flushed from the context of ipoib_stop(). In the current code, ipoib_stop() (which doesn't flush the workqueue) calls ipoib_mcast_dev_flush(), which goes and deletes all the multicast entries. This takes place without any synchronization with a possible running instance of ipoib_mcast_join_task() for the same ipoib device, leading to a crash due to NULL pointer dereference. Fix this by making sure that the workqueue is flushed before ipoib_mcast_dev_flush() is called. To make that possible, we move the RTNL-lock wrapped code to ipoib_mcast_join_finish(). Signed-off-by: Patrick McHardy Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +- .../infiniband/ulp/ipoib/ipoib_multicast.c | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 3974c290b667..69b23c22d4e9 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -148,7 +148,7 @@ static int ipoib_stop(struct net_device *dev) netif_stop_queue(dev); - ipoib_ib_dev_down(dev, 0); + ipoib_ib_dev_down(dev, 1); ipoib_ib_dev_stop(dev, 0); if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 20ebc6fd1bb9..213965d5bc8b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -190,7 +190,9 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, mcast->mcmember = *mcmember; - /* Set the cached Q_Key before we attach if it's the broadcast group */ + /* Set the multicast MTU and cached Q_Key before we attach if it's + * the broadcast group. + */ if (!memcmp(mcast->mcmember.mgid.raw, priv->dev->broadcast + 4, sizeof (union ib_gid))) { spin_lock_irq(&priv->lock); @@ -198,10 +200,17 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, spin_unlock_irq(&priv->lock); return -EAGAIN; } + priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu)); priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey); spin_unlock_irq(&priv->lock); priv->tx_wr.wr.ud.remote_qkey = priv->qkey; set_qkey = 1; + + if (!ipoib_cm_admin_enabled(dev)) { + rtnl_lock(); + dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu)); + rtnl_unlock(); + } } if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) { @@ -589,14 +598,6 @@ void ipoib_mcast_join_task(struct work_struct *work) return; } - priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu)); - - if (!ipoib_cm_admin_enabled(dev)) { - rtnl_lock(); - dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu)); - rtnl_unlock(); - } - ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n"); clear_bit(IPOIB_MCAST_RUN, &priv->flags); -- GitLab From 0e4765fd9c0f8df577e0b8cbea927c2051710f27 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 24 Aug 2012 10:27:54 +0000 Subject: [PATCH 0619/1799] IB/srp: Fix use-after-free in srp_reset_req() commit 9b796d06d5d1b1e85ae2316a283ea11dd739ef96 upstream. srp_free_req() uses the scsi_cmnd structure contents to unmap buffers, so we must invoke srp_free_req() before we release ownership of that structure. Signed-off-by: Bart Van Assche Acked-by: David Dillow Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/srp/ib_srp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 1b5b0c730054..ac66e6b43ee2 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -638,9 +638,9 @@ static void srp_reset_req(struct srp_target_port *target, struct srp_request *re struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL); if (scmnd) { + srp_free_req(target, req, scmnd, 0); scmnd->result = DID_RESET << 16; scmnd->scsi_done(scmnd); - srp_free_req(target, req, scmnd, 0); } } -- GitLab From 22fb582405002812d8fb89d0ed1264e97d3d25ad Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 24 Aug 2012 10:29:11 +0000 Subject: [PATCH 0620/1799] IB/srp: Avoid having aborted requests hang commit d8536670916a685df116b5c2cb256573fd25e4e3 upstream. We need to call scsi_done() for commands after we abort them. Signed-off-by: Bart Van Assche Acked-by: David Dillow Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/srp/ib_srp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index ac66e6b43ee2..922d845f76b0 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1687,6 +1687,7 @@ static int srp_abort(struct scsi_cmnd *scmnd) SRP_TSK_ABORT_TASK); srp_free_req(target, req, scmnd, 0); scmnd->result = DID_ABORT << 16; + scmnd->scsi_done(scmnd); return SUCCESS; } -- GitLab From b4d4dc33a372aaee2205d4506b4c7ead6275067d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 22 Jun 2012 11:31:14 -0700 Subject: [PATCH 0621/1799] isci: fix isci_pci_probe() generates warning on efi failure path commit 6d70a74ffd616073a68ae0974d98819bfa8e6da6 upstream. The oem parameter image embedded in the efi variable is at an offset from the start of the variable. However, in the failure path we try to free the 'orom' pointer which is only valid when the paramaters are being read from the legacy option-rom space. Since failure to load the oem parameters is unlikely and we keep the memory around in the success case just defer all de-allocation to devm. Reported-by: Don Morris Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/isci/init.c | 1 - drivers/scsi/isci/probe_roms.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index bc6cf8886312..4c150dffb1ab 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -481,7 +481,6 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic orom->hdr.version)) { dev_warn(&pdev->dev, "[%d]: invalid oem parameters detected, falling back to firmware\n", i); - devm_kfree(&pdev->dev, orom); orom = NULL; break; } diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 9b8117b9d756..4c66f4682fd4 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -104,7 +104,6 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev) if (i >= len) { dev_err(&pdev->dev, "oprom parse error\n"); - devm_kfree(&pdev->dev, rom); rom = NULL; } pci_unmap_biosrom(oprom); -- GitLab From 4a3bb116ee8ab2f912fdb6d2af40028b15825151 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 22 Aug 2012 13:03:48 +0300 Subject: [PATCH 0622/1799] x86/alternatives: Fix p6 nops on non-modular kernels commit cb09cad44f07044d9810f18f6f9a6a6f3771f979 upstream. Probably a leftover from the early days of self-patching, p6nops are marked __initconst_or_module, which causes them to be discarded in a non-modular kernel. If something later triggers patching, it will overwrite kernel code with garbage. Reported-by: Tomas Racek Signed-off-by: Avi Kivity Cc: Michael Tokarev Cc: Borislav Petkov Cc: Marcelo Tosatti Cc: qemu-devel@nongnu.org Cc: Anthony Liguori Cc: H. Peter Anvin Cc: Alan Cox Cc: Alan Cox Link: http://lkml.kernel.org/r/5034AE84.90708@redhat.com Signed-off-by: Ingo Molnar Cc: Ben Jencks Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/alternative.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 73ef56c5a8b3..bda833c5f6ce 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -160,7 +160,7 @@ static const unsigned char * const k7_nops[ASM_NOP_MAX+2] = #endif #ifdef P6_NOP1 -static const unsigned char __initconst_or_module p6nops[] = +static const unsigned char p6nops[] = { P6_NOP1, P6_NOP2, -- GitLab From b8d54c01874da4e548a531b77a29c21236ce8a31 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 28 Aug 2012 22:12:10 -0700 Subject: [PATCH 0623/1799] SCSI: scsi_remove_target: fix softlockup regression on hot remove commit bc3f02a795d3b4faa99d37390174be2a75d091bd upstream. John reports: BUG: soft lockup - CPU#2 stuck for 23s! [kworker/u:8:2202] [..] Call Trace: [] scsi_remove_target+0xda/0x1f0 [] sas_rphy_remove+0x55/0x60 [] sas_rphy_delete+0x11/0x20 [] sas_port_delete+0x25/0x160 [] mptsas_del_end_device+0x183/0x270 ...introduced by commit 3b661a9 "[SCSI] fix hot unplug vs async scan race". Don't restart lookup of more stargets in the multi-target case, just arrange to traverse the list once, on the assumption that new targets are always added at the end. There is no guarantee that the target will change state in scsi_target_reap() so we can end up spinning if we restart. Acked-by: Jack Wang LKML-Reference: Reported-by: John Drescher Tested-by: John Drescher Signed-off-by: Dan Williams Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_sysfs.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index bb7c4828acc0..08d48a3b7679 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1023,33 +1023,31 @@ static void __scsi_remove_target(struct scsi_target *starget) void scsi_remove_target(struct device *dev) { struct Scsi_Host *shost = dev_to_shost(dev->parent); - struct scsi_target *starget, *found; + struct scsi_target *starget, *last = NULL; unsigned long flags; - restart: - found = NULL; + /* remove targets being careful to lookup next entry before + * deleting the last + */ spin_lock_irqsave(shost->host_lock, flags); list_for_each_entry(starget, &shost->__targets, siblings) { if (starget->state == STARGET_DEL) continue; if (starget->dev.parent == dev || &starget->dev == dev) { - found = starget; - found->reap_ref++; - break; + /* assuming new targets arrive at the end */ + starget->reap_ref++; + spin_unlock_irqrestore(shost->host_lock, flags); + if (last) + scsi_target_reap(last); + last = starget; + __scsi_remove_target(starget); + spin_lock_irqsave(shost->host_lock, flags); } } spin_unlock_irqrestore(shost->host_lock, flags); - if (found) { - __scsi_remove_target(found); - scsi_target_reap(found); - /* in the case where @dev has multiple starget children, - * continue removing. - * - * FIXME: does such a case exist? - */ - goto restart; - } + if (last) + scsi_target_reap(last); } EXPORT_SYMBOL(scsi_remove_target); -- GitLab From ead94148559d54f0aae235dda91dfb98dfb1eae7 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 24 Aug 2012 09:08:41 +0000 Subject: [PATCH 0624/1799] SCSI: scsi_dh_alua: Enable STPG for unavailable ports commit e47f8976d8e573928824a06748f7bc82c58d747f upstream. A quote from SPC-4: "While in the unavailable primary target port asymmetric access state, the device server shall support those of the following commands that it supports while in the active/optimized state: [ ... ] d) SET TARGET PORT GROUPS; [ ... ]". Hence enable sending STPG to a target port group that is in the unavailable state. Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Acked-by: Hannes Reinecke Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/device_handler/scsi_dh_alua.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 04c5cea47a22..3a8ba3e433d2 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -583,8 +583,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) h->state = TPGS_STATE_STANDBY; break; case TPGS_STATE_OFFLINE: - case TPGS_STATE_UNAVAILABLE: - /* Path unusable for unavailable/offline */ + /* Path unusable */ err = SCSI_DH_DEV_OFFLINED; break; default: -- GitLab From 399abb8918aa5cef74a1d5c582bc7c08c8c99757 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 7 Oct 2012 08:32:45 -0700 Subject: [PATCH 0625/1799] Linux 3.4.13 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bcf5bc455a94..75b37ce4f1ee 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 12 +SUBLEVEL = 13 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 605843502b0573c0c865b13f770d971aadaf0c41 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 4 Oct 2012 17:11:13 -0700 Subject: [PATCH 0626/1799] mn10300: only add -mmem-funcs to KBUILD_CFLAGS if gcc supports it commit 9957423f035c2071f6d1c5d2f095cdafbeb25ad7 upstream. It seems the current (gcc 4.6.3) no longer provides this so make it conditional. As reported by Tony before, the mn10300 architecture cross-compiles with gcc-4.6.3 if -mmem-funcs is not added to KBUILD_CFLAGS. Reported-by: Tony Breeds Signed-off-by: Geert Uytterhoeven Cc: David Howells Cc: Koichi Yasutake Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/mn10300/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mn10300/Makefile b/arch/mn10300/Makefile index 7120282bf0d8..3eb4a52ff9a7 100644 --- a/arch/mn10300/Makefile +++ b/arch/mn10300/Makefile @@ -26,7 +26,7 @@ CHECKFLAGS += PROCESSOR := unset UNIT := unset -KBUILD_CFLAGS += -mam33 -mmem-funcs -DCPU=AM33 +KBUILD_CFLAGS += -mam33 -DCPU=AM33 $(call cc-option,-mmem-funcs,) KBUILD_AFLAGS += -mam33 -DCPU=AM33 ifeq ($(CONFIG_MN10300_CURRENT_IN_E2),y) -- GitLab From f15977883584e7b52832518c3fef115957d3203b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 4 Oct 2012 17:11:17 -0700 Subject: [PATCH 0627/1799] kbuild: make: fix if_changed when command contains backslashes commit c353acba28fb3fa1fd05fd6b85a9fc7938330f9c upstream. The call if_changed mechanism does not work when the command contains backslashes. This basically is an issue with lzo and bzip2 compressed kernels. The compressed binaries do not contain the uncompressed image size, so these use size_append to append the size. This results in backslashes in the executed command. With this if_changed always detects a change in the command and rebuilds the compressed image even if nothing has changed. Fix this by escaping backslashes in make-cmd Signed-off-by: Sascha Hauer Signed-off-by: Jan Luebbe Cc: Sam Ravnborg Cc: Bernhard Walle Cc: Michal Marek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- scripts/Kbuild.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 6a3ee981931d..afa44595f348 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -209,7 +209,7 @@ endif # >$< substitution to preserve $ when reloading .cmd file # note: when using inline perl scripts [perl -e '...$$t=1;...'] # in $(cmd_xxx) double $$ your perl vars -make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))) +make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))) # Find any prerequisites that is newer than target or that does not exist. # PHONY targets skipped in both cases. -- GitLab From 4893cf612a68d26cdbe0e16ba9c42772136e2340 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 2 Oct 2012 16:42:36 +0200 Subject: [PATCH 0628/1799] kbuild: Fix gcc -x syntax commit b1e0d8b70fa31821ebca3965f2ef8619d7c5e316 upstream. The correct syntax for gcc -x is "gcc -x assembler", not "gcc -xassembler". Even though the latter happens to work, the former is what is documented in the manual page and thus what gcc wrappers such as icecream do expect. This isn't a cosmetic change. The missing space prevents icecream from recognizing compilation tasks it can't handle, leading to silent kernel miscompilations. Besides me, credits go to Michael Matz and Dirk Mueller for investigating the miscompilation issue and tracking it down to this incorrect -x parameter syntax. Signed-off-by: Jean Delvare Acked-by: Ingo Molnar Cc: Bernhard Walle Cc: Michal Marek Cc: Ralf Baechle Signed-off-by: Michal Marek Signed-off-by: Greg Kroah-Hartman --- arch/mips/Makefile | 2 +- arch/mips/kernel/Makefile | 2 +- arch/x86/Makefile | 2 +- scripts/Kbuild.include | 12 ++++++------ scripts/gcc-version.sh | 6 +++--- scripts/gcc-x86_32-has-stack-protector.sh | 2 +- scripts/gcc-x86_64-has-stack-protector.sh | 2 +- scripts/kconfig/check.sh | 2 +- scripts/kconfig/lxdialog/check-lxdialog.sh | 2 +- tools/perf/Makefile | 2 +- tools/power/cpupower/Makefile | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 4fedf5a51d96..5c1e75d1c41e 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -225,7 +225,7 @@ KBUILD_CPPFLAGS += -D"DATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)" LDFLAGS += -m $(ld-emul) ifdef CONFIG_MIPS -CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -xc /dev/null | \ +CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/") ifdef CONFIG_64BIT diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 0c6877ea9004..d3d6fa97c09f 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -104,7 +104,7 @@ obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o obj-$(CONFIG_OF) += prom.o -CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) +CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -x c /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o diff --git a/arch/x86/Makefile b/arch/x86/Makefile index b1c611e6da67..f1276aaeffdb 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -85,7 +85,7 @@ endif ifdef CONFIG_X86_X32 x32_ld_ok := $(call try-run,\ /bin/echo -e '1: .quad 1b' | \ - $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" - && \ + $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" - && \ $(OBJCOPY) -O elf32-x86-64 "$$TMP" "$$TMPO" && \ $(LD) -m elf32_x86_64 "$$TMPO" -o "$$TMP",y,n) ifeq ($(x32_ld_ok),y) diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index afa44595f348..978416dd31ca 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -98,24 +98,24 @@ try-run = $(shell set -e; \ # Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,) as-option = $(call try-run,\ - $(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2)) + $(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2)) # as-instr # Usage: cflags-y += $(call as-instr,instr,option1,option2) as-instr = $(call try-run,\ - printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3)) + printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3)) # cc-option # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586) cc-option = $(call try-run,\ - $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2)) + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2)) # cc-option-yn # Usage: flag := $(call cc-option-yn,-march=winchip-c6) cc-option-yn = $(call try-run,\ - $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n) + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n) # cc-option-align # Prefix align with either -falign or -malign @@ -125,7 +125,7 @@ cc-option-align = $(subst -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) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1))) # cc-version # Usage gcc-ver := $(call cc-version) @@ -143,7 +143,7 @@ cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3)) # cc-ldoption # Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both) cc-ldoption = $(call try-run,\ - $(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2)) + $(CC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2)) # ld-option # Usage: LDFLAGS += $(call ld-option, -X) diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh index debecb5561c4..7f2126df91f2 100644 --- a/scripts/gcc-version.sh +++ b/scripts/gcc-version.sh @@ -22,10 +22,10 @@ if [ ${#compiler} -eq 0 ]; then exit 1 fi -MAJOR=$(echo __GNUC__ | $compiler -E -xc - | tail -n 1) -MINOR=$(echo __GNUC_MINOR__ | $compiler -E -xc - | tail -n 1) +MAJOR=$(echo __GNUC__ | $compiler -E -x c - | tail -n 1) +MINOR=$(echo __GNUC_MINOR__ | $compiler -E -x c - | tail -n 1) if [ "x$with_patchlevel" != "x" ] ; then - PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -xc - | tail -n 1) + PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1) printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL else printf "%02d%02d\\n" $MAJOR $MINOR diff --git a/scripts/gcc-x86_32-has-stack-protector.sh b/scripts/gcc-x86_32-has-stack-protector.sh index 29493dc4528d..12dbd0b11ea4 100644 --- a/scripts/gcc-x86_32-has-stack-protector.sh +++ b/scripts/gcc-x86_32-has-stack-protector.sh @@ -1,6 +1,6 @@ #!/bin/sh -echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs" +echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs" if [ "$?" -eq "0" ] ; then echo y else diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh index afaec618b395..973e8c141567 100644 --- a/scripts/gcc-x86_64-has-stack-protector.sh +++ b/scripts/gcc-x86_64-has-stack-protector.sh @@ -1,6 +1,6 @@ #!/bin/sh -echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" +echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" if [ "$?" -eq "0" ] ; then echo y else diff --git a/scripts/kconfig/check.sh b/scripts/kconfig/check.sh index fa59cbf9d62c..854d9c7c675c 100755 --- a/scripts/kconfig/check.sh +++ b/scripts/kconfig/check.sh @@ -1,6 +1,6 @@ #!/bin/sh # Needed for systems without gettext -$* -xc -o /dev/null - > /dev/null 2>&1 << EOF +$* -x c -o /dev/null - > /dev/null 2>&1 << EOF #include int main() { diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh index 82cc3a85e7f8..50df490fe1de 100644 --- a/scripts/kconfig/lxdialog/check-lxdialog.sh +++ b/scripts/kconfig/lxdialog/check-lxdialog.sh @@ -38,7 +38,7 @@ trap "rm -f $tmp" 0 1 2 3 15 # Check if we can link to ncurses check() { - $cc -xc - -o $tmp 2>/dev/null <<'EOF' + $cc -x c - -o $tmp 2>/dev/null <<'EOF' #include CURSES_LOC main() {} EOF diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 92271d32bc30..c3dd3d4424fe 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -70,7 +70,7 @@ ifeq ($(ARCH),x86_64) ARCH := x86 IS_X86_64 := 0 ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) - IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) + IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) endif ifeq (${IS_X86_64}, 1) RAW_ARCH := x86_64 diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index a93e06cfcc2a..cf397bd26d0c 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -111,7 +111,7 @@ GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo $(OUTPUT)po/$$HLANG.gmo; export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS # check if compiler option is supported -cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;} +cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -x c /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;} # use '-Os' optimization if available, else use -O2 OPTIMIZATION := $(call cc-supports,-Os,-O2) -- GitLab From 750025ab1950b5e32e308c446de32c399cf2d6f6 Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Wed, 5 Sep 2012 10:33:18 +0800 Subject: [PATCH 0629/1799] slab: fix the DEADLOCK issue on l3 alien lock commit 947ca1856a7e60aa6d20536785e6a42dff25aa6e upstream. DEADLOCK will be report while running a kernel with NUMA and LOCKDEP enabled, the process of this fake report is: kmem_cache_free() //free obj in cachep -> cache_free_alien() //acquire cachep's l3 alien lock -> __drain_alien_cache() -> free_block() -> slab_destroy() -> kmem_cache_free() //free slab in cachep->slabp_cache -> cache_free_alien() //acquire cachep->slabp_cache's l3 alien lock Since the cachep and cachep->slabp_cache's l3 alien are in the same lock class, fake report generated. This should not happen since we already have init_lock_keys() which will reassign the lock class for both l3 list and l3 alien. However, init_lock_keys() was invoked at a wrong position which is before we invoke enable_cpucache() on each cache. Since until set slab_state to be FULL, we won't invoke enable_cpucache() on caches to build their l3 alien while creating them, so although we invoked init_lock_keys(), the l3 alien lock class won't change since we don't have them until invoked enable_cpucache() later. This patch will invoke init_lock_keys() after we done enable_cpucache() instead of before to avoid the fake DEADLOCK report. Michael traced the problem back to a commit in release 3.0.0: commit 30765b92ada267c5395fc788623cb15233276f5c Author: Peter Zijlstra Date: Thu Jul 28 23:22:56 2011 +0200 slab, lockdep: Annotate the locks before using them Fernando found we hit the regular OFF_SLAB 'recursion' before we annotate the locks, cure this. The relevant portion of the stack-trace: > [ 0.000000] [] rt_spin_lock+0x50/0x56 > [ 0.000000] [] __cache_free+0x43/0xc3 > [ 0.000000] [] kmem_cache_free+0x6c/0xdc > [ 0.000000] [] slab_destroy+0x4f/0x53 > [ 0.000000] [] free_block+0x94/0xc1 > [ 0.000000] [] do_tune_cpucache+0x10b/0x2bb > [ 0.000000] [] enable_cpucache+0x7b/0xa7 > [ 0.000000] [] kmem_cache_init_late+0x1f/0x61 > [ 0.000000] [] start_kernel+0x24c/0x363 > [ 0.000000] [] i386_start_kernel+0xa9/0xaf Reported-by: Fernando Lopez-Lezcano Acked-by: Pekka Enberg Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1311888176.2617.379.camel@laptop Signed-off-by: Ingo Molnar The commit moved init_lock_keys() before we build up the alien, so we failed to reclass it. Acked-by: Christoph Lameter Tested-by: Paul E. McKenney Signed-off-by: Michael Wang Signed-off-by: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- mm/slab.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index e901a36e2520..da2bb689a008 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1685,9 +1685,6 @@ void __init kmem_cache_init_late(void) g_cpucache_up = LATE; - /* Annotate slab for lockdep -- annotate the malloc caches */ - init_lock_keys(); - /* 6) resize the head arrays to their final sizes */ mutex_lock(&cache_chain_mutex); list_for_each_entry(cachep, &cache_chain, next) @@ -1695,6 +1692,9 @@ void __init kmem_cache_init_late(void) BUG(); mutex_unlock(&cache_chain_mutex); + /* Annotate slab for lockdep -- annotate the malloc caches */ + init_lock_keys(); + /* Done! */ g_cpucache_up = FULL; -- GitLab From 63b2f08626e0cacaa038c296df52a7cb504ae318 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Fri, 11 Nov 2011 17:26:44 -0700 Subject: [PATCH 0630/1799] intel-iommu: Default to non-coherent for domains unattached to iommus commit 2e12bc29fc5a12242d68e11875db3dd58efad9ff upstream. domain_update_iommu_coherency() currently defaults to setting domains as coherent when the domain is not attached to any iommus. This allows for a window in domain_context_mapping_one() where such a domain can update context entries non-coherently, and only after update the domain capability to clear iommu_coherency. This can be seen using KVM device assignment on VT-d systems that do not support coherency in the ecap register. When a device is added to a guest, a domain is created (iommu_coherency = 0), the device is attached, and ranges are mapped. If we then hot unplug the device, the coherency is updated and set to the default (1) since no iommus are attached to the domain. A subsequent attach of a device makes use of the same dmar domain (now marked coherent) updates context entries with coherency enabled, and only disables coherency as the last step in the process. To fix this, switch domain_update_iommu_coherency() to use the safer, non-coherent default for domains not attached to iommus. Signed-off-by: Alex Williamson Tested-by: Donald Dutile Acked-by: Donald Dutile Acked-by: Chris Wright Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel-iommu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 5fda348702c1..0d251d301be6 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -588,7 +588,9 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain) { int i; - domain->iommu_coherency = 1; + i = find_first_bit(domain->iommu_bmp, g_num_of_iommus); + + domain->iommu_coherency = i < g_num_of_iommus ? 1 : 0; for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) { if (!ecap_coherent(g_iommus[i]->ecap)) { -- GitLab From 63c486377c32dcfd5775c04b4d0cc5bc53990787 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 19 Aug 2012 19:32:27 -0300 Subject: [PATCH 0631/1799] media: rc: ite-cir: Initialise ite_dev::rdev earlier commit 4b961180ef275035b1538317ffd0e21e80e63e77 upstream. ite_dev::rdev is currently initialised in ite_probe() after rc_register_device() returns. If a newly registered device is opened quickly enough, we may enable interrupts and try to use ite_dev::rdev before it has been initialised. Move it up to the earliest point we can, right after calling rc_allocate_device(). Reported-and-tested-by: YunQiang Su Signed-off-by: Ben Hutchings Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/rc/ite-cir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index 0e49c99abf68..c06992e1320d 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -1473,6 +1473,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id rdev = rc_allocate_device(); if (!rdev) goto failure; + itdev->rdev = rdev; ret = -ENODEV; @@ -1604,7 +1605,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id if (ret) goto failure; - itdev->rdev = rdev; ite_pr(KERN_NOTICE, "driver has been successfully loaded\n"); return 0; -- GitLab From 991e71944f30eb7debd2d00abb749657b409b357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Sch=C3=A4fer?= Date: Sun, 9 Sep 2012 15:02:19 -0300 Subject: [PATCH 0632/1799] media: gspca_pac7302: add support for device 1ae7:2001 Speedlink Snappy Microphone SL-6825-SBK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 97d2fbf501e3cf105ac957086c7e40e62e15cdf8 upstream. Signed-off-by: Frank Schäfer Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/gspca/pac7302.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 30662fccb0cf..63f571b7cc22 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -945,6 +945,7 @@ static const struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x262a)}, {USB_DEVICE(0x093a, 0x262c)}, {USB_DEVICE(0x145f, 0x013c)}, + {USB_DEVICE(0x1ae7, 0x2001)}, /* SpeedLink Snappy Mic SL-6825-SBK */ {} }; MODULE_DEVICE_TABLE(usb, device_table); -- GitLab From 2006e6f75e7cb88e0508eeff066834c847ce91b3 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Mon, 16 Jul 2012 16:30:21 +0800 Subject: [PATCH 0633/1799] ACPI: run _OSC after ACPI_FULL_INITIALIZATION commit fc54ab72959edbf229b65ac74b2f122d799ca002 upstream. The _OSC method may exist in module level code, so it must be called after ACPI_FULL_INITIALIZATION On some new platforms with Zero-Power-Optical-Disk-Drive (ZPODD) support, this fix is necessary to save power. Signed-off-by: Lin Ming Tested-by: Aaron Lu Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/bus.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 3188da3df8da..cf02e971467f 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -954,14 +954,18 @@ static int __init acpi_bus_init(void) status = acpi_ec_ecdt_probe(); /* Ignore result. Not having an ECDT is not fatal. */ - acpi_bus_osc_support(); - status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); goto error1; } + /* + * _OSC method may exist in module level code, + * so it must be run after ACPI_FULL_INITIALIZATION + */ + acpi_bus_osc_support(); + /* * _PDC control method may load dynamic SSDT tables, * and we need to install the table handler before that. -- GitLab From 95482ba9494658e69aecf0f97b64f3f2ab82af62 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 20 Jun 2012 16:18:29 -0600 Subject: [PATCH 0634/1799] PCI: acpiphp: check whether _ADR evaluation succeeded commit dfb117b3e50c52c7b3416db4a4569224b8db80bb upstream. Check whether we evaluated _ADR successfully. Previously we ignored failure, so we would have used garbage data from the stack as the device and function number. We return AE_OK so that we ignore only this slot and continue looking for other slots. Found by Coverity (CID 113981). Signed-off-by: Bjorn Helgaas Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 806c44fa645a..09bf37721842 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -132,6 +132,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) return AE_OK; + status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); + if (ACPI_FAILURE(status)) { + warn("can't evaluate _ADR (%#x)\n", status); + return AE_OK; + } + + device = (adr >> 16) & 0xffff; + function = adr & 0xffff; + pdev = pbus->self; if (pdev && pci_is_pcie(pdev)) { tmp = acpi_find_root_bridge_handle(pdev); @@ -144,10 +153,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) } } - acpi_evaluate_integer(handle, "_ADR", NULL, &adr); - device = (adr >> 16) & 0xffff; - function = adr & 0xffff; - newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); if (!newfunc) return AE_NO_MEMORY; -- GitLab From 03c4441b88fd2614580eeda598623e2b21ec5822 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 7 Aug 2012 19:42:43 +0100 Subject: [PATCH 0635/1799] mfd: max8925: Move _IO resources out of ioport_ioresource commit bee6e1fa617b1fb7f6f91033428410e05f5ab0ed upstream. The removal of mach/io.h from most ARM platforms also set the range of valid IO ports to be empty for most platforms when previously any 32 bit integer had been valid. This makes it impossible to add IO resources as the added range is smaller than that of the root resource for IO ports. Since we're not really using IO memory at all fix this by defining our own root resource outside the normal tree and make that the parent of all IO resources. This also ensures we won't conflict with read IO ports if we ever run on a platform which happens to use them. Signed-off-by: Mark Brown Acked-by: Arnd Bergmann Acked-by: Haojian Zhuang Tested-by: Haojian Zhuang Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/max8925-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index ca881efedf75..746a59c29fed 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -18,12 +18,19 @@ #include #include +static struct resource io_parent = { + .start = 0, + .end = 0xffffffff, + .flags = IORESOURCE_IO, +}; + static struct resource backlight_resources[] = { { .name = "max8925-backlight", .start = MAX8925_WLED_MODE_CNTL, .end = MAX8925_WLED_CNTL, .flags = IORESOURCE_IO, + .parent = &io_parent, }, }; @@ -42,6 +49,7 @@ static struct resource touch_resources[] = { .start = MAX8925_TSC_IRQ, .end = MAX8925_ADC_RES_END, .flags = IORESOURCE_IO, + .parent = &io_parent, }, }; @@ -60,6 +68,7 @@ static struct resource power_supply_resources[] = { .start = MAX8925_CHG_IRQ1, .end = MAX8925_CHG_IRQ1_MASK, .flags = IORESOURCE_IO, + .parent = &io_parent, }, }; @@ -118,6 +127,7 @@ static struct mfd_cell onkey_devs[] = { .start = MAX8925_##_start, \ .end = MAX8925_##_end, \ .flags = IORESOURCE_IO, \ + .parent = &io_parent, \ } static struct resource regulator_resources[] = { -- GitLab From 6d36a9dd1dcdd053ab32f303b94cc1bae5a47f22 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Thu, 4 Oct 2012 17:13:18 -0700 Subject: [PATCH 0636/1799] lib/gcd.c: prevent possible div by 0 commit e96875677fb2b7cb739c5d7769824dff7260d31d upstream. Account for all properties when a and/or b are 0: gcd(0, 0) = 0 gcd(a, 0) = a gcd(0, b) = b Fixes no known problems in current kernels. Signed-off-by: Davidlohr Bueso Cc: Eric Dumazet Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- lib/gcd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/gcd.c b/lib/gcd.c index cce4f3cd14b3..3657f129d7b8 100644 --- a/lib/gcd.c +++ b/lib/gcd.c @@ -9,6 +9,9 @@ unsigned long gcd(unsigned long a, unsigned long b) if (a < b) swap(a, b); + + if (!b) + return a; while ((r = a % b) != 0) { a = b; b = r; -- GitLab From 3fc49ce67fefd3de38aa72a215eb1a2b68a7e89b Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 4 Oct 2012 17:12:23 -0700 Subject: [PATCH 0637/1799] kernel/sys.c: call disable_nonboot_cpus() in kernel_restart() commit f96972f2dc6365421cf2366ebd61ee4cf060c8d5 upstream. As kernel_power_off() calls disable_nonboot_cpus(), we may also want to have kernel_restart() call disable_nonboot_cpus(). Doing so can help machines that require boot cpu be the last alive cpu during reboot to survive with kernel restart. This fixes one reboot issue seen on imx6q (Cortex-A9 Quad). The machine requires that the restart routine be run on the primary cpu rather than secondary ones. Otherwise, the secondary core running the restart routine will fail to come to online after reboot. Signed-off-by: Shawn Guo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/sys.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/sys.c b/kernel/sys.c index e7006eb6c1e4..898a84c9df5b 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -365,6 +365,7 @@ EXPORT_SYMBOL(unregister_reboot_notifier); void kernel_restart(char *cmd) { kernel_restart_prepare(cmd); + disable_nonboot_cpus(); if (!cmd) printk(KERN_EMERG "Restarting system.\n"); else -- GitLab From 03f0a11553d06002af53f2d399da6c711e7d3b40 Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Thu, 4 Oct 2012 17:11:25 -0700 Subject: [PATCH 0638/1799] drivers/scsi/atp870u.c: fix bad use of udelay commit 0f6d93aa9d96cc9022b51bd10d462b03296be146 upstream. The ACARD driver calls udelay() with a value > 2000, which leads to to the following compilation error on ARM: ERROR: "__bad_udelay" [drivers/scsi/atp870u.ko] undefined! make[1]: *** [__modpost] Error 1 This is because udelay is defined on ARM, roughly speaking, as #define udelay(n) ((n) > 2000 ? __bad_udelay() : \ __const_udelay((n) * ((2199023U*HZ)>>11))) The argument to __const_udelay is the number of jiffies to wait divided by 4, but this does not work unless the multiplication does not overflow, and that is what the build error is designed to prevent. The intended behavior can be achieved by using mdelay to call udelay multiple times in a loop. [jrnieder@gmail.com: adding context] Signed-off-by: Martin Michlmayr Signed-off-by: Jonathan Nieder Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/atp870u.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 68ce08552f69..a540162ac59c 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -1173,7 +1173,16 @@ static void tscam(struct Scsi_Host *host) outw(val, tmport); outb(2, 0x80); TCM_SYNC: - udelay(0x800); + /* + * The funny division into multiple delays is to accomodate + * arches like ARM where udelay() multiplies its argument by + * a large number to initialize a loop counter. To avoid + * overflow, the maximum supported udelay is 2000 microseconds. + * + * XXX it would be more polite to find a way to use msleep() + */ + mdelay(2); + udelay(48); if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */ outw(0, tmport--); outb(0, tmport); -- GitLab From 0c0b534583fb1c02809e0a3978413fe79f7dac8f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 4 Oct 2012 17:11:16 -0700 Subject: [PATCH 0639/1799] drivers/dma/dmaengine.c: lower the priority of 'failed to get' dma channel message commit 0eb5a35801df3c438ce3fc91310a415ea4452c00 upstream. Do the same as commit a03a202e95fd ("dmaengine: failure to get a specific DMA channel is not critical") to get rid of the following messages during kernel boot: dmaengine_get: failed to get dma1chan0: (-22) dmaengine_get: failed to get dma1chan1: (-22) dmaengine_get: failed to get dma1chan2: (-22) dmaengine_get: failed to get dma1chan3: (-22) .. Signed-off-by: Fabio Estevam Cc: Vinod Koul Cc: Dan Williams Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/dma/dmaengine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 2397f6f451b1..6c87d676c62d 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -578,7 +578,7 @@ void dmaengine_get(void) list_del_rcu(&device->global_node); break; } else if (err) - pr_err("%s: failed to get %s: (%d)\n", + pr_debug("%s: failed to get %s: (%d)\n", __func__, dma_chan_name(chan), err); } } -- GitLab From 9825e3158e302980b71c54b72e90f0624e1cfab3 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 4 Oct 2012 12:03:25 +0930 Subject: [PATCH 0640/1799] lguest: fix occasional crash in example launcher. commit ca16f580a5db7e60bfafe59a50bb133bd3347491 upstream. We usually got away with ->next on the final entry being NULL, but it finally bit me. Signed-off-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- tools/lguest/lguest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c index f759f4f097c7..fd2f9221b241 100644 --- a/tools/lguest/lguest.c +++ b/tools/lguest/lguest.c @@ -1299,6 +1299,7 @@ static struct device *new_device(const char *name, u16 type) dev->feature_len = 0; dev->num_vq = 0; dev->running = false; + dev->next = NULL; /* * Append to device list. Prepending to a single-linked list is -- GitLab From ed55202fda5c68e44464cd5afdc819a8721b601a Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Mon, 17 Sep 2012 04:34:28 +0000 Subject: [PATCH 0641/1799] powerpc/eeh: Fix crash on converting OF node to edev commit 1e38b7140185e384da216aff66a711df09b5afc9 upstream. The kernel crash was reported by Alexy. He was testing some feature with private kernel, in which Alexy added some code in pci_pm_reset() to read the CSR after writting it. The bug could be reproduced on Fiber Channel card (Fibre Channel: Emulex Corporation Saturn-X: LightPulse Fibre Channel Host Adapter (rev 03)) by the following commands. # echo 1 > /sys/devices/pci0004:01/0004:01:00.0/reset # rmmod lpfc # modprobe lpfc The history behind the test case is that those additional config space reading operations in pci_pm_reset() would cause EEH error, but we didn't detect EEH error until "modprobe lpfc". For the case, all the PCI devices on PCI bus (0004:01) were removed and added after PE reset. Then the EEH devices would be figured out again based on the OF nodes. Unfortunately, there were some child OF nodes under PCI device (0004:01:00.0), but they didn't have attached PCI_DN since they're invisible from PCI domain. However, we were still trying to convert OF node to EEH device without checking on the attached PCI_DN. Eventually, it caused the kernel crash as follows: Unable to handle kernel paging request for data at address 0x00000030 Faulting instruction address: 0xc00000000004d888 cpu 0x0: Vector: 300 (Data Access) at [c000000fc797b950] pc: c00000000004d888: .eeh_add_device_tree_early+0x78/0x140 lr: c00000000004d880: .eeh_add_device_tree_early+0x70/0x140 sp: c000000fc797bbd0 msr: 8000000000009032 dar: 30 dsisr: 40000000 current = 0xc000000fc78d9f70 paca = 0xc00000000edb0000 softe: 0 irq_happened: 0x00 pid = 2951, comm = eehd enter ? for help [c000000fc797bc50] c00000000004d848 .eeh_add_device_tree_early+0x38/0x140 [c000000fc797bcd0] c00000000004d848 .eeh_add_device_tree_early+0x38/0x140 [c000000fc797bd50] c000000000051b54 .pcibios_add_pci_devices+0x34/0x190 [c000000fc797bde0] c00000000004fb10 .eeh_reset_device+0x100/0x160 [c000000fc797be70] c0000000000502dc .eeh_handle_event+0x19c/0x300 [c000000fc797bf00] c000000000050570 .eeh_event_handler+0x130/0x1a0 [c000000fc797bf90] c000000000020138 .kernel_thread+0x54/0x70 The patch changes of_node_to_eeh_dev() and just returns NULL if the passed OF node doesn't have attached PCI_DN. Reported-by: Alexey Kardashevskiy Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/include/asm/pci-bridge.h | 8 ++++++++ arch/powerpc/platforms/pseries/eeh.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index ac39e6a3b25a..2974edd999da 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -181,6 +181,14 @@ static inline int pci_device_from_OF_node(struct device_node *np, #if defined(CONFIG_EEH) static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn) { + /* + * For those OF nodes whose parent isn't PCI bridge, they + * don't have PCI_DN actually. So we have to skip them for + * any EEH operations. + */ + if (!dn || !PCI_DN(dn)) + return NULL; + return PCI_DN(dn)->edev; } #endif diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index a75e37dc41aa..41d4b163c063 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -1029,7 +1029,7 @@ static void eeh_add_device_early(struct device_node *dn) { struct pci_controller *phb; - if (!dn || !of_node_to_eeh_dev(dn)) + if (!of_node_to_eeh_dev(dn)) return; phb = of_node_to_eeh_dev(dn)->phb; -- GitLab From a332509fcd9064cae48d26e09aec46e08247223b Mon Sep 17 00:00:00 2001 From: Alexandre Bounine Date: Thu, 4 Oct 2012 17:15:48 -0700 Subject: [PATCH 0642/1799] rapidio/rionet: fix multicast packet transmit logic commit 7c4a6106d6451fc03c491e61df37c044505d843a upstream. Fix multicast packet transmit logic to account for repetitive transmission of single skb: - correct check for available buffers (this bug may produce NULL pointer crash dump in case of heavy traffic); - update skb user count (incorrect user counter causes a warning dump from net_tx_action routine during multicast transfers in systems with three or more rionet participants). Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: David S. Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/net/rionet.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 91d25888a1b9..1470d3e86e3c 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -79,6 +79,7 @@ static int rionet_capable = 1; * on system trade-offs. */ static struct rio_dev **rionet_active; +static int nact; /* total number of active rionet peers */ #define is_rionet_capable(src_ops, dst_ops) \ ((src_ops & RIO_SRC_OPS_DATA_MSG) && \ @@ -175,6 +176,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct ethhdr *eth = (struct ethhdr *)skb->data; u16 destid; unsigned long flags; + int add_num = 1; local_irq_save(flags); if (!spin_trylock(&rnet->tx_lock)) { @@ -182,7 +184,10 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_LOCKED; } - if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) { + if (is_multicast_ether_addr(eth->h_dest)) + add_num = nact; + + if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) { netif_stop_queue(ndev); spin_unlock_irqrestore(&rnet->tx_lock, flags); printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n", @@ -191,11 +196,16 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) } if (is_multicast_ether_addr(eth->h_dest)) { + int count = 0; for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size); i++) - if (rionet_active[i]) + if (rionet_active[i]) { rionet_queue_tx_msg(skb, ndev, rionet_active[i]); + if (count) + atomic_inc(&skb->users); + count++; + } } else if (RIONET_MAC_MATCH(eth->h_dest)) { destid = RIONET_GET_DESTID(eth->h_dest); if (rionet_active[destid]) @@ -220,14 +230,17 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u if (info == RIONET_DOORBELL_JOIN) { if (!rionet_active[sid]) { list_for_each_entry(peer, &rionet_peers, node) { - if (peer->rdev->destid == sid) + if (peer->rdev->destid == sid) { rionet_active[sid] = peer->rdev; + nact++; + } } rio_mport_send_doorbell(mport, sid, RIONET_DOORBELL_JOIN); } } else if (info == RIONET_DOORBELL_LEAVE) { rionet_active[sid] = NULL; + nact--; } else { if (netif_msg_intr(rnet)) printk(KERN_WARNING "%s: unhandled doorbell\n", @@ -523,6 +536,7 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) rc = rionet_setup_netdev(rdev->net->hport, ndev); rionet_check = 1; + nact = 0; } /* -- GitLab From 24a0c2063c805e9cf1f3f418bb7f444b5b3f0e4e Mon Sep 17 00:00:00 2001 From: Feng Hong Date: Wed, 19 Sep 2012 14:16:00 +0200 Subject: [PATCH 0643/1799] PM / Sleep: use resume event when call dpm_resume_early commit 997a031107ec962967ce36db9bc500f1fad491c1 upstream. When dpm_suspend_noirq fail, state is PMSG_SUSPEND, should change to PMSG_RESUME when dpm_resume_early is called Signed-off-by: Feng Hong Signed-off-by: Raul Xiong Signed-off-by: Neil Zhang Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index f7eff25ffe49..ebc272f8cf28 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -984,7 +984,7 @@ int dpm_suspend_end(pm_message_t state) error = dpm_suspend_noirq(state); if (error) { - dpm_resume_early(state); + dpm_resume_early(resume_event(state)); return error; } -- GitLab From 66307aef43a3a51cccf03f4ca8063cfce1bd4ac1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 3 Aug 2012 10:30:45 -0700 Subject: [PATCH 0644/1799] workqueue: add missing smp_wmb() in process_one_work() commit 959d1af8cffc8fd38ed53e8be1cf4ab8782f9c00 upstream. WORK_STRUCT_PENDING is used to claim ownership of a work item and process_one_work() releases it before starting execution. When someone else grabs PENDING, all pre-release updates to the work item should be visible and all updates made by the new owner should happen afterwards. Grabbing PENDING uses test_and_set_bit() and thus has a full barrier; however, clearing doesn't have a matching wmb. Given the preceding spin_unlock and use of clear_bit, I don't believe this can be a problem on an actual machine and there hasn't been any related report but it still is theretically possible for clear_pending to permeate upwards and happen before work->entry update. Add an explicit smp_wmb() before work_clear_pending(). Signed-off-by: Tejun Heo Cc: Oleg Nesterov Signed-off-by: Greg Kroah-Hartman --- kernel/workqueue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 7584322349c1..56f793d044a5 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1864,7 +1864,9 @@ __acquires(&gcwq->lock) spin_unlock_irq(&gcwq->lock); + smp_wmb(); /* paired with test_and_set_bit(PENDING) */ work_clear_pending(work); + lock_map_acquire_read(&cwq->wq->lockdep_map); lock_map_acquire(&lockdep_map); trace_workqueue_execute_start(work); -- GitLab From 0699c6dd66e7083f837cfe620837ddcf10649b89 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Sat, 18 Aug 2012 22:29:40 -0400 Subject: [PATCH 0645/1799] jbd2: don't write superblock when if its empty commit eeecef0af5ea4efd763c9554cf2bd80fc4a0efd3 upstream. This sequence: # truncate --size=1g fsfile # mkfs.ext4 -F fsfile # mount -o loop,ro fsfile /mnt # umount /mnt # dmesg | tail results in an IO error when unmounting the RO filesystem: [ 318.020828] Buffer I/O error on device loop1, logical block 196608 [ 318.027024] lost page write due to I/O error on loop1 [ 318.032088] JBD2: Error -5 detected when updating journal superblock for loop1-8. This was a regression introduced by commit 24bcc89c7e7c: "jbd2: split updating of journal superblock and marking journal empty". Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/jbd2/journal.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 9956ac68b72b..e5bfb1150cf5 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1317,6 +1317,11 @@ static void jbd2_mark_journal_empty(journal_t *journal) BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); read_lock(&journal->j_state_lock); + /* Is it already empty? */ + if (sb->s_start == 0) { + read_unlock(&journal->j_state_lock); + return; + } jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n", journal->j_tail_sequence); -- GitLab From e878ead68937be79e530ea9bf568766ab454e3ee Mon Sep 17 00:00:00 2001 From: Yuta Ando Date: Mon, 1 Oct 2012 23:24:30 +0900 Subject: [PATCH 0646/1799] localmodconfig: Fix localyesconfig to set to 'y' not 'm' commit 4eae518d4b01b0cbf2f0d8edb5a6f3d6245ee8fb upstream. The kbuild target 'localyesconfig' has been same as 'localmodconfig' since the commit 50bce3e "kconfig/streamline_config.pl: merge local{mod,yes}config". The commit expects this script generates different configure depending on target, but it was not yet implemented. So I added code that sets to 'yes' when target is 'localyesconfig'. Link: http://lkml.kernel.org/r/1349101470-12243-1-git-send-email-yuta.and@gmail.com Signed-off-by: Yuta Ando Cc: linux-kbuild@vger.kernel.org Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- scripts/kconfig/streamline_config.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index bccf07ddd0b6..3346f4236ebe 100644 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -463,6 +463,8 @@ while() { if (defined($configs{$1})) { if ($localyesconfig) { $setconfigs{$1} = 'y'; + print "$1=y\n"; + next; } else { $setconfigs{$1} = $2; } -- GitLab From 657197486950474bf30290344339fd0914fe99c9 Mon Sep 17 00:00:00 2001 From: Michal Schmidt Date: Thu, 13 Sep 2012 12:59:44 +0000 Subject: [PATCH 0647/1799] bnx2x: fix rx checksum validation for IPv6 [ Upstream commit e488921f44765e8ab6c48ca35e3f6b78df9819df ] Commit d6cb3e41 "bnx2x: fix checksum validation" caused a performance regression for IPv6. Rx checksum offload does not work. IPv6 packets are passed to the stack with CHECKSUM_NONE. The hardware obviously cannot perform IP checksum validation for IPv6, because there is no checksum in the IPv6 header. This should not prevent us from setting CHECKSUM_UNNECESSARY. Tested on BCM57711. Signed-off-by: Michal Schmidt Acked-by: Eric Dumazet Acked-by: Eilon Greenstein Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 41bb34fcf687..acd824660367 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -571,14 +571,16 @@ static inline void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, static void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe, struct bnx2x_fastpath *fp) { - /* Do nothing if no IP/L4 csum validation was done */ - + /* Do nothing if no L4 csum validation was done. + * We do not check whether IP csum was validated. For IPv4 we assume + * that if the card got as far as validating the L4 csum, it also + * validated the IP csum. IPv6 has no IP csum. + */ if (cqe->fast_path_cqe.status_flags & - (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG | - ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)) + ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) return; - /* If both IP/L4 validation were done, check if an error was found. */ + /* If L4 validation was done, check if an error was found. */ if (cqe->fast_path_cqe.type_error_flags & (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG | -- GitLab From 20eb20851385e53d27dff9ed79c4e68e58e3d9da Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Tue, 4 Sep 2012 00:03:29 +0000 Subject: [PATCH 0648/1799] xfrm: Workaround incompatibility of ESN and async crypto [ Upstream commit 3b59df46a449ec9975146d71318c4777ad086744 ] ESN for esp is defined in RFC 4303. This RFC assumes that the sequence number counters are always up to date. However, this is not true if an async crypto algorithm is employed. If the sequence number counters are not up to date on sequence number check, we may incorrectly update the upper 32 bit of the sequence number. This leads to a DOS. We workaround this by comparing the upper sequence number, (used for authentication) with the upper sequence number computed after the async processing. We drop the packet if these numbers are different. To do this, we introduce a recheck function that does this check in the ESN case. Signed-off-by: Steffen Klassert Acked-by: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/xfrm.h | 3 +++ net/xfrm/xfrm_input.c | 2 +- net/xfrm/xfrm_replay.c | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 96239e78e621..9f7e94ba6696 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -269,6 +269,9 @@ struct xfrm_replay { int (*check)(struct xfrm_state *x, struct sk_buff *skb, __be32 net_seq); + int (*recheck)(struct xfrm_state *x, + struct sk_buff *skb, + __be32 net_seq); void (*notify)(struct xfrm_state *x, int event); int (*overflow)(struct xfrm_state *x, struct sk_buff *skb); }; diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 54a0dc2e2f8d..ab2bb42fe094 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -212,7 +212,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) /* only the first xfrm gets the encap type */ encap_type = 0; - if (async && x->repl->check(x, skb, seq)) { + if (async && x->repl->recheck(x, skb, seq)) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); goto drop_unlock; } diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 2f6d11d04a2b..3efb07d3eb27 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c @@ -420,6 +420,18 @@ static int xfrm_replay_check_esn(struct xfrm_state *x, return -EINVAL; } +static int xfrm_replay_recheck_esn(struct xfrm_state *x, + struct sk_buff *skb, __be32 net_seq) +{ + if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi != + htonl(xfrm_replay_seqhi(x, net_seq)))) { + x->stats.replay_window++; + return -EINVAL; + } + + return xfrm_replay_check_esn(x, skb, net_seq); +} + static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) { unsigned int bitnr, nr, i; @@ -479,6 +491,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) static struct xfrm_replay xfrm_replay_legacy = { .advance = xfrm_replay_advance, .check = xfrm_replay_check, + .recheck = xfrm_replay_check, .notify = xfrm_replay_notify, .overflow = xfrm_replay_overflow, }; @@ -486,6 +499,7 @@ static struct xfrm_replay xfrm_replay_legacy = { static struct xfrm_replay xfrm_replay_bmp = { .advance = xfrm_replay_advance_bmp, .check = xfrm_replay_check_bmp, + .recheck = xfrm_replay_check_bmp, .notify = xfrm_replay_notify_bmp, .overflow = xfrm_replay_overflow_bmp, }; @@ -493,6 +507,7 @@ static struct xfrm_replay xfrm_replay_bmp = { static struct xfrm_replay xfrm_replay_esn = { .advance = xfrm_replay_advance_esn, .check = xfrm_replay_check_esn, + .recheck = xfrm_replay_recheck_esn, .notify = xfrm_replay_notify_bmp, .overflow = xfrm_replay_overflow_esn, }; -- GitLab From 555144b63d57c0df7a2677868f83957a34135207 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Thu, 13 Sep 2012 11:41:26 +0000 Subject: [PATCH 0649/1799] xfrm_user: return error pointer instead of NULL [ Upstream commit 864745d291b5ba80ea0bd0edcbe67273de368836 ] When dump_one_state() returns an error, e.g. because of a too small buffer to dump the whole xfrm state, xfrm_state_netlink() returns NULL instead of an error pointer. But its callers expect an error pointer and therefore continue to operate on a NULL skbuff. This could lead to a privilege escalation (execution of user code in kernel context) if the attacker has CAP_NET_ADMIN and is able to map address 0. Signed-off-by: Mathias Krause Acked-by: Steffen Klassert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/xfrm/xfrm_user.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 7128dde0fe1a..c1537f0b4062 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -862,6 +862,7 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, { struct xfrm_dump_info info; struct sk_buff *skb; + int err; skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); if (!skb) @@ -872,9 +873,10 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, info.nlmsg_seq = seq; info.nlmsg_flags = 0; - if (dump_one_state(x, 0, &info)) { + err = dump_one_state(x, 0, &info); + if (err) { kfree_skb(skb); - return NULL; + return ERR_PTR(err); } return skb; -- GitLab From f38b334adca51bbf18ad549a9736c0f86bb4a375 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Fri, 14 Sep 2012 09:58:32 +0000 Subject: [PATCH 0650/1799] xfrm_user: return error pointer instead of NULL #2 [ Upstream commit c25463722509fef0ed630b271576a8c9a70236f3 ] When dump_one_policy() returns an error, e.g. because of a too small buffer to dump the whole xfrm policy, xfrm_policy_netlink() returns NULL instead of an error pointer. But its caller expects an error pointer and therefore continues to operate on a NULL skbuff. Signed-off-by: Mathias Krause Acked-by: Steffen Klassert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/xfrm/xfrm_user.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index c1537f0b4062..4cae47d8dc41 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1531,6 +1531,7 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, { struct xfrm_dump_info info; struct sk_buff *skb; + int err; skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!skb) @@ -1541,9 +1542,10 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, info.nlmsg_seq = seq; info.nlmsg_flags = 0; - if (dump_one_policy(xp, dir, 0, &info) < 0) { + err = dump_one_policy(xp, dir, 0, &info); + if (err) { kfree_skb(skb); - return NULL; + return ERR_PTR(err); } return skb; -- GitLab From a91af73f445cacfb0db4df3eb2e3d0ddeff43893 Mon Sep 17 00:00:00 2001 From: Li RongQing Date: Mon, 17 Sep 2012 22:40:10 +0000 Subject: [PATCH 0651/1799] xfrm: fix a read lock imbalance in make_blackhole [ Upstream commit 433a19548061bb5457b6ab77ed7ea58ca6e43ddb ] if xfrm_policy_get_afinfo returns 0, it has already released the read lock, xfrm_policy_put_afinfo should not be called again. Signed-off-by: Li RongQing Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/xfrm/xfrm_policy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index a15d2a03172a..71c80c763d57 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1761,7 +1761,7 @@ static struct dst_entry *make_blackhole(struct net *net, u16 family, if (!afinfo) { dst_release(dst_orig); - ret = ERR_PTR(-EINVAL); + return ERR_PTR(-EINVAL); } else { ret = afinfo->blackhole_route(net, dst_orig); } -- GitLab From 37d61a27a59671d88279dcc4d331f950d4901d4d Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 19 Sep 2012 11:33:38 +0000 Subject: [PATCH 0652/1799] xfrm_user: fix info leak in copy_to_user_auth() [ Upstream commit 4c87308bdea31a7b4828a51f6156e6f721a1fcc9 ] copy_to_user_auth() fails to initialize the remainder of alg_name and therefore discloses up to 54 bytes of heap memory via netlink to userland. Use strncpy() instead of strcpy() to fill the trailing bytes of alg_name with null bytes. Signed-off-by: Mathias Krause Acked-by: Steffen Klassert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/xfrm/xfrm_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 4cae47d8dc41..f5936d84655c 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -742,7 +742,7 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb) return -EMSGSIZE; algo = nla_data(nla); - strcpy(algo->alg_name, auth->alg_name); + strncpy(algo->alg_name, auth->alg_name, sizeof(algo->alg_name)); memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8); algo->alg_key_len = auth->alg_key_len; -- GitLab From d5f1f7c230df5f2a198fb231547f1b298594c709 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 19 Sep 2012 11:33:39 +0000 Subject: [PATCH 0653/1799] xfrm_user: fix info leak in copy_to_user_state() [ Upstream commit f778a636713a435d3a922c60b1622a91136560c1 ] The memory reserved to dump the xfrm state includes the padding bytes of struct xfrm_usersa_info added by the compiler for alignment (7 for amd64, 3 for i386). Add an explicit memset(0) before filling the buffer to avoid the info leak. Signed-off-by: Mathias Krause Acked-by: Steffen Klassert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/xfrm/xfrm_user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index f5936d84655c..9e5c07eb292b 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -689,6 +689,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) { + memset(p, 0, sizeof(*p)); memcpy(&p->id, &x->id, sizeof(p->id)); memcpy(&p->sel, &x->sel, sizeof(p->sel)); memcpy(&p->lft, &x->lft, sizeof(p->lft)); -- GitLab From 97f96eab8eb32f3178439f73acca4e286c091435 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 19 Sep 2012 11:33:40 +0000 Subject: [PATCH 0654/1799] xfrm_user: fix info leak in copy_to_user_policy() [ Upstream commit 7b789836f434c87168eab067cfbed1ec4783dffd ] The memory reserved to dump the xfrm policy includes multiple padding bytes added by the compiler for alignment (padding bytes in struct xfrm_selector and struct xfrm_userpolicy_info). Add an explicit memset(0) before filling the buffer to avoid the heap info leak. Signed-off-by: Mathias Krause Acked-by: Steffen Klassert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/xfrm/xfrm_user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 9e5c07eb292b..4ec3ccd7d517 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1300,6 +1300,7 @@ static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir) { + memset(p, 0, sizeof(*p)); memcpy(&p->sel, &xp->selector, sizeof(p->sel)); memcpy(&p->lft, &xp->lft, sizeof(p->lft)); memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft)); -- GitLab From 0c5e37586ef83845acbae1738e693bc97c12d4c3 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 19 Sep 2012 11:33:41 +0000 Subject: [PATCH 0655/1799] xfrm_user: fix info leak in copy_to_user_tmpl() [ Upstream commit 1f86840f897717f86d523a13e99a447e6a5d2fa5 ] The memory used for the template copy is a local stack variable. As struct xfrm_user_tmpl contains multiple holes added by the compiler for alignment, not initializing the memory will lead to leaking stack bytes to userland. Add an explicit memset(0) to avoid the info leak. Initial version of the patch by Brad Spengler. Signed-off-by: Mathias Krause Cc: Brad Spengler Acked-by: Steffen Klassert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/xfrm/xfrm_user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 4ec3ccd7d517..74ea70f5f358 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1405,6 +1405,7 @@ static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb) struct xfrm_user_tmpl *up = &vec[i]; struct xfrm_tmpl *kp = &xp->xfrm_vec[i]; + memset(up, 0, sizeof(*up)); memcpy(&up->id, &kp->id, sizeof(up->id)); up->family = kp->encap_family; memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr)); -- GitLab From 743b911d8b2214bfa9ecd1631edbe6f61f8fdced Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 19 Sep 2012 11:33:43 +0000 Subject: [PATCH 0656/1799] xfrm_user: don't copy esn replay window twice for new states [ Upstream commit e3ac104d41a97b42316915020ba228c505447d21 ] The ESN replay window was already fully initialized in xfrm_alloc_replay_state_esn(). No need to copy it again. Signed-off-by: Mathias Krause Cc: Steffen Klassert Acked-by: Steffen Klassert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/xfrm/xfrm_user.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 74ea70f5f358..e0972b26a598 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -442,10 +442,11 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * * somehow made shareable and move it to xfrm_state.c - JHS * */ -static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs) +static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs, + int update_esn) { struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; - struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; + struct nlattr *re = update_esn ? attrs[XFRMA_REPLAY_ESN_VAL] : NULL; struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; struct nlattr *et = attrs[XFRMA_ETIMER_THRESH]; struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; @@ -555,7 +556,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, goto error; /* override default values from above */ - xfrm_update_ae_params(x, attrs); + xfrm_update_ae_params(x, attrs, 0); return x; @@ -1801,7 +1802,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, goto out; spin_lock_bh(&x->lock); - xfrm_update_ae_params(x, attrs); + xfrm_update_ae_params(x, attrs, 1); spin_unlock_bh(&x->lock); c.event = nlh->nlmsg_type; -- GitLab From 53bf1469924e07385b4493d3cbd78551d4afaaa3 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Thu, 20 Sep 2012 10:01:49 +0000 Subject: [PATCH 0657/1799] xfrm_user: ensure user supplied esn replay window is valid [ Upstream commit ecd7918745234e423dd87fcc0c077da557909720 ] The current code fails to ensure that the netlink message actually contains as many bytes as the header indicates. If a user creates a new state or updates an existing one but does not supply the bytes for the whole ESN replay window, the kernel copies random heap bytes into the replay bitmap, the ones happen to follow the XFRMA_REPLAY_ESN_VAL netlink attribute. This leads to following issues: 1. The replay window has random bits set confusing the replay handling code later on. 2. A malicious user could use this flaw to leak up to ~3.5kB of heap memory when she has access to the XFRM netlink interface (requires CAP_NET_ADMIN). Known users of the ESN replay window are strongSwan and Steffen's iproute2 patch (). The latter uses the interface with a bitmap supplied while the former does not. strongSwan is therefore prone to run into issue 1. To fix both issues without breaking existing userland allow using the XFRMA_REPLAY_ESN_VAL netlink attribute with either an empty bitmap or a fully specified one. For the former case we initialize the in-kernel bitmap with zero, for the latter we copy the user supplied bitmap. For state updates the full bitmap must be supplied. To prevent overflows in the bitmap length calculation the maximum size of bmp_len is limited to 128 by this patch -- resulting in a maximum replay window of 4096 packets. This should be sufficient for all real life scenarios (RFC 4303 recommends a default replay window size of 64). Signed-off-by: Mathias Krause Cc: Steffen Klassert Cc: Martin Willi Cc: Ben Hutchings Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/xfrm.h | 2 ++ net/xfrm/xfrm_user.c | 31 +++++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 22e61fdf75a2..28e493b5b94c 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -84,6 +84,8 @@ struct xfrm_replay_state { __u32 bitmap; }; +#define XFRMA_REPLAY_ESN_MAX 4096 + struct xfrm_replay_state_esn { unsigned int bmp_len; __u32 oseq; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index e0972b26a598..c8b903df943f 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -123,9 +123,21 @@ static inline int verify_replay(struct xfrm_usersa_info *p, struct nlattr **attrs) { struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; + struct xfrm_replay_state_esn *rs; - if ((p->flags & XFRM_STATE_ESN) && !rt) - return -EINVAL; + if (p->flags & XFRM_STATE_ESN) { + if (!rt) + return -EINVAL; + + rs = nla_data(rt); + + if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8) + return -EINVAL; + + if (nla_len(rt) < xfrm_replay_state_esn_len(rs) && + nla_len(rt) != sizeof(*rs)) + return -EINVAL; + } if (!rt) return 0; @@ -370,14 +382,15 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es struct nlattr *rp) { struct xfrm_replay_state_esn *up; + int ulen; if (!replay_esn || !rp) return 0; up = nla_data(rp); + ulen = xfrm_replay_state_esn_len(up); - if (xfrm_replay_state_esn_len(replay_esn) != - xfrm_replay_state_esn_len(up)) + if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen) return -EINVAL; return 0; @@ -388,22 +401,28 @@ static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn struct nlattr *rta) { struct xfrm_replay_state_esn *p, *pp, *up; + int klen, ulen; if (!rta) return 0; up = nla_data(rta); + klen = xfrm_replay_state_esn_len(up); + ulen = nla_len(rta) >= klen ? klen : sizeof(*up); - p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); + p = kzalloc(klen, GFP_KERNEL); if (!p) return -ENOMEM; - pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); + pp = kzalloc(klen, GFP_KERNEL); if (!pp) { kfree(p); return -ENOMEM; } + memcpy(p, up, ulen); + memcpy(pp, up, ulen); + *replay_esn = p; *preplay_esn = pp; -- GitLab From f7ee46fb594cf2c3dd3a96457a028336fb34d5a6 Mon Sep 17 00:00:00 2001 From: htbegin Date: Mon, 1 Oct 2012 16:42:43 +0000 Subject: [PATCH 0658/1799] net: ethernet: davinci_cpdma: decrease the desc count when cleaning up the remaining packets [ Upstream commit ffb5ba90017505a19e238e986e6d33f09e4df765 ] chan->count is used by rx channel. If the desc count is not updated by the clean up loop in cpdma_chan_stop, the value written to the rxfree register in cpdma_chan_start will be incorrect. Signed-off-by: Tao Hou Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/ti/davinci_cpdma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index 34558766cbf0..06f2b495428c 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -851,6 +851,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan) next_dma = desc_read(desc, hw_next); chan->head = desc_from_phys(pool, next_dma); + chan->count--; chan->stats.teardown_dequeue++; /* issue callback without locks held */ -- GitLab From ec7fd138e2e690efff5eaec279ebc2c4740589e4 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 10 Sep 2012 14:06:58 +0200 Subject: [PATCH 0659/1799] ixp4xx_hss: fix build failure due to missing linux/module.h inclusion [ Upstream commit 0b836ddde177bdd5790ade83772860940bd481ea ] Commit 36a1211970193ce215de50ed1e4e1272bc814df1 (netprio_cgroup.h: dont include module.h from other includes) made the following build error on ixp4xx_hss pop up: CC [M] drivers/net/wan/ixp4xx_hss.o drivers/net/wan/ixp4xx_hss.c:1412:20: error: expected ';', ',' or ')' before string constant drivers/net/wan/ixp4xx_hss.c:1413:25: error: expected ';', ',' or ')' before string constant drivers/net/wan/ixp4xx_hss.c:1414:21: error: expected ';', ',' or ')' before string constant drivers/net/wan/ixp4xx_hss.c:1415:19: error: expected ';', ',' or ')' before string constant make[8]: *** [drivers/net/wan/ixp4xx_hss.o] Error 1 This was previously hidden because ixp4xx_hss includes linux/hdlc.h which includes linux/netdevice.h which includes linux/netprio_cgroup.h which used to include linux/module.h. The real issue was actually present since the initial commit that added this driver since it uses macros from linux/module.h without including this file. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/wan/ixp4xx_hss.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index aaaca9aa2293..3f575afd8cfc 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -10,6 +10,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include -- GitLab From 6720119023f635bd8c285530a7092716c23bdfcc Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Fri, 14 Sep 2012 05:50:03 +0000 Subject: [PATCH 0660/1799] netxen: check for root bus in netxen_mask_aer_correctable [ Upstream commit e4d1aa40e363ed3e0486aeeeb0d173f7f822737e ] Add a check if pdev->bus->self == NULL (root bus). When attaching a netxen NIC to a VM it can be on the root bus and the guest would crash in netxen_mask_aer_correctable() because of a NULL pointer dereference if CONFIG_PCIEAER is present. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 65a718f9ccd3..22b399a9db90 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1370,6 +1370,10 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter) struct pci_dev *root = pdev->bus->self; u32 aer_pos; + /* root bus? */ + if (!root) + return; + if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM && adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP) return; -- GitLab From 52ee75479f2aea816d8bb6a9d6caf5c1ebb36724 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 11 Sep 2012 13:11:12 +0000 Subject: [PATCH 0661/1799] net-sched: sch_cbq: avoid infinite loop [ Upstream commit bdfc87f7d1e253e0a61e2fc6a75ea9d76f7fc03a ] Its possible to setup a bad cbq configuration leading to an infinite loop in cbq_classify() DEV_OUT=eth0 ICMP="match ip protocol 1 0xff" U32="protocol ip u32" DST="match ip dst" tc qdisc add dev $DEV_OUT root handle 1: cbq avpkt 1000 \ bandwidth 100mbit tc class add dev $DEV_OUT parent 1: classid 1:1 cbq \ rate 512kbit allot 1500 prio 5 bounded isolated tc filter add dev $DEV_OUT parent 1: prio 3 $U32 \ $ICMP $DST 192.168.3.234 flowid 1: Reported-by: Denys Fedoryschenko Tested-by: Denys Fedoryschenko Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/sch_cbq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 24d94c097b35..599f67ada1ed 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -250,10 +250,11 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) else if ((cl = defmap[res.classid & TC_PRIO_MAX]) == NULL) cl = defmap[TC_PRIO_BESTEFFORT]; - if (cl == NULL || cl->level >= head->level) + if (cl == NULL) goto fallback; } - + if (cl->level >= head->level) + goto fallback; #ifdef CONFIG_NET_CLS_ACT switch (result) { case TC_ACT_QUEUED: -- GitLab From 5ee708f19bd6a1da1d7bab5916382bbbfba4edbb Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Sat, 15 Sep 2012 00:41:35 +0000 Subject: [PATCH 0662/1799] pkt_sched: fix virtual-start-time update in QFQ [ Upstream commit 71261956973ba9e0637848a5adb4a5819b4bae83 ] If the old timestamps of a class, say cl, are stale when the class becomes active, then QFQ may assign to cl a much higher start time than the maximum value allowed. This may happen when QFQ assigns to the start time of cl the finish time of a group whose classes are characterized by a higher value of the ratio max_class_pkt/weight_of_the_class with respect to that of cl. Inserting a class with a too high start time into the bucket list corrupts the data structure and may eventually lead to crashes. This patch limits the maximum start time assigned to a class. Signed-off-by: Paolo Valente Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/sch_qfq.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index e68cb440756a..cdd474afbbd2 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -830,7 +830,10 @@ static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl) if (mask) { struct qfq_group *next = qfq_ffs(q, mask); if (qfq_gt(roundedF, next->F)) { - cl->S = next->F; + if (qfq_gt(limit, next->F)) + cl->S = next->F; + else /* preserve timestamp correctness */ + cl->S = limit; return; } } -- GitLab From 97d5d3295198279362552d9b810c088d3410da23 Mon Sep 17 00:00:00 2001 From: Lennart Sorensen Date: Fri, 7 Sep 2012 12:14:02 +0000 Subject: [PATCH 0663/1799] sierra_net: Endianess bug fix. [ Upstream commit 2120c52da6fe741454a60644018ad2a6abd957ac ] I discovered I couldn't get sierra_net to work on a powerpc. Turns out the firmware attribute check assumes the system is little endian and hence fails because the attributes is a 16 bit value. Signed-off-by: Len Sorensen Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/sierra_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index cc9776c2a39a..8789bc58b176 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -678,7 +678,7 @@ static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap) return -EIO; } - *datap = *attrdata; + *datap = le16_to_cpu(*attrdata); kfree(attrdata); return result; -- GitLab From 2ab08687cf48805c5abd0f9a785e09181eda9492 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 2 Oct 2012 06:14:17 +0000 Subject: [PATCH 0664/1799] 8021q: fix mac_len recomputation in vlan_untag() [ Upstream commit 5316cf9a5197eb80b2800e1acadde287924ca975 ] skb_reset_mac_len() relies on the value of the skb->network_header pointer, therefore we must wait for such pointer to be recalculated before computing the new mac_len value. Signed-off-by: Antonio Quartulli Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/8021q/vlan_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 4d39d802be2c..f36463087ba8 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -106,7 +106,6 @@ static struct sk_buff *vlan_reorder_header(struct sk_buff *skb) return NULL; memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); skb->mac_header += VLAN_HLEN; - skb_reset_mac_len(skb); return skb; } @@ -140,6 +139,8 @@ struct sk_buff *vlan_untag(struct sk_buff *skb) skb_reset_network_header(skb); skb_reset_transport_header(skb); + skb_reset_mac_len(skb); + return skb; err_free: -- GitLab From 17de307472bf21479e6d7c35211204b6ea186a7c Mon Sep 17 00:00:00 2001 From: Gao feng Date: Wed, 19 Sep 2012 19:25:34 +0000 Subject: [PATCH 0665/1799] ipv6: release reference of ip6_null_entry's dst entry in __ip6_del_rt [ Upstream commit 6825a26c2dc21eb4f8df9c06d3786ddec97cf53b ] as we hold dst_entry before we call __ip6_del_rt, so we should alse call dst_release not only return -ENOENT when the rt6_info is ip6_null_entry. and we already hold the dst entry, so I think it's safe to call dst_release out of the write-read lock. Signed-off-by: Gao feng Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/route.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c4920ca83f5f..2796b374cb2b 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1485,17 +1485,18 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) struct fib6_table *table; struct net *net = dev_net(rt->dst.dev); - if (rt == net->ipv6.ip6_null_entry) - return -ENOENT; + if (rt == net->ipv6.ip6_null_entry) { + err = -ENOENT; + goto out; + } table = rt->rt6i_table; write_lock_bh(&table->tb6_lock); - err = fib6_del(rt, info); - dst_release(&rt->dst); - write_unlock_bh(&table->tb6_lock); +out: + dst_release(&rt->dst); return err; } -- GitLab From d5e36b089edcc8179d4640e1a8e5bca6fb74409e Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 26 Sep 2012 00:04:55 +0000 Subject: [PATCH 0666/1799] ipv6: del unreachable route when an addr is deleted on lo [ Upstream commit 64c6d08e6490fb18cea09bb03686c149946bd818 ] When an address is added on loopback (ip -6 a a 2002::1/128 dev lo), two routes are added: - one in the local table: local 2002::1 via :: dev lo proto none metric 0 - one the in main table (for the prefix): unreachable 2002::1 dev lo proto kernel metric 256 error -101 When the address is deleted, the route inserted in the main table remains because we use rt6_lookup(), which returns NULL when dst->error is set, which is the case here! Thus, it is better to use ip6_route_lookup() to avoid this kind of filter. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/addrconf.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 2c69eca4b61a..5ec60699c671 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -793,10 +793,16 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) struct in6_addr prefix; struct rt6_info *rt; struct net *net = dev_net(ifp->idev->dev); + struct flowi6 fl6 = {}; + ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); - rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1); + fl6.flowi6_oif = ifp->idev->dev->ifindex; + fl6.daddr = prefix; + rt = (struct rt6_info *)ip6_route_lookup(net, &fl6, + RT6_LOOKUP_F_IFACE); - if (rt && addrconf_is_prefix_route(rt)) { + if (rt != net->ipv6.ip6_null_entry && + addrconf_is_prefix_route(rt)) { if (onlink == 0) { ip6_del_rt(rt); rt = NULL; -- GitLab From 410eafac650a906e990351a01ec70451064df83d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 20 Sep 2012 18:29:56 +0000 Subject: [PATCH 0667/1799] ipv6: fix return value check in fib6_add() [ Upstream commit f950c0ecc78f745e490d615280e031de4dbb1306 ] In case of error, the function fib6_add_1() returns ERR_PTR() or NULL pointer. The ERR_PTR() case check is missing in fib6_add(). dpatch engine is used to generated this patch. (https://github.com/weiyj/dpatch) Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ip6_fib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 92bb9cba5c39..c3a007dc37cd 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -818,6 +818,10 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) offsetof(struct rt6_info, rt6i_src), allow_create, replace_required); + if (IS_ERR(sn)) { + err = PTR_ERR(sn); + sn = NULL; + } if (!sn) { /* If it is failed, discard just allocated root, and then (in st_failure) stale node -- GitLab From 2033554a2fe3c5e54764f2f1dba0baff3261f8b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kube=C4=8Dek?= Date: Fri, 14 Sep 2012 04:59:52 +0000 Subject: [PATCH 0668/1799] tcp: flush DMA queue before sk_wait_data if rcv_wnd is zero [ Upstream commit 15c041759bfcd9ab0a4e43f1c16e2644977d0467 ] If recv() syscall is called for a TCP socket so that - IOAT DMA is used - MSG_WAITALL flag is used - requested length is bigger than sk_rcvbuf - enough data has already arrived to bring rcv_wnd to zero then when tcp_recvmsg() gets to calling sk_wait_data(), receive window can be still zero while sk_async_wait_queue exhausts enough space to keep it zero. As this queue isn't cleaned until the tcp_service_net_dma() call, sk_wait_data() cannot receive any data and blocks forever. If zero receive window and non-empty sk_async_wait_queue is detected before calling sk_wait_data(), process the queue first. Signed-off-by: Michal Kubecek Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 367bdaf9a56f..8fbe2e20e7cc 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1594,8 +1594,14 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, } #ifdef CONFIG_NET_DMA - if (tp->ucopy.dma_chan) - dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); + if (tp->ucopy.dma_chan) { + if (tp->rcv_wnd == 0 && + !skb_queue_empty(&sk->sk_async_wait_queue)) { + tcp_service_net_dma(sk, true); + tcp_cleanup_rbuf(sk, copied); + } else + dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); + } #endif if (copied >= target) { /* Do not sleep, just process backlog. */ -- GitLab From 8d16c6268b7c3af2ce4f58de903588489e037fcf Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 3 Sep 2012 04:27:42 +0000 Subject: [PATCH 0669/1799] sctp: Don't charge for data in sndbuf again when transmitting packet [ Upstream commit 4c3a5bdae293f75cdf729c6c00124e8489af2276 ] SCTP charges wmem_alloc via sctp_set_owner_w() in sctp_sendmsg() and via skb_set_owner_w() in sctp_packet_transmit(). If a sender runs out of sndbuf it will sleep in sctp_wait_for_sndbuf() and expects to be waken up by __sctp_write_space(). Buffer space charged via sctp_set_owner_w() is released in sctp_wfree() which calls __sctp_write_space() directly. Buffer space charged via skb_set_owner_w() is released via sock_wfree() which calls sk->sk_write_space() _if_ SOCK_USE_WRITE_QUEUE is not set. sctp_endpoint_init() sets SOCK_USE_WRITE_QUEUE on all sockets. Therefore if sctp_packet_transmit() manages to queue up more than sndbuf bytes, sctp_wait_for_sndbuf() will never be woken up again unless it is interrupted by a signal. This could be fixed by clearing the SOCK_USE_WRITE_QUEUE flag but ... Charging for the data twice does not make sense in the first place, it leads to overcharging sndbuf by a factor 2. Therefore this patch only charges a single byte in wmem_alloc when transmitting an SCTP packet to ensure that the socket stays alive until the packet has been released. This means that control chunks are no longer accounted for in wmem_alloc which I believe is not a problem as skb->truesize will typically lead to overcharging anyway and thus compensates for any control overhead. Signed-off-by: Thomas Graf CC: Vlad Yasevich CC: Neil Horman CC: David Miller Acked-by: Vlad Yasevich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/output.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/net/sctp/output.c b/net/sctp/output.c index 8fc4dcd294ab..32ba8d0e50e2 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -334,6 +334,25 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, return retval; } +static void sctp_packet_release_owner(struct sk_buff *skb) +{ + sk_free(skb->sk); +} + +static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk) +{ + skb_orphan(skb); + skb->sk = sk; + skb->destructor = sctp_packet_release_owner; + + /* + * The data chunks have already been accounted for in sctp_sendmsg(), + * therefore only reserve a single byte to keep socket around until + * the packet has been transmitted. + */ + atomic_inc(&sk->sk_wmem_alloc); +} + /* All packets are sent to the network through this function from * sctp_outq_tail(). * @@ -375,7 +394,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) /* Set the owning socket so that we know where to get the * destination IP address. */ - skb_set_owner_w(nskb, sk); + sctp_packet_set_owner_w(nskb, sk); if (!sctp_transport_dst_check(tp)) { sctp_transport_route(tp, NULL, sctp_sk(sk)); -- GitLab From e043257dde697ded17ed99f280cdb7643fdc007a Mon Sep 17 00:00:00 2001 From: Xiaodong Xu Date: Sat, 22 Sep 2012 00:09:32 +0000 Subject: [PATCH 0670/1799] pppoe: drop PPPOX_ZOMBIEs in pppoe_release [ Upstream commit 2b018d57ff18e5405823e5cb59651a5b4d946d7b ] When PPPOE is running over a virtual ethernet interface (e.g., a bonding interface) and the user tries to delete the interface in case the PPPOE state is ZOMBIE, the kernel will loop forever while unregistering net_device for the reference count is not decreased to zero which should have been done with dev_put(). Signed-off-by: Xiaodong Xu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ppp/pppoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index 2fa1a9b6f498..2e0d8762bb52 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -576,7 +576,7 @@ static int pppoe_release(struct socket *sock) po = pppox_sk(sk); - if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { + if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) { dev_put(po->pppoe_dev); po->pppoe_dev = NULL; } -- GitLab From 6b8fc5c4eba92b5cd3c9ca0d926e99831604f81e Mon Sep 17 00:00:00 2001 From: Chema Gonzalez Date: Fri, 7 Sep 2012 13:40:50 +0000 Subject: [PATCH 0671/1799] net: small bug on rxhash calculation [ Upstream commit 6862234238e84648c305526af2edd98badcad1e0 ] In the current rxhash calculation function, while the sorting of the ports/addrs is coherent (you get the same rxhash for packets sharing the same 4-tuple, in both directions), ports and addrs are sorted independently. This implies packets from a connection between the same addresses but crossed ports hash to the same rxhash. For example, traffic between A=S:l and B=L:s is hashed (in both directions) from {L, S, {s, l}}. The same rxhash is obtained for packets between C=S:s and D=L:l. This patch ensures that you either swap both addrs and ports, or you swap none. Traffic between A and B, and traffic between C and D, get their rxhash from different sources ({L, S, {l, s}} for A<->B, and {L, S, {s, l}} for C<->D) The patch is co-written with Eric Dumazet Signed-off-by: Chema Gonzalez Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 3fd9cae3ccb1..f9ae3975f6b5 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2617,15 +2617,16 @@ void __skb_get_rxhash(struct sk_buff *skb) if (!skb_flow_dissect(skb, &keys)) return; - if (keys.ports) { - if ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]) - swap(keys.port16[0], keys.port16[1]); + if (keys.ports) skb->l4_rxhash = 1; - } /* get a consistent hash (same value on both flow directions) */ - if ((__force u32)keys.dst < (__force u32)keys.src) + if (((__force u32)keys.dst < (__force u32)keys.src) || + (((__force u32)keys.dst == (__force u32)keys.src) && + ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) { swap(keys.dst, keys.src); + swap(keys.port16[0], keys.port16[1]); + } hash = jhash_3words((__force u32)keys.dst, (__force u32)keys.src, -- GitLab From 09c6cf7f980f1e8dbf58dc9ae0ebf4f6eb93cc0d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 24 Sep 2012 07:00:11 +0000 Subject: [PATCH 0672/1799] net: guard tcp_set_keepalive() to tcp sockets [ Upstream commit 3e10986d1d698140747fcfc2761ec9cb64c1d582 ] Its possible to use RAW sockets to get a crash in tcp_set_keepalive() / sk_reset_timer() Fix is to make sure socket is a SOCK_STREAM one. Reported-by: Dave Jones Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/sock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/sock.c b/net/core/sock.c index d3e0a5201d47..4b469e367923 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -644,7 +644,8 @@ int sock_setsockopt(struct socket *sock, int level, int optname, case SO_KEEPALIVE: #ifdef CONFIG_INET - if (sk->sk_protocol == IPPROTO_TCP) + if (sk->sk_protocol == IPPROTO_TCP && + sk->sk_type == SOCK_STREAM) tcp_set_keepalive(sk, valbool); #endif sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool); -- GitLab From 514ddfedb89c19c57de82aedec8da2bd8ff3802c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 22 Sep 2012 00:08:29 +0000 Subject: [PATCH 0673/1799] ipv4: raw: fix icmp_filter() [ Upstream commit ab43ed8b7490cb387782423ecf74aeee7237e591 ] icmp_filter() should not modify its input, or else its caller would need to recompute ip_hdr() if skb->head is reallocated. Use skb_header_pointer() instead of pskb_may_pull() and change the prototype to make clear both sk and skb are const. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/raw.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index bbd604c68e68..2fe0dc28ea98 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -131,18 +131,20 @@ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, * 0 - deliver * 1 - block */ -static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb) +static int icmp_filter(const struct sock *sk, const struct sk_buff *skb) { - int type; + struct icmphdr _hdr; + const struct icmphdr *hdr; - if (!pskb_may_pull(skb, sizeof(struct icmphdr))) + hdr = skb_header_pointer(skb, skb_transport_offset(skb), + sizeof(_hdr), &_hdr); + if (!hdr) return 1; - type = icmp_hdr(skb)->type; - if (type < 32) { + if (hdr->type < 32) { __u32 data = raw_sk(sk)->filter.data; - return ((1 << type) & data) != 0; + return ((1U << hdr->type) & data) != 0; } /* Do not block unknown ICMP types */ -- GitLab From 7a20f9c5fa76e602bf9dda7f610c8de04e7afa04 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 25 Sep 2012 07:03:40 +0000 Subject: [PATCH 0674/1799] ipv6: raw: fix icmpv6_filter() [ Upstream commit 1b05c4b50edbddbdde715c4a7350629819f6655e ] icmpv6_filter() should not modify its input, or else its caller would need to recompute ipv6_hdr() if skb->head is reallocated. Use skb_header_pointer() instead of pskb_may_pull() and change the prototype to make clear both sk and skb are const. Also, if icmpv6 header cannot be found, do not deliver the packet, as we do in IPv4. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/raw.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 5bddea778840..3ee28700de4c 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -107,21 +107,20 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, * 0 - deliver * 1 - block */ -static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) +static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb) { - struct icmp6hdr *icmph; - struct raw6_sock *rp = raw6_sk(sk); - - if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) { - __u32 *data = &rp->filter.data[0]; - int bit_nr; + struct icmp6hdr *_hdr; + const struct icmp6hdr *hdr; - icmph = (struct icmp6hdr *) skb->data; - bit_nr = icmph->icmp6_type; + hdr = skb_header_pointer(skb, skb_transport_offset(skb), + sizeof(_hdr), &_hdr); + if (hdr) { + const __u32 *data = &raw6_sk(sk)->filter.data[0]; + unsigned int type = hdr->icmp6_type; - return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0; + return (data[type >> 5] & (1U << (type & 31))) != 0; } - return 0; + return 1; } #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) -- GitLab From 28ad5c792deb17e1274cef32c59049d2062ed1b3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 25 Sep 2012 22:01:28 +0200 Subject: [PATCH 0675/1799] ipv6: mip6: fix mip6_mh_filter() [ Upstream commit 96af69ea2a83d292238bdba20e4508ee967cf8cb ] mip6_mh_filter() should not modify its input, or else its caller would need to recompute ipv6_hdr() if skb->head is reallocated. Use skb_header_pointer() instead of pskb_may_pull() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/mip6.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 7e1e0fbfef21..740c919e0b6c 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c @@ -84,28 +84,30 @@ static int mip6_mh_len(int type) static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) { - struct ip6_mh *mh; + struct ip6_mh _hdr; + const struct ip6_mh *mh; - if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) || - !pskb_may_pull(skb, (skb_transport_offset(skb) + - ((skb_transport_header(skb)[1] + 1) << 3)))) + mh = skb_header_pointer(skb, skb_transport_offset(skb), + sizeof(_hdr), &_hdr); + if (!mh) return -1; - mh = (struct ip6_mh *)skb_transport_header(skb); + if (((mh->ip6mh_hdrlen + 1) << 3) > skb->len) + return -1; if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) { LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n", mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); - mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) - - skb_network_header(skb))); + mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_hdrlen) + + skb_network_header_len(skb)); return -1; } if (mh->ip6mh_proto != IPPROTO_NONE) { LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n", mh->ip6mh_proto); - mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) - - skb_network_header(skb))); + mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_proto) + + skb_network_header_len(skb)); return -1; } -- GitLab From bc0b2168aed1ecf0d71975af12d4f0ffecb92bfc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 4 Sep 2012 15:54:55 -0400 Subject: [PATCH 0676/1799] l2tp: fix a typo in l2tp_eth_dev_recv() [ Upstream commit c0cc88a7627c333de50b07b7c60b1d49d9d2e6cc ] While investigating l2tp bug, I hit a bug in eth_type_trans(), because not enough bytes were pulled in skb head. 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 7446038e6b42..5c829077b256 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 (!pskb_may_pull(skb, sizeof(ETH_HLEN))) + if (!pskb_may_pull(skb, ETH_HLEN)) goto error; secpath_reset(skb); -- GitLab From 782d596c84bf4239b24906132ba6367ca7dca865 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 4 Sep 2012 04:13:18 +0000 Subject: [PATCH 0677/1799] netrom: copy_datagram_iovec can fail [ Upstream commit 6cf5c951175abcec4da470c50565cc0afe6cd11d ] Check for an error from this and if so bail properly. Signed-off-by: Alan Cox Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/netrom/af_netrom.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 06592d8b4a2b..1b9024ee963c 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1169,7 +1169,12 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, msg->msg_flags |= MSG_TRUNC; } - skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + er = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + if (er < 0) { + skb_free_datagram(sk, skb); + release_sock(sk); + return er; + } if (sax != NULL) { sax->sax25_family = AF_NETROM; -- GitLab From 2583c9724757046ed749ec7d1fef2e371b02f203 Mon Sep 17 00:00:00 2001 From: Ed Cashin Date: Wed, 19 Sep 2012 15:49:00 +0000 Subject: [PATCH 0678/1799] net: do not disable sg for packets requiring no checksum [ Upstream commit c0d680e577ff171e7b37dbdb1b1bf5451e851f04 ] A change in a series of VLAN-related changes appears to have inadvertently disabled the use of the scatter gather feature of network cards for transmission of non-IP ethernet protocols like ATA over Ethernet (AoE). Below is a reference to the commit that introduces a "harmonize_features" function that turns off scatter gather when the NIC does not support hardware checksumming for the ethernet protocol of an sk buff. commit f01a5236bd4b140198fbcc550f085e8361fd73fa Author: Jesse Gross Date: Sun Jan 9 06:23:31 2011 +0000 net offloading: Generalize netif_get_vlan_features(). The can_checksum_protocol function is not equipped to consider a protocol that does not require checksumming. Calling it for a protocol that requires no checksum is inappropriate. The patch below has harmonize_features call can_checksum_protocol when the protocol needs a checksum, so that the network layer is not forced to perform unnecessary skb linearization on the transmission of AoE packets. Unnecessary linearization results in decreased performance and increased memory pressure, as reported here: http://www.spinics.net/lists/linux-mm/msg15184.html The problem has probably not been widely experienced yet, because only recently has the kernel.org-distributed aoe driver acquired the ability to use payloads of over a page in size, with the patchset recently included in the mm tree: https://lkml.org/lkml/2012/8/28/140 The coraid.com-distributed aoe driver already could use payloads of greater than a page in size, but its users generally do not use the newest kernels. Signed-off-by: Ed Cashin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index f9ae3975f6b5..086bc2e578cc 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2121,7 +2121,8 @@ static bool can_checksum_protocol(netdev_features_t features, __be16 protocol) static netdev_features_t harmonize_features(struct sk_buff *skb, __be16 protocol, netdev_features_t features) { - if (!can_checksum_protocol(features, protocol)) { + if (skb->ip_summed != CHECKSUM_NONE && + !can_checksum_protocol(features, protocol)) { features &= ~NETIF_F_ALL_CSUM; features &= ~NETIF_F_SG; } else if (illegal_highdma(skb->dev, skb)) { -- GitLab From fa9a48a7bed7d785a98356d4d06090500ec00c82 Mon Sep 17 00:00:00 2001 From: Ed Cashin Date: Wed, 19 Sep 2012 15:46:39 +0000 Subject: [PATCH 0679/1799] aoe: assert AoE packets marked as requiring no checksum [ Upstream commit 8babe8cc6570ed896b7b596337eb8fe730c3ff45 ] In order for the network layer to see that AoE requires no checksumming in a generic way, the packets must be marked as requiring no checksum, so we make this requirement explicit with the assertion. Signed-off-by: Ed Cashin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoecmd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index de0435e63b02..887f68f6d79a 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -35,6 +35,7 @@ new_skb(ulong len) skb_reset_mac_header(skb); skb_reset_network_header(skb); skb->protocol = __constant_htons(ETH_P_AOE); + skb_checksum_none_assert(skb); } return skb; } -- GitLab From 194cca171bc5a062974d96b0246cde0c65ac33d0 Mon Sep 17 00:00:00 2001 From: Florian Zumbiehl Date: Tue, 2 Oct 2012 12:20:37 +0000 Subject: [PATCH 0680/1799] drm/savage: re-add busmaster enable, regression fix commit df86b5765a48d5f557489577652bd6df145b0e1b upstream. 466e69b8b03b8c1987367912782bc12988ad8794 dropped busmaster enable from the global drm code and moved it to the individual drivers, but missed the savage driver. So, this re-adds busmaster enable to the savage driver, fixing the regression. Signed-off-by: Florian Zumbiehl Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/savage/savage_bci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c index cb1ee4e0050a..2a258887e419 100644 --- a/drivers/gpu/drm/savage/savage_bci.c +++ b/drivers/gpu/drm/savage/savage_bci.c @@ -547,6 +547,8 @@ int savage_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->chipset = (enum savage_family)chipset; + pci_set_master(dev->pdev); + return 0; } -- GitLab From ab617446730e46080235b9e158d364bab233e9ee Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Tue, 4 Sep 2012 15:23:29 +0200 Subject: [PATCH 0681/1799] SCSI: zfcp: Adapt to new FC_PORTSPEED semantics commit d22019778cd9ea04c1dadf7bf453920d5288f8d9 upstream. Commit a9277e7783651d4e0a849f7988340b1c1cf748a4 "[SCSI] scsi_transport_fc: Getting FC Port Speed in sync with FC-GS" changed the semantics of FC_PORTSPEED defines to FDMI port attributes of FC-HBA/SM-HBA which is different from the previous bit reversed Report Port Speed Capabilities (RPSC) ELS of FC-GS/FC-LS. Zfcp showed "10 Gbit" instead of "4 Gbit" for supported_speeds. It now uses explicit bit conversion as the other LLDs already do, in order to be independent of the kernel bit semantics. See also http://marc.info/?l=linux-scsi&m=134452926830730&w=2 Signed-off-by: Steffen Maier Reviewed-by: Martin Peschke Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_fsf.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index e9a787e2e6a5..613ce11d06c5 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -437,6 +437,34 @@ void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) } } +#define ZFCP_FSF_PORTSPEED_1GBIT (1 << 0) +#define ZFCP_FSF_PORTSPEED_2GBIT (1 << 1) +#define ZFCP_FSF_PORTSPEED_4GBIT (1 << 2) +#define ZFCP_FSF_PORTSPEED_10GBIT (1 << 3) +#define ZFCP_FSF_PORTSPEED_8GBIT (1 << 4) +#define ZFCP_FSF_PORTSPEED_16GBIT (1 << 5) +#define ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED (1 << 15) + +static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed) +{ + u32 fdmi_speed = 0; + if (fsf_speed & ZFCP_FSF_PORTSPEED_1GBIT) + fdmi_speed |= FC_PORTSPEED_1GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_2GBIT) + fdmi_speed |= FC_PORTSPEED_2GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_4GBIT) + fdmi_speed |= FC_PORTSPEED_4GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_10GBIT) + fdmi_speed |= FC_PORTSPEED_10GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_8GBIT) + fdmi_speed |= FC_PORTSPEED_8GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_16GBIT) + fdmi_speed |= FC_PORTSPEED_16GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED) + fdmi_speed |= FC_PORTSPEED_NOT_NEGOTIATED; + return fdmi_speed; +} + static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) { struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config; @@ -456,7 +484,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) fc_host_port_name(shost) = nsp->fl_wwpn; fc_host_node_name(shost) = nsp->fl_wwnn; fc_host_port_id(shost) = ntoh24(bottom->s_id); - fc_host_speed(shost) = bottom->fc_link_speed; + fc_host_speed(shost) = + zfcp_fsf_convert_portspeed(bottom->fc_link_speed); fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; adapter->hydra_version = bottom->adapter_type; @@ -580,7 +609,8 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) } else fc_host_permanent_port_name(shost) = fc_host_port_name(shost); fc_host_maxframe_size(shost) = bottom->maximum_frame_size; - fc_host_supported_speeds(shost) = bottom->supported_speed; + fc_host_supported_speeds(shost) = + zfcp_fsf_convert_portspeed(bottom->supported_speed); memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types, FC_FC4_LIST_SIZE); memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types, -- GitLab From 1afbcbdd1c0761ca9e807e78fa106efc465c3925 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Tue, 4 Sep 2012 15:23:30 +0200 Subject: [PATCH 0682/1799] SCSI: zfcp: Make trace record tags unique commit 0100998dbfe6dfcd90a6e912ca7ed6f255d48f25 upstream. Duplicate fssrh_2 from a54ca0f62f953898b05549391ac2a8a4dad6482b "[SCSI] zfcp: Redesign of the debug tracing for HBA records." complicates distinction of generic status read response from local link up. Duplicate fsscth1 from 2c55b750a884b86dea8b4cc5f15e1484cc47a25c "[SCSI] zfcp: Redesign of the debug tracing for SAN records." complicates distinction of good common transport response from invalid port handle. Signed-off-by: Steffen Maier Reviewed-by: Martin Peschke Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_fsf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 613ce11d06c5..e9d10f45241a 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -219,7 +219,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) return; } - zfcp_dbf_hba_fsf_uss("fssrh_2", req); + zfcp_dbf_hba_fsf_uss("fssrh_4", req); switch (sr_buf->status_type) { case FSF_STATUS_READ_PORT_CLOSED: @@ -915,7 +915,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_GOOD: - zfcp_dbf_san_res("fsscth1", req); + zfcp_dbf_san_res("fsscth2", req); ct->status = 0; break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: -- GitLab From 2872405ba2729853da43865893469f8cb80b69b2 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Tue, 4 Sep 2012 15:23:31 +0200 Subject: [PATCH 0683/1799] SCSI: zfcp: Bounds checking for deferred error trace commit 01e60527f0a49b3d7df603010bd6079bb4b6cf07 upstream. The pl vector has scount elements, i.e. pl[scount-1] is the last valid element. For maximum sized requests, payload->counter == scount after the last loop iteration. Therefore, do bounds checking first (with boolean shortcut) to not access the invalid element pl[scount]. Do not trust the maximum sbale->scount value from the HBA but ensure we won't access the pl vector out of our allocated bounds. While at it, clean up scoping and prevent unnecessary memset. Minor fix for 86a9668a8d29ea711613e1cb37efa68e7c4db564 "[SCSI] zfcp: support for hardware data router" Signed-off-by: Steffen Maier Reviewed-by: Martin Peschke Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_dbf.c | 2 +- drivers/s390/scsi/zfcp_qdio.c | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index a9a816e4aa55..bdca8e692902 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -191,7 +191,7 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount, length = min((u16)sizeof(struct qdio_buffer), (u16)ZFCP_DBF_PAY_MAX_REC); - while ((char *)pl[payload->counter] && payload->counter < scount) { + while (payload->counter < scount && (char *)pl[payload->counter]) { memcpy(payload->data, (char *)pl[payload->counter], length); debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length)); payload->counter++; diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index e14da5751d32..e76d003ebdb3 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -102,18 +102,22 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, { struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; struct zfcp_adapter *adapter = qdio->adapter; - struct qdio_buffer_element *sbale; int sbal_no, sbal_idx; - void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1]; - u64 req_id; - u8 scount; if (unlikely(qdio_err)) { - memset(pl, 0, ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *)); if (zfcp_adapter_multi_buffer_active(adapter)) { + void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1]; + struct qdio_buffer_element *sbale; + u64 req_id; + u8 scount; + + memset(pl, 0, + ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *)); sbale = qdio->res_q[idx]->element; req_id = (u64) sbale->addr; - scount = sbale->scount + 1; /* incl. signaling SBAL */ + scount = min(sbale->scount + 1, + ZFCP_QDIO_MAX_SBALS_PER_REQ + 1); + /* incl. signaling SBAL */ for (sbal_no = 0; sbal_no < scount; sbal_no++) { sbal_idx = (idx + sbal_no) % -- GitLab From 530bab7e87951aea1ae20706174021c3355f305a Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Tue, 4 Sep 2012 15:23:32 +0200 Subject: [PATCH 0684/1799] SCSI: zfcp: Do not wakeup while suspended commit cb45214960bc989af8b911ebd77da541c797717d upstream. If the mapping of FCP device bus ID and corresponding subchannel is modified while the Linux image is suspended, the resume of FCP devices can fail. During resume, zfcp gets callbacks from cio regarding the modified subchannels but they can be arbitrarily mixed with the restore/resume callback. Since the cio callbacks would trigger adapter recovery, zfcp could wakeup before the resume callback. Therefore, ignore the cio callbacks regarding subchannels while being suspended. We can safely do so, since zfcp does not deal itself with subchannels. For problem determination purposes, we still trace the ignored callback events. The following kernel messages could be seen on resume: kernel: : parent should not be sleeping As part of adapter reopen recovery, zfcp performs auto port scanning which can erroneously try to register new remote ports with scsi_transport_fc and the device core code complains about the parent (adapter) still sleeping. kernel: zfcp.3dff9c: :\ Setting up the QDIO connection to the FCP adapter failed kernel: zfcp.574d43: :\ ERP cannot recover an error on the FCP device In such cases, the adapter gave up recovery and remained blocked along with its child objects: remote ports and LUNs/scsi devices. Even the adapter shutdown as part of giving up recovery failed because the ccw device state remained disconnected. Later, the corresponding remote ports ran into dev_loss_tmo. As a result, the LUNs were erroneously not available again after resume. Even a manually triggered adapter recovery (e.g. sysfs attribute failed, or device offline/online via sysfs) could not recover the adapter due to the remaining disconnected state of the corresponding ccw device. Signed-off-by: Steffen Maier Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_ccw.c | 73 +++++++++++++++++++++++++++++++----- drivers/s390/scsi/zfcp_dbf.c | 20 ++++++++++ drivers/s390/scsi/zfcp_dbf.h | 1 + drivers/s390/scsi/zfcp_def.h | 1 + drivers/s390/scsi/zfcp_ext.h | 1 + 5 files changed, 86 insertions(+), 10 deletions(-) diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 96f13ad88123..79a6afe0212a 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -39,17 +39,23 @@ void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter) spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags); } -static int zfcp_ccw_activate(struct ccw_device *cdev) - +/** + * zfcp_ccw_activate - activate adapter and wait for it to finish + * @cdev: pointer to belonging ccw device + * @clear: Status flags to clear. + * @tag: s390dbf trace record tag + */ +static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag) { struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); if (!adapter) return 0; + zfcp_erp_clear_adapter_status(adapter, clear); zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, - "ccresu2"); + tag); zfcp_erp_wait(adapter); flush_work(&adapter->scan_work); @@ -164,32 +170,47 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev) BUG_ON(!zfcp_reqlist_isempty(adapter->req_list)); adapter->req_no = 0; - zfcp_ccw_activate(cdev); + zfcp_ccw_activate(cdev, 0, "ccsonl1"); zfcp_ccw_adapter_put(adapter); return 0; } /** - * zfcp_ccw_set_offline - set_offline function of zfcp driver + * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish * @cdev: pointer to belonging ccw device + * @set: Status flags to set. + * @tag: s390dbf trace record tag * * This function gets called by the common i/o layer and sets an adapter * into state offline. */ -static int zfcp_ccw_set_offline(struct ccw_device *cdev) +static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag) { struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); if (!adapter) return 0; - zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1"); + zfcp_erp_set_adapter_status(adapter, set); + zfcp_erp_adapter_shutdown(adapter, 0, tag); zfcp_erp_wait(adapter); zfcp_ccw_adapter_put(adapter); return 0; } +/** + * zfcp_ccw_set_offline - set_offline function of zfcp driver + * @cdev: pointer to belonging ccw device + * + * This function gets called by the common i/o layer and sets an adapter + * into state offline. + */ +static int zfcp_ccw_set_offline(struct ccw_device *cdev) +{ + return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1"); +} + /** * zfcp_ccw_notify - ccw notify function * @cdev: pointer to belonging ccw device @@ -207,6 +228,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event) switch (event) { case CIO_GONE: + if (atomic_read(&adapter->status) & + ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ + zfcp_dbf_hba_basic("ccnigo1", adapter); + break; + } dev_warn(&cdev->dev, "The FCP device has been detached\n"); zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1"); break; @@ -216,6 +242,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event) zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2"); break; case CIO_OPER: + if (atomic_read(&adapter->status) & + ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ + zfcp_dbf_hba_basic("ccniop1", adapter); + break; + } dev_info(&cdev->dev, "The FCP device is operational again\n"); zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); @@ -251,6 +282,28 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev) zfcp_ccw_adapter_put(adapter); } +static int zfcp_ccw_suspend(struct ccw_device *cdev) +{ + zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1"); + return 0; +} + +static int zfcp_ccw_thaw(struct ccw_device *cdev) +{ + /* trace records for thaw and final shutdown during suspend + can only be found in system dump until the end of suspend + but not after resume because it's based on the memory image + right after the very first suspend (freeze) callback */ + zfcp_ccw_activate(cdev, 0, "ccthaw1"); + return 0; +} + +static int zfcp_ccw_resume(struct ccw_device *cdev) +{ + zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1"); + return 0; +} + struct ccw_driver zfcp_ccw_driver = { .driver = { .owner = THIS_MODULE, @@ -263,7 +316,7 @@ struct ccw_driver zfcp_ccw_driver = { .set_offline = zfcp_ccw_set_offline, .notify = zfcp_ccw_notify, .shutdown = zfcp_ccw_shutdown, - .freeze = zfcp_ccw_set_offline, - .thaw = zfcp_ccw_activate, - .restore = zfcp_ccw_activate, + .freeze = zfcp_ccw_suspend, + .thaw = zfcp_ccw_thaw, + .restore = zfcp_ccw_resume, }; diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index bdca8e692902..79b98482547b 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -200,6 +200,26 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount, spin_unlock_irqrestore(&dbf->pay_lock, flags); } +/** + * zfcp_dbf_hba_basic - trace event for basic adapter events + * @adapter: pointer to struct zfcp_adapter + */ +void zfcp_dbf_hba_basic(char *tag, struct zfcp_adapter *adapter) +{ + struct zfcp_dbf *dbf = adapter->dbf; + struct zfcp_dbf_hba *rec = &dbf->hba_buf; + unsigned long flags; + + spin_lock_irqsave(&dbf->hba_lock, flags); + memset(rec, 0, sizeof(*rec)); + + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + rec->id = ZFCP_DBF_HBA_BASIC; + + debug_event(dbf->hba, 1, rec, sizeof(*rec)); + spin_unlock_irqrestore(&dbf->hba_lock, flags); +} + static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, struct zfcp_adapter *adapter, struct zfcp_port *port, diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 714f087eb7a9..3ac7a4b30dd9 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -154,6 +154,7 @@ enum zfcp_dbf_hba_id { ZFCP_DBF_HBA_RES = 1, ZFCP_DBF_HBA_USS = 2, ZFCP_DBF_HBA_BIT = 3, + ZFCP_DBF_HBA_BASIC = 4, }; /** diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index ed5d921e82cd..6009c3bf31c3 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -77,6 +77,7 @@ struct zfcp_reqlist; #define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004 #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 +#define ZFCP_STATUS_ADAPTER_SUSPENDED 0x00000040 #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 #define ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED 0x00000400 diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 2302e1cfb76c..1564ba24de6a 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -54,6 +54,7 @@ extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **); +extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *); extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); -- GitLab From ab37eb284ac88f092187f7c4ee4a42c28cdaf3e5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 4 Sep 2012 15:23:33 +0200 Subject: [PATCH 0685/1799] SCSI: zfcp: remove invalid reference to list iterator variable commit ca579c9f136af4274ccfd1bcaee7f38a29a0e2e9 upstream. If list_for_each_entry, etc complete a traversal of the list, the iterator variable ends up pointing to an address at an offset from the list head, and not a meaningful structure. Thus this value should not be used after the end of the iterator. Replace port->adapter->scsi_host by adapter->scsi_host. This problem was found using Coccinelle (http://coccinelle.lip6.fr/). Oversight in upsteam commit of v2.6.37 a1ca48319a9aa1c5b57ce142f538e76050bb8972 "[SCSI] zfcp: Move ACL/CFDC code to zfcp_cfdc.c" which merged the content of zfcp_erp_port_access_changed(). Signed-off-by: Julia Lawall Signed-off-by: Steffen Maier Reviewed-by: Martin Peschke Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_cfdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index fab2c2592a97..8ed63aa9abea 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c @@ -293,7 +293,7 @@ void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter) } read_unlock_irqrestore(&adapter->port_list_lock, flags); - shost_for_each_device(sdev, port->adapter->scsi_host) { + shost_for_each_device(sdev, adapter->scsi_host) { zfcp_sdev = sdev_to_zfcp(sdev); status = atomic_read(&zfcp_sdev->status); if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) || -- GitLab From 960e8a5e0257c26bb5d5b14c8c89919e1293e76c Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Tue, 4 Sep 2012 15:23:34 +0200 Subject: [PATCH 0686/1799] SCSI: zfcp: restore refcount check on port_remove commit d99b601b63386f3395dc26a699ae703a273d9982 upstream. Upstream commit f3450c7b917201bb49d67032e9f60d5125675d6a "[SCSI] zfcp: Replace local reference counting with common kref" accidentally dropped a reference count check before tearing down zfcp_ports that are potentially in use by zfcp_units. Even remote ports in use can be removed causing unreachable garbage objects zfcp_ports with zfcp_units. Thus units won't come back even after a manual port_rescan. The kref of zfcp_port->dev.kobj is already used by the driver core. We cannot re-use it to track the number of zfcp_units. Re-introduce our own counter for units per port and check on port_remove. Signed-off-by: Steffen Maier Reviewed-by: Heiko Carstens Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_aux.c | 1 + drivers/s390/scsi/zfcp_def.h | 1 + drivers/s390/scsi/zfcp_ext.h | 1 + drivers/s390/scsi/zfcp_sysfs.c | 18 +++++++++++++++-- drivers/s390/scsi/zfcp_unit.c | 36 ++++++++++++++++++++++++---------- 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 086018109662..4f1b10b7dea6 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -519,6 +519,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, rwlock_init(&port->unit_list_lock); INIT_LIST_HEAD(&port->unit_list); + atomic_set(&port->units, 0); INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup); INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 6009c3bf31c3..f172b844217d 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -205,6 +205,7 @@ struct zfcp_port { struct zfcp_adapter *adapter; /* adapter used to access port */ struct list_head unit_list; /* head of logical unit list */ rwlock_t unit_list_lock; /* unit list lock */ + atomic_t units; /* zfcp_unit count */ atomic_t status; /* status of this remote port */ u64 wwnn; /* WWNN if known */ u64 wwpn; /* WWPN */ diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 1564ba24de6a..ef9e50225ee7 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -159,6 +159,7 @@ extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int); extern struct attribute_group zfcp_sysfs_unit_attrs; extern struct attribute_group zfcp_sysfs_adapter_attrs; extern struct attribute_group zfcp_sysfs_port_attrs; +extern struct mutex zfcp_sysfs_port_units_mutex; extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; extern struct device_attribute *zfcp_sysfs_shost_attrs[]; diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index cdc4ff78a7ba..9e62210b294f 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -227,6 +227,8 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev, static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, zfcp_sysfs_port_rescan_store); +DEFINE_MUTEX(zfcp_sysfs_port_units_mutex); + static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -249,6 +251,16 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, else retval = 0; + mutex_lock(&zfcp_sysfs_port_units_mutex); + if (atomic_read(&port->units) > 0) { + retval = -EBUSY; + mutex_unlock(&zfcp_sysfs_port_units_mutex); + goto out; + } + /* port is about to be removed, so no more unit_add */ + atomic_set(&port->units, -1); + mutex_unlock(&zfcp_sysfs_port_units_mutex); + write_lock_irq(&adapter->port_list_lock); list_del(&port->list); write_unlock_irq(&adapter->port_list_lock); @@ -289,12 +301,14 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, { struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); u64 fcp_lun; + int retval; if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) return -EINVAL; - if (zfcp_unit_add(port, fcp_lun)) - return -EINVAL; + retval = zfcp_unit_add(port, fcp_lun); + if (retval) + return retval; return count; } diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c index 20796ebc33ce..4e6a5356bdbd 100644 --- a/drivers/s390/scsi/zfcp_unit.c +++ b/drivers/s390/scsi/zfcp_unit.c @@ -104,7 +104,7 @@ static void zfcp_unit_release(struct device *dev) { struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); - put_device(&unit->port->dev); + atomic_dec(&unit->port->units); kfree(unit); } @@ -119,16 +119,27 @@ static void zfcp_unit_release(struct device *dev) int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) { struct zfcp_unit *unit; + int retval = 0; + + mutex_lock(&zfcp_sysfs_port_units_mutex); + if (atomic_read(&port->units) == -1) { + /* port is already gone */ + retval = -ENODEV; + goto out; + } unit = zfcp_unit_find(port, fcp_lun); if (unit) { put_device(&unit->dev); - return -EEXIST; + retval = -EEXIST; + goto out; } unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); - if (!unit) - return -ENOMEM; + if (!unit) { + retval = -ENOMEM; + goto out; + } unit->port = port; unit->fcp_lun = fcp_lun; @@ -139,28 +150,33 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) if (dev_set_name(&unit->dev, "0x%016llx", (unsigned long long) fcp_lun)) { kfree(unit); - return -ENOMEM; + retval = -ENOMEM; + goto out; } - get_device(&port->dev); - if (device_register(&unit->dev)) { put_device(&unit->dev); - return -ENOMEM; + retval = -ENOMEM; + goto out; } if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) { device_unregister(&unit->dev); - return -EINVAL; + retval = -EINVAL; + goto out; } + atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */ + write_lock_irq(&port->unit_list_lock); list_add_tail(&unit->list, &port->unit_list); write_unlock_irq(&port->unit_list_lock); zfcp_unit_scsi_scan(unit); - return 0; +out: + mutex_unlock(&zfcp_sysfs_port_units_mutex); + return retval; } /** -- GitLab From 82e0551186fd455d792fccae805470f222339c06 Mon Sep 17 00:00:00 2001 From: Martin Peschke Date: Tue, 4 Sep 2012 15:23:36 +0200 Subject: [PATCH 0687/1799] SCSI: zfcp: only access zfcp_scsi_dev for valid scsi_device commit d436de8ce25f53a8a880a931886821f632247943 upstream. __scsi_remove_device (e.g. due to dev_loss_tmo) calls zfcp_scsi_slave_destroy which in turn sends a close LUN FSF request to the adapter. After 30 seconds without response, zfcp_erp_timeout_handler kicks the ERP thread failing the close LUN ERP action. zfcp_erp_wait in zfcp_erp_lun_shutdown_wait and thus zfcp_scsi_slave_destroy returns and then scsi_device is no longer valid. Sometime later the response to the close LUN FSF request may finally come in. However, commit b62a8d9b45b971a67a0f8413338c230e3117dff5 "[SCSI] zfcp: Use SCSI device data zfcp_scsi_dev instead of zfcp_unit" introduced a number of attempts to unconditionally access struct zfcp_scsi_dev through struct scsi_device causing a use-after-free. This leads to an Oops due to kernel page fault in one of: zfcp_fsf_abort_fcp_command_handler, zfcp_fsf_open_lun_handler, zfcp_fsf_close_lun_handler, zfcp_fsf_req_trace, zfcp_fsf_fcp_handler_common. Move dereferencing of zfcp private data zfcp_scsi_dev allocated in scsi_device via scsi_transport_reserve_device after the check for potentially aborted FSF request and thus no longer valid scsi_device. Only then assign sdev_to_zfcp(sdev) to the local auto variable struct zfcp_scsi_dev *zfcp_sdev. Signed-off-by: Martin Peschke Signed-off-by: Steffen Maier Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/scsi/zfcp_fsf.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index e9d10f45241a..2136fc2178eb 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -801,12 +801,14 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio) static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) { struct scsi_device *sdev = req->data; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; + zfcp_sdev = sdev_to_zfcp(sdev); + switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: if (fsq->word[0] == fsq->word[1]) { @@ -1769,13 +1771,15 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req) { struct zfcp_adapter *adapter = req->adapter; struct scsi_device *sdev = req->data; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; struct fsf_qtcb_header *header = &req->qtcb->header; struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; + zfcp_sdev = sdev_to_zfcp(sdev); + atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | ZFCP_STATUS_COMMON_ACCESS_BOXED | ZFCP_STATUS_LUN_SHARED | @@ -1886,11 +1890,13 @@ int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action) static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req) { struct scsi_device *sdev = req->data; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; + zfcp_sdev = sdev_to_zfcp(sdev); + switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1"); @@ -1980,7 +1986,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) { struct fsf_qual_latency_info *lat_in; struct latency_cont *lat = NULL; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device); + struct zfcp_scsi_dev *zfcp_sdev; struct zfcp_blk_drv_data blktrc; int ticks = req->adapter->timer_ticks; @@ -1995,6 +2001,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA && !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { + zfcp_sdev = sdev_to_zfcp(scsi->device); blktrc.flags |= ZFCP_BLK_LAT_VALID; blktrc.channel_lat = lat_in->channel_lat * ticks; blktrc.fabric_lat = lat_in->fabric_lat * ticks; @@ -2032,12 +2039,14 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) { struct scsi_cmnd *scmnd = req->data; struct scsi_device *sdev = scmnd->device; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; struct fsf_qtcb_header *header = &req->qtcb->header; if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) return; + zfcp_sdev = sdev_to_zfcp(sdev); + switch (header->fsf_status) { case FSF_HANDLE_MISMATCH: case FSF_PORT_HANDLE_NOT_VALID: -- GitLab From b790ef23cd1fd3fece4777e90d85a945c4820ae7 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 10 Sep 2012 17:19:33 -0700 Subject: [PATCH 0688/1799] PCI: Check P2P bridge for invalid secondary/subordinate range commit 1965f66e7db08d1ebccd24a59043eba826cc1ce8 upstream. For bridges with "secondary > subordinate", i.e., invalid bus number apertures, we don't enumerate anything behind the bridge unless the user specified "pci=assign-busses". This patch makes us automatically try to reassign the downstream bus numbers in this case (just for that bridge, not for all bridges as "pci=assign-busses" does). We don't discover all the devices on the Intel DP43BF motherboard without this change (or "pci=assign-busses") because its BIOS configures a bridge as: pci 0000:00:1e.0: PCI bridge to [bus 20-08] (subtractive decode) [bhelgaas: changelog, change message to dev_info] Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=18412 Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=625754 Reported-by: Brian C. Huffman Reported-by: VL Tested-by: VL Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 5e1ca3c58a7d..63e0199f7c78 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -749,8 +749,10 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, /* Check if setup is sensible at all */ if (!pass && - (primary != bus->number || secondary <= bus->number)) { - dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n"); + (primary != bus->number || secondary <= bus->number || + secondary > subordinate)) { + dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n", + secondary, subordinate); broken = 1; } -- GitLab From 2d5a1fbc0c25ab4a2e2770a5c729467893407009 Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Wed, 5 Sep 2012 01:21:50 -0400 Subject: [PATCH 0689/1799] ext4: ignore last group w/o enough space when resizing instead of BUG'ing commit 03c1c29053f678234dbd51bf3d65f3b7529021de upstream. If the last group does not have enough space for group tables, ignore it instead of calling BUG_ON(). Reported-by: Daniel Drake Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/resize.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 3407a62590d6..46d9ec8453f2 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -200,8 +200,11 @@ static void free_flex_gd(struct ext4_new_flex_group_data *flex_gd) * be a partial of a flex group. * * @sb: super block of fs to which the groups belongs + * + * Returns 0 on a successful allocation of the metadata blocks in the + * block group. */ -static void ext4_alloc_group_tables(struct super_block *sb, +static int ext4_alloc_group_tables(struct super_block *sb, struct ext4_new_flex_group_data *flex_gd, int flexbg_size) { @@ -226,6 +229,8 @@ static void ext4_alloc_group_tables(struct super_block *sb, (last_group & ~(flexbg_size - 1)))); next_group: group = group_data[0].group; + if (src_group >= group_data[0].group + flex_gd->count) + return -ENOSPC; start_blk = ext4_group_first_block_no(sb, src_group); last_blk = start_blk + group_data[src_group - group].blocks_count; @@ -235,7 +240,6 @@ static void ext4_alloc_group_tables(struct super_block *sb, start_blk += overhead; - BUG_ON(src_group >= group_data[0].group + flex_gd->count); /* We collect contiguous blocks as much as possible. */ src_group++; for (; src_group <= last_group; src_group++) @@ -300,6 +304,7 @@ static void ext4_alloc_group_tables(struct super_block *sb, group_data[i].free_blocks_count); } } + return 0; } static struct buffer_head *bclean(handle_t *handle, struct super_block *sb, @@ -1676,7 +1681,8 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count) */ while (ext4_setup_next_flex_gd(sb, flex_gd, n_blocks_count, flexbg_size)) { - ext4_alloc_group_tables(sb, flex_gd, flexbg_size); + if (ext4_alloc_group_tables(sb, flex_gd, flexbg_size) != 0) + break; err = ext4_flex_group_add(sb, resize_inode, flex_gd); if (unlikely(err)) break; -- GitLab From 1079d76f47379886ebfd3ae0f79a9f6cd62df29e Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Wed, 5 Sep 2012 01:25:50 -0400 Subject: [PATCH 0690/1799] ext4: don't copy non-existent gdt blocks when resizing commit 6df935ad2fced9033ab52078825fcaf6365f34b7 upstream. The resize code was copying blocks at the beginning of each block group in order to copy the superblock and block group descriptor table (gdt) blocks. This was, unfortunately, being done even for block groups that did not have super blocks or gdt blocks. This is a complete waste of perfectly good I/O bandwidth, to skip writing those blocks for sparse bg's. Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/resize.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 46d9ec8453f2..257d2f00311f 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -456,6 +456,9 @@ static int setup_new_flex_group_blocks(struct super_block *sb, gdblocks = ext4_bg_num_gdb(sb, group); start = ext4_group_first_block_no(sb, group); + if (!ext4_bg_has_super(sb, group)) + goto handle_itb; + /* Copy all of the GDT blocks into the backup in this group */ for (j = 0, block = start + 1; j < gdblocks; j++, block++) { struct buffer_head *gdb; @@ -498,6 +501,7 @@ static int setup_new_flex_group_blocks(struct super_block *sb, goto out; } +handle_itb: /* Initialize group tables of the grop @group */ if (!(bg_flags[i] & EXT4_BG_INODE_ZEROED)) goto handle_bb; -- GitLab From 2de1ece4de710668bb53eff74bffe80bb267087f Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Wed, 5 Sep 2012 01:27:50 -0400 Subject: [PATCH 0691/1799] ext4: avoid duplicate writes of the backup bg descriptor blocks commit 2ebd1704ded88a8ae29b5f3998b13959c715c4be upstream. The resize code was needlessly writing the backup block group descriptor blocks multiple times (once per block group) during an online resize. Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/resize.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 257d2f00311f..231cacb8f640 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -1302,13 +1302,15 @@ static int ext4_flex_group_add(struct super_block *sb, err = err2; if (!err) { - int i; + int gdb_num = group / EXT4_DESC_PER_BLOCK(sb); + int gdb_num_end = ((group + flex_gd->count - 1) / + EXT4_DESC_PER_BLOCK(sb)); + update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es, sizeof(struct ext4_super_block)); - for (i = 0; i < flex_gd->count; i++, group++) { + for (; gdb_num <= gdb_num_end; gdb_num++) { struct buffer_head *gdb_bh; - int gdb_num; - gdb_num = group / EXT4_BLOCKS_PER_GROUP(sb); + gdb_bh = sbi->s_group_desc[gdb_num]; update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data, gdb_bh->b_size); -- GitLab From 78790d120fd2a6ffa39dc23e57fdf9133e67b14c Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 19 Sep 2012 22:42:36 -0400 Subject: [PATCH 0692/1799] ext4: fix potential deadlock in ext4_nonda_switch() commit 00d4e7362ed01987183e9528295de3213031309c upstream. In ext4_nonda_switch(), if the file system is getting full we used to call writeback_inodes_sb_if_idle(). The problem is that we can be holding i_mutex already, and this causes a potential deadlock when writeback_inodes_sb_if_idle() when it tries to take s_umount. (See lockdep output below). As it turns out we don't need need to hold s_umount; the fact that we are in the middle of the write(2) system call will keep the superblock pinned. Unfortunately writeback_inodes_sb() checks to make sure s_umount is taken, and the VFS uses a different mechanism for making sure the file system doesn't get unmounted out from under us. The simplest way of dealing with this is to just simply grab s_umount using a trylock, and skip kicking the writeback flusher thread in the very unlikely case that we can't take a read lock on s_umount without blocking. Also, we now check the cirteria for kicking the writeback thread before we decide to whether to fall back to non-delayed writeback, so if there are any outstanding delayed allocation writes, we try to get them resolved as soon as possible. [ INFO: possible circular locking dependency detected ] 3.6.0-rc1-00042-gce894ca #367 Not tainted ------------------------------------------------------- dd/8298 is trying to acquire lock: (&type->s_umount_key#18){++++..}, at: [] writeback_inodes_sb_if_idle+0x28/0x46 but task is already holding lock: (&sb->s_type->i_mutex_key#8){+.+...}, at: [] generic_file_aio_write+0x5f/0xd3 which lock already depends on the new lock. 2 locks held by dd/8298: #0: (sb_writers#2){.+.+.+}, at: [] generic_file_aio_write+0x56/0xd3 #1: (&sb->s_type->i_mutex_key#8){+.+...}, at: [] generic_file_aio_write+0x5f/0xd3 stack backtrace: Pid: 8298, comm: dd Not tainted 3.6.0-rc1-00042-gce894ca #367 Call Trace: [] ? console_unlock+0x345/0x372 [] print_circular_bug+0x190/0x19d [] __lock_acquire+0x86d/0xb6c [] ? mark_held_locks+0x5c/0x7b [] lock_acquire+0x66/0xb9 [] ? writeback_inodes_sb_if_idle+0x28/0x46 [] down_read+0x28/0x58 [] ? writeback_inodes_sb_if_idle+0x28/0x46 [] writeback_inodes_sb_if_idle+0x28/0x46 [] ext4_nonda_switch+0xe1/0xf4 [] ext4_da_write_begin+0x27/0x193 [] generic_file_buffered_write+0xc8/0x1bb [] __generic_file_aio_write+0x1dd/0x205 [] generic_file_aio_write+0x78/0xd3 [] ext4_file_write+0x480/0x4a6 [] ? __lock_acquire+0x41e/0xb6c [] ? sched_clock_cpu+0x11a/0x13e [] ? trace_hardirqs_off+0xb/0xd [] ? local_clock+0x37/0x4e [] do_sync_write+0x67/0x9d [] ? wait_on_retry_sync_kiocb+0x44/0x44 [] vfs_write+0x7b/0xe6 [] sys_write+0x3b/0x64 [] syscall_call+0x7/0xb Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 17 ++++++++++------- fs/fs-writeback.c | 1 + 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 55a654d86182..45c544fe3aee 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2386,6 +2386,16 @@ static int ext4_nonda_switch(struct super_block *sb) free_blocks = EXT4_C2B(sbi, percpu_counter_read_positive(&sbi->s_freeclusters_counter)); dirty_blocks = percpu_counter_read_positive(&sbi->s_dirtyclusters_counter); + /* + * Start pushing delalloc when 1/2 of free blocks are dirty. + */ + if (dirty_blocks && (free_blocks < 2 * dirty_blocks) && + !writeback_in_progress(sb->s_bdi) && + down_read_trylock(&sb->s_umount)) { + writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE); + up_read(&sb->s_umount); + } + if (2 * free_blocks < 3 * dirty_blocks || free_blocks < (dirty_blocks + EXT4_FREECLUSTERS_WATERMARK)) { /* @@ -2394,13 +2404,6 @@ static int ext4_nonda_switch(struct super_block *sb) */ return 1; } - /* - * Even if we don't switch but are nearing capacity, - * start pushing delalloc when 1/2 of free blocks are dirty. - */ - if (free_blocks < 2 * dirty_blocks) - writeback_inodes_sb_if_idle(sb, WB_REASON_FS_FREE_SPACE); - return 0; } diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 539f36cf3e4a..b35bd64fb548 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -68,6 +68,7 @@ int writeback_in_progress(struct backing_dev_info *bdi) { return test_bit(BDI_writeback_running, &bdi->state); } +EXPORT_SYMBOL(writeback_in_progress); static inline struct backing_dev_info *inode_to_bdi(struct inode *inode) { -- GitLab From d49765a2110de8ac18aa74373ae89c1e4484b5d6 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Sun, 23 Sep 2012 22:49:12 -0400 Subject: [PATCH 0693/1799] ext4: fix crash when accessing /proc/mounts concurrently commit 50df9fd55e4271e89a7adf3b1172083dd0ca199d upstream. The crash was caused by a variable being erronously declared static in token2str(). In addition to /proc/mounts, the problem can also be easily replicated by accessing /proc/fs/ext4//options in parallel: $ cat /proc/fs/ext4//options > options.txt ... and then running the following command in two different terminals: $ while diff /proc/fs/ext4//options options.txt; do true; done This is also the cause of the following a crash while running xfstests #234, as reported in the following bug reports: https://bugs.launchpad.net/bugs/1053019 https://bugzilla.kernel.org/show_bug.cgi?id=47731 Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: "Theodore Ts'o" Cc: Brad Figg Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 12a278ff82a8..b1c28f18701c 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1692,7 +1692,7 @@ static inline void ext4_show_quota_options(struct seq_file *seq, static const char *token2str(int token) { - static const struct match_token *t; + const struct match_token *t; for (t = tokens; t->token != Opt_err; t++) if (t->token == token && !strchr(t->pattern, '=')) -- GitLab From 67bec353575f1205425c07bd76dbe5dfeb950a1e Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Wed, 26 Sep 2012 12:32:19 -0400 Subject: [PATCH 0694/1799] ext4: move_extent code cleanup commit 03bd8b9b896c8e940f282f540e6b4de90d666b7c upstream. - Remove usless checks, because it is too late to check that inode != NULL at the moment it was referenced several times. - Double lock routines looks very ugly and locking ordering relays on order of i_ino, but other kernel code rely on order of pointers. Let's make them simple and clean. - check that inodes belongs to the same SB as soon as possible. Signed-off-by: Dmitry Monakhov Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/move_extent.c | 167 ++++++++++++------------------------------ 1 file changed, 47 insertions(+), 120 deletions(-) diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index c5826c623e7a..df5cde5130c5 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -140,56 +140,22 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path, return 1; } -/** - * mext_check_null_inode - NULL check for two inodes - * - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0. - */ -static int -mext_check_null_inode(struct inode *inode1, struct inode *inode2, - const char *function, unsigned int line) -{ - int ret = 0; - - if (inode1 == NULL) { - __ext4_error(inode2->i_sb, function, line, - "Both inodes should not be NULL: " - "inode1 NULL inode2 %lu", inode2->i_ino); - ret = -EIO; - } else if (inode2 == NULL) { - __ext4_error(inode1->i_sb, function, line, - "Both inodes should not be NULL: " - "inode1 %lu inode2 NULL", inode1->i_ino); - ret = -EIO; - } - return ret; -} - /** * double_down_write_data_sem - Acquire two inodes' write lock of i_data_sem * - * @orig_inode: original inode structure - * @donor_inode: donor inode structure - * Acquire write lock of i_data_sem of the two inodes (orig and donor) by - * i_ino order. + * Acquire write lock of i_data_sem of the two inodes */ static void -double_down_write_data_sem(struct inode *orig_inode, struct inode *donor_inode) +double_down_write_data_sem(struct inode *first, struct inode *second) { - struct inode *first = orig_inode, *second = donor_inode; + if (first < second) { + down_write(&EXT4_I(first)->i_data_sem); + down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING); + } else { + down_write(&EXT4_I(second)->i_data_sem); + down_write_nested(&EXT4_I(first)->i_data_sem, SINGLE_DEPTH_NESTING); - /* - * Use the inode number to provide the stable locking order instead - * of its address, because the C language doesn't guarantee you can - * compare pointers that don't come from the same array. - */ - if (donor_inode->i_ino < orig_inode->i_ino) { - first = donor_inode; - second = orig_inode; } - - down_write(&EXT4_I(first)->i_data_sem); - down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING); } /** @@ -969,14 +935,6 @@ mext_check_arguments(struct inode *orig_inode, return -EINVAL; } - /* Files should be in the same ext4 FS */ - if (orig_inode->i_sb != donor_inode->i_sb) { - ext4_debug("ext4 move extent: The argument files " - "should be in same FS [ino:orig %lu, donor %lu]\n", - orig_inode->i_ino, donor_inode->i_ino); - return -EINVAL; - } - /* Ext4 move extent supports only extent based file */ if (!(ext4_test_inode_flag(orig_inode, EXT4_INODE_EXTENTS))) { ext4_debug("ext4 move extent: orig file is not extents " @@ -1072,35 +1030,19 @@ mext_check_arguments(struct inode *orig_inode, * @inode1: the inode structure * @inode2: the inode structure * - * Lock two inodes' i_mutex by i_ino order. - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0. + * Lock two inodes' i_mutex */ -static int +static void mext_inode_double_lock(struct inode *inode1, struct inode *inode2) { - int ret = 0; - - BUG_ON(inode1 == NULL && inode2 == NULL); - - ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__); - if (ret < 0) - goto out; - - if (inode1 == inode2) { - mutex_lock(&inode1->i_mutex); - goto out; - } - - if (inode1->i_ino < inode2->i_ino) { + BUG_ON(inode1 == inode2); + if (inode1 < inode2) { mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD); } else { mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT); mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD); } - -out: - return ret; } /** @@ -1109,28 +1051,13 @@ mext_inode_double_lock(struct inode *inode1, struct inode *inode2) * @inode1: the inode that is released first * @inode2: the inode that is released second * - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0. */ -static int +static void mext_inode_double_unlock(struct inode *inode1, struct inode *inode2) { - int ret = 0; - - BUG_ON(inode1 == NULL && inode2 == NULL); - - ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__); - if (ret < 0) - goto out; - - if (inode1) - mutex_unlock(&inode1->i_mutex); - - if (inode2 && inode2 != inode1) - mutex_unlock(&inode2->i_mutex); - -out: - return ret; + mutex_unlock(&inode1->i_mutex); + mutex_unlock(&inode2->i_mutex); } /** @@ -1187,16 +1114,23 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, ext4_lblk_t block_end, seq_start, add_blocks, file_end, seq_blocks = 0; ext4_lblk_t rest_blocks; pgoff_t orig_page_offset = 0, seq_end_page; - int ret1, ret2, depth, last_extent = 0; + int ret, depth, last_extent = 0; int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits; int data_offset_in_page; int block_len_in_page; int uninit; - /* orig and donor should be different file */ - if (orig_inode->i_ino == donor_inode->i_ino) { + if (orig_inode->i_sb != donor_inode->i_sb) { + ext4_debug("ext4 move extent: The argument files " + "should be in same FS [ino:orig %lu, donor %lu]\n", + orig_inode->i_ino, donor_inode->i_ino); + return -EINVAL; + } + + /* orig and donor should be different inodes */ + if (orig_inode == donor_inode) { ext4_debug("ext4 move extent: The argument files should not " - "be same file [ino:orig %lu, donor %lu]\n", + "be same inode [ino:orig %lu, donor %lu]\n", orig_inode->i_ino, donor_inode->i_ino); return -EINVAL; } @@ -1210,16 +1144,14 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, } /* Protect orig and donor inodes against a truncate */ - ret1 = mext_inode_double_lock(orig_inode, donor_inode); - if (ret1 < 0) - return ret1; + mext_inode_double_lock(orig_inode, donor_inode); /* Protect extent tree against block allocations via delalloc */ double_down_write_data_sem(orig_inode, donor_inode); /* Check the filesystem environment whether move_extent can be done */ - ret1 = mext_check_arguments(orig_inode, donor_inode, orig_start, + ret = mext_check_arguments(orig_inode, donor_inode, orig_start, donor_start, &len); - if (ret1) + if (ret) goto out; file_end = (i_size_read(orig_inode) - 1) >> orig_inode->i_blkbits; @@ -1227,13 +1159,13 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, if (file_end < block_end) len -= block_end - file_end; - ret1 = get_ext_path(orig_inode, block_start, &orig_path); - if (ret1) + ret = get_ext_path(orig_inode, block_start, &orig_path); + if (ret) goto out; /* Get path structure to check the hole */ - ret1 = get_ext_path(orig_inode, block_start, &holecheck_path); - if (ret1) + ret = get_ext_path(orig_inode, block_start, &holecheck_path); + if (ret) goto out; depth = ext_depth(orig_inode); @@ -1252,13 +1184,13 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, last_extent = mext_next_extent(orig_inode, holecheck_path, &ext_cur); if (last_extent < 0) { - ret1 = last_extent; + ret = last_extent; goto out; } last_extent = mext_next_extent(orig_inode, orig_path, &ext_dummy); if (last_extent < 0) { - ret1 = last_extent; + ret = last_extent; goto out; } seq_start = le32_to_cpu(ext_cur->ee_block); @@ -1272,7 +1204,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, if (le32_to_cpu(ext_cur->ee_block) > block_end) { ext4_debug("ext4 move extent: The specified range of file " "may be the hole\n"); - ret1 = -EINVAL; + ret = -EINVAL; goto out; } @@ -1292,7 +1224,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, last_extent = mext_next_extent(orig_inode, holecheck_path, &ext_cur); if (last_extent < 0) { - ret1 = last_extent; + ret = last_extent; break; } add_blocks = ext4_ext_get_actual_len(ext_cur); @@ -1349,18 +1281,18 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, orig_page_offset, data_offset_in_page, block_len_in_page, uninit, - &ret1); + &ret); /* Count how many blocks we have exchanged */ *moved_len += block_len_in_page; - if (ret1 < 0) + if (ret < 0) break; if (*moved_len > len) { EXT4_ERROR_INODE(orig_inode, "We replaced blocks too much! " "sum of replaced: %llu requested: %llu", *moved_len, len); - ret1 = -EIO; + ret = -EIO; break; } @@ -1374,22 +1306,22 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, } double_down_write_data_sem(orig_inode, donor_inode); - if (ret1 < 0) + if (ret < 0) break; /* Decrease buffer counter */ if (holecheck_path) ext4_ext_drop_refs(holecheck_path); - ret1 = get_ext_path(orig_inode, seq_start, &holecheck_path); - if (ret1) + ret = get_ext_path(orig_inode, seq_start, &holecheck_path); + if (ret) break; depth = holecheck_path->p_depth; /* Decrease buffer counter */ if (orig_path) ext4_ext_drop_refs(orig_path); - ret1 = get_ext_path(orig_inode, seq_start, &orig_path); - if (ret1) + ret = get_ext_path(orig_inode, seq_start, &orig_path); + if (ret) break; ext_cur = holecheck_path[depth].p_ext; @@ -1412,12 +1344,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, kfree(holecheck_path); } double_up_write_data_sem(orig_inode, donor_inode); - ret2 = mext_inode_double_unlock(orig_inode, donor_inode); + mext_inode_double_unlock(orig_inode, donor_inode); - if (ret1) - return ret1; - else if (ret2) - return ret2; - - return 0; + return ret; } -- GitLab From a4bf81c2bf891cbd46d6a69ba15dd7d4350b62f3 Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Wed, 26 Sep 2012 12:32:54 -0400 Subject: [PATCH 0695/1799] ext4: online defrag is not supported for journaled files commit f066055a3449f0e5b0ae4f3ceab4445bead47638 upstream. Proper block swap for inodes with full journaling enabled is truly non obvious task. In order to be on a safe side let's explicitly disable it for now. Signed-off-by: Dmitry Monakhov Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/move_extent.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index df5cde5130c5..e2016f34b58f 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -1142,7 +1142,12 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, orig_inode->i_ino, donor_inode->i_ino); return -EINVAL; } - + /* TODO: This is non obvious task to swap blocks for inodes with full + jornaling enabled */ + if (ext4_should_journal_data(orig_inode) || + ext4_should_journal_data(donor_inode)) { + return -EINVAL; + } /* Protect orig and donor inodes against a truncate */ mext_inode_double_lock(orig_inode, donor_inode); -- GitLab From 7061315f57c1dfa81d3d9b2f0efb50ce2b6f3371 Mon Sep 17 00:00:00 2001 From: Bernd Schubert Date: Wed, 26 Sep 2012 21:24:57 -0400 Subject: [PATCH 0696/1799] ext4: always set i_op in ext4_mknod() commit 6a08f447facb4f9e29fcc30fb68060bb5a0d21c2 upstream. ext4_special_inode_operations have their own ifdef CONFIG_EXT4_FS_XATTR to mask those methods. And ext4_iget also always sets it, so there is an inconsistency. Signed-off-by: Bernd Schubert Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/namei.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 0a94cbbe8828..ac769399b141 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1801,9 +1801,7 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry, err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, inode->i_mode, rdev); -#ifdef CONFIG_EXT4_FS_XATTR inode->i_op = &ext4_special_inode_operations; -#endif err = ext4_add_nondir(handle, dentry, inode); } ext4_journal_stop(handle); -- GitLab From e87ba35f1fba828bb198bdf89704eb9583932da8 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 26 Sep 2012 21:52:20 -0400 Subject: [PATCH 0697/1799] ext4: fix fdatasync() for files with only i_size changes commit b71fc079b5d8f42b2a52743c8d2f1d35d655b1c5 upstream. Code tracking when transaction needs to be committed on fdatasync(2) forgets to handle a situation when only inode's i_size is changed. Thus in such situations fdatasync(2) doesn't force transaction with new i_size to disk and that can result in wrong i_size after a crash. Fix the issue by updating inode's i_datasync_tid whenever its size is updated. Reported-by: Kristian Nielsen Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 45c544fe3aee..dcd08e485762 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3892,6 +3892,7 @@ static int ext4_do_update_inode(handle_t *handle, struct ext4_inode_info *ei = EXT4_I(inode); struct buffer_head *bh = iloc->bh; int err = 0, rc, block; + int need_datasync = 0; /* For fields not not tracking in the in-memory inode, * initialise them to zero for new inodes. */ @@ -3940,7 +3941,10 @@ static int ext4_do_update_inode(handle_t *handle, raw_inode->i_file_acl_high = cpu_to_le16(ei->i_file_acl >> 32); raw_inode->i_file_acl_lo = cpu_to_le32(ei->i_file_acl); - ext4_isize_set(raw_inode, ei->i_disksize); + if (ei->i_disksize != ext4_isize(raw_inode)) { + ext4_isize_set(raw_inode, ei->i_disksize); + need_datasync = 1; + } if (ei->i_disksize > 0x7fffffffULL) { struct super_block *sb = inode->i_sb; if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, @@ -3991,7 +3995,7 @@ static int ext4_do_update_inode(handle_t *handle, err = rc; ext4_clear_inode_state(inode, EXT4_STATE_NEW); - ext4_update_inode_fsync_trans(handle, inode, 0); + ext4_update_inode_fsync_trans(handle, inode, need_datasync); out_brelse: brelse(bh); ext4_std_error(inode->i_sb, err); -- GitLab From 62bd817182be053f1c6dde95748d34fd7be27bb0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 Jul 2012 18:37:29 +0100 Subject: [PATCH 0698/1799] ASoC: wm9712: Fix name of Capture Switch commit 689185b78ba6fbe0042f662a468b5565909dff7a upstream. Help UIs associate it with the matching gain control. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm9712.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index b9567bc16aea..757a52aed804 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -146,7 +146,7 @@ SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0), SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1), SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), -SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1), +SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1), SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1), SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), -- GitLab From 70fb727d0900836b71ebf7a7badaa7b7c9068102 Mon Sep 17 00:00:00 2001 From: Naoya Horiguchi Date: Mon, 8 Oct 2012 16:33:47 -0700 Subject: [PATCH 0699/1799] kpageflags: fix wrong KPF_THP on non-huge compound pages commit 7a71932d5676b7410ab64d149bad8bde6b0d8632 upstream. KPF_THP can be set on non-huge compound pages (like slab pages or pages allocated by drivers with __GFP_COMP) because PageTransCompound only checks PG_head and PG_tail. Obviously this is a bug and breaks user space applications which look for thp via /proc/kpageflags. This patch rules out setting KPF_THP wrongly by additionally checking PageLRU on the head pages. Signed-off-by: Naoya Horiguchi Acked-by: KOSAKI Motohiro Acked-by: David Rientjes Reviewed-by: Fengguang Wu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/proc/page.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/proc/page.c b/fs/proc/page.c index 7fcd0d60a968..b8730d9ebaee 100644 --- a/fs/proc/page.c +++ b/fs/proc/page.c @@ -115,7 +115,13 @@ u64 stable_page_flags(struct page *page) u |= 1 << KPF_COMPOUND_TAIL; if (PageHuge(page)) u |= 1 << KPF_HUGE; - else if (PageTransCompound(page)) + /* + * PageTransCompound can be true for non-huge compound pages (slab + * pages or pages allocated by drivers with __GFP_COMP) because it + * just checks PG_head/PG_tail, so we need to check PageLRU to make + * sure a given page is a thp, not a non-huge compound page. + */ + else if (PageTransCompound(page) && PageLRU(compound_trans_head(page))) u |= 1 << KPF_THP; /* -- GitLab From 26fc07d8da4aa118cfe44776c2d2ddef8ef5f641 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Mon, 8 Oct 2012 16:33:31 -0700 Subject: [PATCH 0700/1799] hugetlb: do not use vma_hugecache_offset() for vma_prio_tree_foreach commit 36e4f20af833d1ce196e6a4ade05dc26c44652d1 upstream. Commit 0c176d52b0b2 ("mm: hugetlb: fix pgoff computation when unmapping page from vma") fixed pgoff calculation but it has replaced it by vma_hugecache_offset() which is not approapriate for offsets used for vma_prio_tree_foreach() because that one expects index in page units rather than in huge_page_shift. Johannes said: : The resulting index may not be too big, but it can be too small: assume : hpage size of 2M and the address to unmap to be 0x200000. This is regular : page index 512 and hpage index 1. If you have a VMA that maps the file : only starting at the second huge page, that VMAs vm_pgoff will be 512 but : you ask for offset 1 and miss it even though it does map the page of : interest. hugetlb_cow() will try to unmap, miss the vma, and retry the : cow until the allocation succeeds or the skipped vma(s) go away. Signed-off-by: Michal Hocko Acked-by: Hillf Danton Cc: Mel Gorman Cc: KAMEZAWA Hiroyuki Cc: Andrea Arcangeli Cc: David Rientjes Acked-by: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/hugetlb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index a799df59d310..c384e0901f9c 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2431,7 +2431,8 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, * from page cache lookup which is in HPAGE_SIZE units. */ address = address & huge_page_mask(h); - pgoff = vma_hugecache_offset(h, vma, address); + pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + + vma->vm_pgoff; mapping = vma->vm_file->f_dentry->d_inode->i_mapping; /* -- GitLab From 6a91e161a7f1b0125822b1693ea8fe46035b0f1b Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 8 Oct 2012 16:33:14 -0700 Subject: [PATCH 0701/1799] mm: fix invalidate_complete_page2() lock ordering commit ec4d9f626d5908b6052c2973f37992f1db52e967 upstream. In fuzzing with trinity, lockdep protested "possible irq lock inversion dependency detected" when isolate_lru_page() reenabled interrupts while still holding the supposedly irq-safe tree_lock: invalidate_inode_pages2 invalidate_complete_page2 spin_lock_irq(&mapping->tree_lock) clear_page_mlock isolate_lru_page spin_unlock_irq(&zone->lru_lock) isolate_lru_page() is correct to enable interrupts unconditionally: invalidate_complete_page2() is incorrect to call clear_page_mlock() while holding tree_lock, which is supposed to nest inside lru_lock. Both truncate_complete_page() and invalidate_complete_page() call clear_page_mlock() before taking tree_lock to remove page from radix_tree. I guess invalidate_complete_page2() preferred to test PageDirty (again) under tree_lock before committing to the munlock; but since the page has already been unmapped, its state is already somewhat inconsistent, and no worse if clear_page_mlock() moved up. Reported-by: Sasha Levin Deciphered-by: Andrew Morton Signed-off-by: Hugh Dickins Acked-by: Mel Gorman Cc: Rik van Riel Cc: Johannes Weiner Cc: Michel Lespinasse Cc: Ying Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/truncate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/truncate.c b/mm/truncate.c index 61a183b89df6..4224627695ba 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -394,11 +394,12 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page) if (page_has_private(page) && !try_to_release_page(page, GFP_KERNEL)) return 0; + clear_page_mlock(page); + spin_lock_irq(&mapping->tree_lock); if (PageDirty(page)) goto failed; - clear_page_mlock(page); BUG_ON(page_has_private(page)); __delete_from_page_cache(page); spin_unlock_irq(&mapping->tree_lock); -- GitLab From c3b9446604af20c426b37b8191d9d089b40f5899 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Mon, 8 Oct 2012 16:33:27 -0700 Subject: [PATCH 0702/1799] mm: thp: fix pmd_present for split_huge_page and PROT_NONE with THP commit 027ef6c87853b0a9df53175063028edb4950d476 upstream. In many places !pmd_present has been converted to pmd_none. For pmds that's equivalent and pmd_none is quicker so using pmd_none is better. However (unless we delete pmd_present) we should provide an accurate pmd_present too. This will avoid the risk of code thinking the pmd is non present because it's under __split_huge_page_map, see the pmd_mknotpresent there and the comment above it. If the page has been mprotected as PROT_NONE, it would also lead to a pmd_present false negative in the same way as the race with split_huge_page. Because the PSE bit stays on at all times (both during split_huge_page and when the _PAGE_PROTNONE bit get set), we could only check for the PSE bit, but checking the PROTNONE bit too is still good to remember pmd_present must always keep PROT_NONE into account. This explains a not reproducible BUG_ON that was seldom reported on the lists. The same issue is in pmd_large, it would go wrong with both PROT_NONE and if it races with split_huge_page. Signed-off-by: Andrea Arcangeli Acked-by: Rik van Riel Cc: Johannes Weiner Cc: Hugh Dickins Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/pgtable.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 49afb3f41eb6..c3520d76820e 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -146,8 +146,7 @@ static inline unsigned long pmd_pfn(pmd_t pmd) static inline int pmd_large(pmd_t pte) { - return (pmd_flags(pte) & (_PAGE_PSE | _PAGE_PRESENT)) == - (_PAGE_PSE | _PAGE_PRESENT); + return pmd_flags(pte) & _PAGE_PSE; } #ifdef CONFIG_TRANSPARENT_HUGEPAGE @@ -415,7 +414,13 @@ static inline int pte_hidden(pte_t pte) static inline int pmd_present(pmd_t pmd) { - return pmd_flags(pmd) & _PAGE_PRESENT; + /* + * Checking for _PAGE_PSE is needed too because + * split_huge_page will temporarily clear the present bit (but + * the _PAGE_PSE flag will remain set at all times while the + * _PAGE_PRESENT bit is clear). + */ + return pmd_flags(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_PSE); } static inline int pmd_none(pmd_t pmd) -- GitLab From 4ca1a84f737e7f8166aed08ba87f5acc49120da9 Mon Sep 17 00:00:00 2001 From: Omair Mohammed Abdullah Date: Sat, 29 Sep 2012 12:24:05 +0530 Subject: [PATCH 0703/1799] ALSA: aloop - add locking to timer access commit d4f1e48bd11e3df6a26811f7a1f06c4225d92f7d upstream. When the loopback timer handler is running, calling del_timer() (for STOP trigger) will not wait for the handler to complete before deactivating the timer. The timer gets rescheduled in the handler as usual. Then a subsequent START trigger will try to start the timer using add_timer() with a timer pending leading to a kernel panic. Serialize the calls to add_timer() and del_timer() using a spin lock to avoid this. Signed-off-by: Omair Mohammed Abdullah Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/drivers/aloop.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index ad079b63b8ba..bdc963e722ad 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -119,6 +119,7 @@ struct loopback_pcm { unsigned int period_size_frac; unsigned long last_jiffies; struct timer_list timer; + spinlock_t timer_lock; }; static struct platform_device *devices[SNDRV_CARDS]; @@ -169,6 +170,7 @@ static void loopback_timer_start(struct loopback_pcm *dpcm) unsigned long tick; unsigned int rate_shift = get_rate_shift(dpcm); + spin_lock(&dpcm->timer_lock); if (rate_shift != dpcm->pcm_rate_shift) { dpcm->pcm_rate_shift = rate_shift; dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size); @@ -181,12 +183,15 @@ static void loopback_timer_start(struct loopback_pcm *dpcm) tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; dpcm->timer.expires = jiffies + tick; add_timer(&dpcm->timer); + spin_unlock(&dpcm->timer_lock); } static inline void loopback_timer_stop(struct loopback_pcm *dpcm) { + spin_lock(&dpcm->timer_lock); del_timer(&dpcm->timer); dpcm->timer.expires = 0; + spin_unlock(&dpcm->timer_lock); } #define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) @@ -659,6 +664,7 @@ static int loopback_open(struct snd_pcm_substream *substream) dpcm->substream = substream; setup_timer(&dpcm->timer, loopback_timer_function, (unsigned long)dpcm); + spin_lock_init(&dpcm->timer_lock); cable = loopback->cables[substream->number][dev]; if (!cable) { -- GitLab From c8ab5d973cd5439ae0223ca259f0e20963905bef Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Thu, 27 Sep 2012 10:38:14 -0300 Subject: [PATCH 0704/1799] ALSA: hda/realtek - Fix detection of ALC271X codec commit 9f720bb9409ea5923361fbd3fdbc505ca36cf012 upstream. In commit af741c1 ("ALSA: hda/realtek - Call alc_auto_parse_customize_define() always after fixup"), alc_auto_parse_customize_define was moved after detection of ALC271X. The problem is that detection of ALC271X relies on spec->cdefine.platform_type, and it's set on alc_auto_parse_customize_define. Move the alc_auto_parse_customize_define and its required fixup setup before the block doing the ALC271X and other codec setup. BugLink: https://bugs.launchpad.net/bugs/1006690 Signed-off-by: Herton Ronaldo Krzesinski Reviewed-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 52e7a45f6e57..e7cb4bd25d22 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6307,6 +6307,12 @@ static int patch_alc269(struct hda_codec *codec) if (err < 0) goto error; + alc_pick_fixup(codec, alc269_fixup_models, + alc269_fixup_tbl, alc269_fixups); + alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); + + alc_auto_parse_customize_define(codec); + if (codec->vendor_id == 0x10ec0269) { spec->codec_variant = ALC269_TYPE_ALC269VA; switch (alc_get_coef0(codec) & 0x00f0) { @@ -6331,12 +6337,6 @@ static int patch_alc269(struct hda_codec *codec) alc269_fill_coef(codec); } - alc_pick_fixup(codec, alc269_fixup_models, - alc269_fixup_tbl, alc269_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - - alc_auto_parse_customize_define(codec); - /* automatic parse from the BIOS config */ err = alc269_parse_auto_config(codec); if (err < 0) -- GitLab From 92c635bfcd86aa182b9a6734426e61e1420579d7 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 20 Sep 2012 10:20:41 +0200 Subject: [PATCH 0705/1799] ALSA: usb - disable broken hw volume for Tenx TP6911 commit c10514394ef9e8de93a4ad8c8904d71dcd82c122 upstream. While going through Ubuntu bugs, I discovered this patch being posted and a confirmation that the patch works as expected. Finding out how the hw volume really works would be preferrable to just disabling the broken one, but this would be better than nothing. Credit: sndfnsdfin (qawsnews) BugLink: https://bugs.launchpad.net/bugs/559939 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/mixer.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index ab23869c01bb..8a818a4573af 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1247,6 +1247,13 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void /* disable non-functional volume control */ master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME); break; + case USB_ID(0x1130, 0xf211): + snd_printk(KERN_INFO + "usbmixer: volume control quirk for Tenx TP6911 Audio Headset\n"); + /* disable non-functional volume control */ + channels = 0; + break; + } if (channels > 0) first_ch_bits = snd_usb_combine_bytes(bmaControls + csize, csize); -- GitLab From 3e0f62d7750436e35540df761dcc2d8b01a9a5bf Mon Sep 17 00:00:00 2001 From: Marko Friedemann Date: Mon, 3 Sep 2012 10:12:40 +0200 Subject: [PATCH 0706/1799] ALSA: USB: Support for (original) Xbox Communicator commit c05fce586d4da2dfe0309bef3795a8586e967bc3 upstream. Added support for Xbox Communicator to USB quirks. Signed-off-by: Marko Friedemann Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/quirks-table.h | 53 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index d89ab4c7d44b..63128cd62544 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2751,6 +2751,59 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, +/* Microsoft XboxLive Headset/Xbox Communicator */ +{ + USB_DEVICE(0x045e, 0x0283), + .bInterfaceClass = USB_CLASS_PER_INTERFACE, + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Microsoft", + .product_name = "XboxLive Headset/Xbox Communicator", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = &(const struct snd_usb_audio_quirk[]) { + { + /* playback */ + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels = 1, + .iface = 0, + .altsetting = 0, + .altset_idx = 0, + .attributes = 0, + .endpoint = 0x04, + .ep_attr = 0x05, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 22050, + .rate_max = 22050 + } + }, + { + /* capture */ + .ifnum = 1, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels = 1, + .iface = 1, + .altsetting = 0, + .altset_idx = 0, + .attributes = 0, + .endpoint = 0x85, + .ep_attr = 0x05, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 16000, + .rate_max = 16000 + } + }, + { + .ifnum = -1 + } + } + } +}, + { /* * Some USB MIDI devices don't have an audio control interface, -- GitLab From 507130a9e351f5662785a8a09ccdc5687b01aabe Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 17 Sep 2012 09:38:03 +0000 Subject: [PATCH 0707/1799] drm: Destroy the planes prior to destroying the associated CRTC commit 3184009c36da413724f283e3c7ac9cc60c623bc4 upstream. As during the plane cleanup, we wish to disable the hardware and so may modify state on the associated CRTC, that CRTC must continue to exist until we are finished. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54101 Signed-off-by: Chris Wilson Cc: Jesse Barnes Reviewed-by: Jesse Barnes Tested-by: lu hua Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_crtc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 7e479a42af0b..4fd363f1656c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1028,15 +1028,15 @@ void drm_mode_config_cleanup(struct drm_device *dev) fb->funcs->destroy(fb); } - list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { - crtc->funcs->destroy(crtc); - } - list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, head) { plane->funcs->destroy(plane); } + list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { + crtc->funcs->destroy(crtc); + } + idr_remove_all(&dev->mode_config.crtc_idr); idr_destroy(&dev->mode_config.crtc_idr); } -- GitLab From 47c3ae0b3b5b360387602c49d7076e6114d05879 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 14 Sep 2012 10:59:26 -0400 Subject: [PATCH 0708/1799] drm/radeon: only adjust default clocks on NI GPUs commit 2e3b3b105ab3bb5b6a37198da4f193cd13781d13 upstream. SI asics store voltage information differently so we don't have a way to deal with it properly yet. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_pm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index caa55d68f319..b8459bdce42e 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -567,7 +567,9 @@ void radeon_pm_suspend(struct radeon_device *rdev) void radeon_pm_resume(struct radeon_device *rdev) { /* set up the default clocks if the MC ucode is loaded */ - if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { + if ((rdev->family >= CHIP_BARTS) && + (rdev->family <= CHIP_CAYMAN) && + rdev->mc_fw) { if (rdev->pm.default_vddc) radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, SET_VOLTAGE_TYPE_ASIC_VDDC); @@ -622,7 +624,9 @@ int radeon_pm_init(struct radeon_device *rdev) radeon_pm_print_states(rdev); radeon_pm_init_profile(rdev); /* set up the default clocks if the MC ucode is loaded */ - if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { + if ((rdev->family >= CHIP_BARTS) && + (rdev->family <= CHIP_CAYMAN) && + rdev->mc_fw) { if (rdev->pm.default_vddc) radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, SET_VOLTAGE_TYPE_ASIC_VDDC); -- GitLab From 60a601fda771cf25df2b702dbba1a3e22e81fa2c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 26 Sep 2012 12:31:45 -0400 Subject: [PATCH 0709/1799] drm/radeon: Add MSI quirk for gateway RS690 commit 3a6d59df80897cc87812b6826d70085905bed013 upstream. Fixes another system on: https://bugs.freedesktop.org/show_bug.cgi?id=37679 Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_irq_kms.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 65060b77c805..a574faab0677 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -147,6 +147,12 @@ static bool radeon_msi_ok(struct radeon_device *rdev) (rdev->pdev->subsystem_device == 0x01fd)) return true; + /* Gateway RS690 only seems to work with MSIs. */ + if ((rdev->pdev->device == 0x791f) && + (rdev->pdev->subsystem_vendor == 0x107b) && + (rdev->pdev->subsystem_device == 0x0185)) + return true; + /* RV515 seems to have MSI issues where it loses * MSI rearms occasionally. This leads to lockups and freezes. * disable it by default. -- GitLab From d59316ee086133955a993855655b24925c0e6b05 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 26 Sep 2012 12:40:45 -0400 Subject: [PATCH 0710/1799] drm/radeon: force MSIs on RS690 asics commit fb6ca6d154cdcd53e7f27f8dbba513830372699b upstream. There are so many quirks, lets just try and force this for all RS690s. See: https://bugs.freedesktop.org/show_bug.cgi?id=37679 Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_irq_kms.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index a574faab0677..645dcbf6490b 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -153,6 +153,10 @@ static bool radeon_msi_ok(struct radeon_device *rdev) (rdev->pdev->subsystem_device == 0x0185)) return true; + /* try and enable MSIs by default on all RS690s */ + if (rdev->family == CHIP_RS690) + return true; + /* RV515 seems to have MSI issues where it loses * MSI rearms occasionally. This leads to lockups and freezes. * disable it by default. -- GitLab From c5a3f2e9981b6da91e70765d0a958a0ac9d14a53 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 24 Aug 2012 13:22:13 -0700 Subject: [PATCH 0711/1799] ia64: Add missing RCU idle APIs on idle loop commit 93482f4ef1093f5961a63359a34612183d6beea0 upstream. Traditionally, the entire idle task served as an RCU quiescent state. But when RCU read side critical sections started appearing within the idle loop, this traditional strategy became untenable. The fix was to create new RCU APIs named rcu_idle_enter() and rcu_idle_exit(), which must be called by each architecture's idle loop so that RCU can tell when it is safe to ignore a given idle CPU. Unfortunately, this fix was never applied to ia64, a shortcoming remedied by this commit. Reported by: Tony Luck Signed-off-by: Paul E. McKenney Signed-off-by: Paul E. McKenney Tested by: Tony Luck Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/ia64/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index ce74e143aea3..86d74ab9800c 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -301,6 +302,7 @@ cpu_idle (void) /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); if (can_do_pal_halt) { current_thread_info()->status &= ~TS_POLLING; /* @@ -331,6 +333,7 @@ cpu_idle (void) normal_xtp(); #endif } + rcu_idle_exit(); schedule_preempt_disabled(); check_pgt_cache(); if (cpu_is_offline(cpu)) -- GitLab From 699d26ccee4e22e324468e94eb648cc89964a15d Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0712/1799] h8300: Add missing RCU idle APIs on idle loop commit b2fe1430d4115c74d007c825cb9dc3317f28bb16 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the h8300's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: Yoshinori Sato Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/h8300/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index 0e9c315be104..f153ed1a4c08 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -78,8 +79,10 @@ void (*idle)(void) = default_idle; void cpu_idle(void) { while (1) { + rcu_idle_enter(); while (!need_resched()) idle(); + rcu_idle_exit(); schedule_preempt_disabled(); } } -- GitLab From d2d41b722e5faf418c1a660eaa602d06e50402eb Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0713/1799] parisc: Add missing RCU idle APIs on idle loop commit fbe752188d5589e7fcbb8e79824e560f77dccc92 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the parisc's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: James E.J. Bottomley Cc: Helge Deller Cc: Parisc Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index d4b94b395c16..c54a4dbcb389 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -69,8 +70,10 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) barrier(); + rcu_idle_exit(); schedule_preempt_disabled(); check_pgt_cache(); } -- GitLab From 2ddcad1f012eb832b5ad61f27888bf36eb495e83 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0714/1799] xtensa: Add missing RCU idle APIs on idle loop commit 11ad47a0edbd62bfc0547cfcdf227a911433f207 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the xtensa's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: Chris Zankel Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/xtensa/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 6a2d6edf8f72..7a41d9ec8ac7 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -110,8 +111,10 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) platform_idle(); + rcu_idle_exit(); schedule_preempt_disabled(); } } -- GitLab From c272355732aaf718ba4c05b0693c0d327ea0de45 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0715/1799] frv: Add missing RCU idle APIs on idle loop commit 41d8fe5bb3cf91ce2716ac8f43e4b40d802a99c8 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the Frv's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: David Howells Acked-by: David Howells Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/frv/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index d4de48bd5efe..3941cbc91ff6 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -84,12 +85,14 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) { check_pgt_cache(); if (!frv_dma_inprogress && idle) idle(); } + rcu_idle_exit(); schedule_preempt_disabled(); } -- GitLab From c7cc1fa9594f1c7fe4de4418dbe9d85c3a4727ee Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0716/1799] mn10300: Add missing RCU idle APIs on idle loop commit 5b0753a90b7a98bc613c3767e9263a1a76d4f900 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the mn10300's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: David Howells Cc: Koichi Yasutake Signed-off-by: Paul E. McKenney Acked-by: David Howells Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/mn10300/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index 14707f25153b..675d8f2c32e9 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,7 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ for (;;) { + rcu_idle_enter(); while (!need_resched()) { void (*idle)(void); @@ -121,6 +123,7 @@ void cpu_idle(void) } idle(); } + rcu_idle_exit(); schedule_preempt_disabled(); } -- GitLab From ce6ccabd21d356ac22973d275f122d3d8efc96d7 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0717/1799] m68k: Add missing RCU idle APIs on idle loop commit 5b57ba37e82a15f345a6a2eb8c01a2b2d94c5eeb upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the m68k's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Acked-by: Geert Uytterhoeven Cc: m68k Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/m68k/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index c488e3cfab53..ac2892e49c7c 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -75,8 +76,10 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) idle(); + rcu_idle_exit(); schedule_preempt_disabled(); } } -- GitLab From 3b30d3182fbf026578fbad09877d78c338562f4c Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0718/1799] alpha: Add missing RCU idle APIs on idle loop commit 4c94cada48f7c660eca582be6032427a5e367117 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the Alpha's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Tested-by: Michael Cree Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Cc: alpha Cc: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/alpha/kernel/process.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 153d3fce3e8e..8e3d91be76b0 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -54,8 +55,11 @@ cpu_idle(void) /* FIXME -- EV6 and LCA45 know how to power down the CPU. */ + rcu_idle_enter(); while (!need_resched()) cpu_relax(); + + rcu_idle_exit(); schedule(); } } -- GitLab From a3e9082a19d723e7be0bc51d851b5689eee67c9c Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0719/1799] cris: Add missing RCU idle APIs on idle loop commit c633f9e788928e91ad11f44df29b47bbbe9550b0 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the Cris's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: Mikael Starvik Cc: Jesper Nilsson Cc: Cris Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/cris/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c index 891dad85e8bd..c722027d69ad 100644 --- a/arch/cris/kernel/process.c +++ b/arch/cris/kernel/process.c @@ -25,6 +25,7 @@ #include #include #include +#include //#define DEBUG @@ -102,6 +103,7 @@ void cpu_idle (void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) { void (*idle)(void); /* @@ -114,6 +116,7 @@ void cpu_idle (void) idle = default_idle; idle(); } + rcu_idle_exit(); schedule_preempt_disabled(); } } -- GitLab From 1b5124a305593deffd6186540546b8bfba429570 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0720/1799] m32r: Add missing RCU idle APIs on idle loop commit 48ae077cfce72591b8fc80e1dcc87806f86fed7f upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in the m32r's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: Hirokazu Takata Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/m32r/kernel/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index 3a4a32b27208..384e63f3a4c4 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -82,6 +83,7 @@ void cpu_idle (void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) { void (*idle)(void) = pm_idle; @@ -90,6 +92,7 @@ void cpu_idle (void) idle(); } + rcu_idle_exit(); schedule_preempt_disabled(); } } -- GitLab From 4a94001bd83f18ff3f3b998899d250d96f60a503 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 22 Aug 2012 17:27:34 +0200 Subject: [PATCH 0721/1799] score: Add missing RCU idle APIs on idle loop commit 0ee23fda59740767324b4340247ca41a2f498ca6 upstream. In the old times, the whole idle task was considered as an RCU quiescent state. But as RCU became more and more successful overtime, some RCU read side critical section have been added even in the code of some architectures idle tasks, for tracing for example. So nowadays, rcu_idle_enter() and rcu_idle_exit() must be called by the architecture to tell RCU about the part in the idle loop that doesn't make use of rcu read side critical sections, typically the part that puts the CPU in low power mode. This is necessary for RCU to find the quiescent states in idle in order to complete grace periods. Add this missing pair of calls in scores's idle loop. Reported-by: Paul E. McKenney Signed-off-by: Frederic Weisbecker Cc: Chen Liqin Cc: Lennox Wu Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- arch/score/kernel/process.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c index 2707023c7563..637970cfd3f4 100644 --- a/arch/score/kernel/process.c +++ b/arch/score/kernel/process.c @@ -27,6 +27,7 @@ #include #include #include +#include void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); @@ -50,9 +51,10 @@ void __noreturn cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) barrier(); - + rcu_idle_exit(); schedule_preempt_disabled(); } } -- GitLab From f5260a7c89bf5146c0d52b036ac58eb192537a84 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sat, 22 Sep 2012 13:55:30 -0700 Subject: [PATCH 0722/1799] rcu: Fix day-one dyntick-idle stall-warning bug commit a10d206ef1a83121ab7430cb196e0376a7145b22 upstream. Each grace period is supposed to have at least one callback waiting for that grace period to complete. However, if CONFIG_NO_HZ=n, an extra callback-free grace period is no big problem -- it will chew up a tiny bit of CPU time, but it will complete normally. In contrast, CONFIG_NO_HZ=y kernels have the potential for all the CPUs to go to sleep indefinitely, in turn indefinitely delaying completion of the callback-free grace period. Given that nothing is waiting on this grace period, this is also not a problem. That is, unless RCU CPU stall warnings are also enabled, as they are in recent kernels. In this case, if a CPU wakes up after at least one minute of inactivity, an RCU CPU stall warning will result. The reason that no one noticed until quite recently is that most systems have enough OS noise that they will never remain absolutely idle for a full minute. But there are some embedded systems with cut-down userspace configurations that consistently get into this situation. All this begs the question of exactly how a callback-free grace period gets started in the first place. This can happen due to the fact that CPUs do not necessarily agree on which grace period is in progress. If a CPU still believes that the grace period that just completed is still ongoing, it will believe that it has callbacks that need to wait for another grace period, never mind the fact that the grace period that they were waiting for just completed. This CPU can therefore erroneously decide to start a new grace period. Note that this can happen in TREE_RCU and TREE_PREEMPT_RCU even on a single-CPU system: Deadlock considerations mean that the CPU that detected the end of the grace period is not necessarily officially informed of this fact for some time. Once this CPU notices that the earlier grace period completed, it will invoke its callbacks. It then won't have any callbacks left. If no other CPU has any callbacks, we now have a callback-free grace period. This commit therefore makes CPUs check more carefully before starting a new grace period. This new check relies on an array of tail pointers into each CPU's list of callbacks. If the CPU is up to date on which grace periods have completed, it checks to see if any callbacks follow the RCU_DONE_TAIL segment, otherwise it checks to see if any callbacks follow the RCU_WAIT_TAIL segment. The reason that this works is that the RCU_WAIT_TAIL segment will be promoted to the RCU_DONE_TAIL segment as soon as the CPU is officially notified that the old grace period has ended. This change is to cpu_needs_another_gp(), which is called in a number of places. The only one that really matters is in rcu_start_gp(), where the root rcu_node structure's ->lock is held, which prevents any other CPU from starting or completing a grace period, so that the comparison that determines whether the CPU is missing the completion of a grace period is stable. Reported-by: Becky Bruce Reported-by: Subodh Nijsure Reported-by: Paul Walmsley Signed-off-by: Paul E. McKenney Signed-off-by: Paul E. McKenney Tested-by: Paul Walmsley Signed-off-by: Greg Kroah-Hartman --- kernel/rcutree.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index d0c5baf1ab18..4eec66e0350d 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -295,7 +295,9 @@ cpu_has_callbacks_ready_to_invoke(struct rcu_data *rdp) static int cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp) { - return *rdp->nxttail[RCU_DONE_TAIL] && !rcu_gp_in_progress(rsp); + return *rdp->nxttail[RCU_DONE_TAIL + + ACCESS_ONCE(rsp->completed) != rdp->completed] && + !rcu_gp_in_progress(rsp); } /* -- GitLab From 34ffca41fc0a205bb00382be7bbefbf2fc63436d Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 6 Oct 2012 11:19:52 +0200 Subject: [PATCH 0723/1799] r8169: Config1 is read-only on 8168c and later. commit 851e60221926a53344b4227879858bef841b0477 upstream. Suggested by Hayes. Signed-off-by: Francois Romieu Cc: Hayes Wang Acked-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/realtek/r8169.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 5fb74c4298fa..adf496d0ce48 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1400,7 +1400,6 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) u16 reg; u8 mask; } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, { WAKE_PHY, Config3, LinkUp }, { WAKE_MAGIC, Config3, MagicPacket }, { WAKE_UCAST, Config5, UWF }, @@ -1408,16 +1407,28 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) { WAKE_MCAST, Config5, MWF }, { WAKE_ANY, Config5, LanWake } }; + u8 options; RTL_W8(Cfg9346, Cfg9346_Unlock); for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; + options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; if (wolopts & cfg[i].opt) options |= cfg[i].mask; RTL_W8(cfg[i].reg, options); } + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17: + options = RTL_R8(Config1) & ~PMEnable; + if (wolopts) + options |= PMEnable; + RTL_W8(Config1, options); + break; + default: + break; + } + RTL_W8(Cfg9346, Cfg9346_Lock); } -- GitLab From 160f00fefef1e5b72be0745236d2b65d14b99ed4 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 6 Oct 2012 11:19:53 +0200 Subject: [PATCH 0724/1799] r8169: 8168c and later require bit 0x20 to be set in Config2 for PME signaling. commit d387b427c973974dd619a33549c070ac5d0e089f upstream. The new 84xx stopped flying below the radars. Signed-off-by: Francois Romieu Cc: Hayes Wang Acked-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/realtek/r8169.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index adf496d0ce48..482dcd3a7ad0 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -319,6 +319,8 @@ enum rtl_registers { Config0 = 0x51, Config1 = 0x52, Config2 = 0x53, +#define PME_SIGNAL (1 << 5) /* 8168c and later */ + Config3 = 0x54, Config4 = 0x55, Config5 = 0x56, @@ -1426,6 +1428,10 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) RTL_W8(Config1, options); break; default: + options = RTL_R8(Config2) & ~PME_SIGNAL; + if (wolopts) + options |= PME_SIGNAL; + RTL_W8(Config2, options); break; } -- GitLab From 14cfd9f986d521f3f97139fa2ae5db67886059d1 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Mon, 8 Oct 2012 16:29:14 -0700 Subject: [PATCH 0725/1799] revert "mm: mempolicy: Let vma_merge and vma_split handle vma->vm_policy linkages" commit 8d34694c1abf29df1f3c7317936b7e3e2e308d9b upstream. Commit 05f144a0d5c2 ("mm: mempolicy: Let vma_merge and vma_split handle vma->vm_policy linkages") removed vma->vm_policy updates code but it is the purpose of mbind_range(). Now, mbind_range() is virtually a no-op and while it does not allow memory corruption it is not the right fix. This patch is a revert. [mgorman@suse.de: Edited changelog] Signed-off-by: KOSAKI Motohiro Signed-off-by: Mel Gorman Cc: Christoph Lameter Cc: Josh Boyer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mempolicy.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 9afcbad632ec..ed3cc1bea49b 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -607,6 +607,27 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end, return first; } +/* Apply policy to a single VMA */ +static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new) +{ + int err = 0; + struct mempolicy *old = vma->vm_policy; + + pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n", + vma->vm_start, vma->vm_end, vma->vm_pgoff, + vma->vm_ops, vma->vm_file, + vma->vm_ops ? vma->vm_ops->set_policy : NULL); + + if (vma->vm_ops && vma->vm_ops->set_policy) + err = vma->vm_ops->set_policy(vma, new); + if (!err) { + mpol_get(new); + vma->vm_policy = new; + mpol_put(old); + } + return err; +} + /* Step 2: apply policy to a range and do splits. */ static int mbind_range(struct mm_struct *mm, unsigned long start, unsigned long end, struct mempolicy *new_pol) @@ -655,23 +676,9 @@ static int mbind_range(struct mm_struct *mm, unsigned long start, if (err) goto out; } - - /* - * Apply policy to a single VMA. The reference counting of - * policy for vma_policy linkages has already been handled by - * vma_merge and split_vma as necessary. If this is a shared - * policy then ->set_policy will increment the reference count - * for an sp node. - */ - pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n", - vma->vm_start, vma->vm_end, vma->vm_pgoff, - vma->vm_ops, vma->vm_file, - vma->vm_ops ? vma->vm_ops->set_policy : NULL); - if (vma->vm_ops && vma->vm_ops->set_policy) { - err = vma->vm_ops->set_policy(vma, new_pol); - if (err) - goto out; - } + err = policy_vma(vma, new_pol); + if (err) + goto out; } out: -- GitLab From 33efe2910bf7865a7d1fba4b06c9fa4b6fda6856 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Mon, 8 Oct 2012 16:29:16 -0700 Subject: [PATCH 0726/1799] mempolicy: remove mempolicy sharing commit 869833f2c5c6e4dd09a5378cfc665ffb4615e5d2 upstream. Dave Jones' system call fuzz testing tool "trinity" triggered the following bug error with slab debugging enabled ============================================================================= BUG numa_policy (Not tainted): Poison overwritten ----------------------------------------------------------------------------- INFO: 0xffff880146498250-0xffff880146498250. First byte 0x6a instead of 0x6b INFO: Allocated in mpol_new+0xa3/0x140 age=46310 cpu=6 pid=32154 __slab_alloc+0x3d3/0x445 kmem_cache_alloc+0x29d/0x2b0 mpol_new+0xa3/0x140 sys_mbind+0x142/0x620 system_call_fastpath+0x16/0x1b INFO: Freed in __mpol_put+0x27/0x30 age=46268 cpu=6 pid=32154 __slab_free+0x2e/0x1de kmem_cache_free+0x25a/0x260 __mpol_put+0x27/0x30 remove_vma+0x68/0x90 exit_mmap+0x118/0x140 mmput+0x73/0x110 exit_mm+0x108/0x130 do_exit+0x162/0xb90 do_group_exit+0x4f/0xc0 sys_exit_group+0x17/0x20 system_call_fastpath+0x16/0x1b INFO: Slab 0xffffea0005192600 objects=27 used=27 fp=0x (null) flags=0x20000000004080 INFO: Object 0xffff880146498250 @offset=592 fp=0xffff88014649b9d0 The problem is that the structure is being prematurely freed due to a reference count imbalance. In the following case mbind(addr, len) should replace the memory policies of both vma1 and vma2 and thus they will become to share the same mempolicy and the new mempolicy will have the MPOL_F_SHARED flag. +-------------------+-------------------+ | vma1 | vma2(shmem) | +-------------------+-------------------+ | | addr addr+len alloc_pages_vma() uses get_vma_policy() and mpol_cond_put() pair for maintaining the mempolicy reference count. The current rule is that get_vma_policy() only increments refcount for shmem VMA and mpol_conf_put() only decrements refcount if the policy has MPOL_F_SHARED. In above case, vma1 is not shmem vma and vma->policy has MPOL_F_SHARED! The reference count will be decreased even though was not increased whenever alloc_page_vma() is called. This has been broken since commit [52cd3b07: mempolicy: rework mempolicy Reference Counting] in 2008. There is another serious bug with the sharing of memory policies. Currently, mempolicy rebind logic (it is called from cpuset rebinding) ignores a refcount of mempolicy and override it forcibly. Thus, any mempolicy sharing may cause mempolicy corruption. The bug was introduced by commit [68860ec1: cpusets: automatic numa mempolicy rebinding]. Ideally, the shared policy handling would be rewritten to either properly handle COW of the policy structures or at least reference count MPOL_F_SHARED based exclusively on information within the policy. However, this patch takes the easier approach of disabling any policy sharing between VMAs. Each new range allocated with sp_alloc will allocate a new policy, set the reference count to 1 and drop the reference count of the old policy. This increases the memory footprint but is not expected to be a major problem as mbind() is unlikely to be used for fine-grained ranges. It is also inefficient because it means we allocate a new policy even in cases where mbind_range() could use the new_policy passed to it. However, it is more straight-forward and the change should be invisible to the user. [mgorman@suse.de: Edited changelog] Reported-by: Dave Jones Cc: Christoph Lameter Reviewed-by: Christoph Lameter Signed-off-by: KOSAKI Motohiro Signed-off-by: Mel Gorman Cc: Josh Boyer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mempolicy.c | 52 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index ed3cc1bea49b..c2efa3ddf62b 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -607,24 +607,39 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end, return first; } -/* Apply policy to a single VMA */ -static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new) +/* + * Apply policy to a single VMA + * This must be called with the mmap_sem held for writing. + */ +static int vma_replace_policy(struct vm_area_struct *vma, + struct mempolicy *pol) { - int err = 0; - struct mempolicy *old = vma->vm_policy; + int err; + struct mempolicy *old; + struct mempolicy *new; pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n", vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_ops, vma->vm_file, vma->vm_ops ? vma->vm_ops->set_policy : NULL); - if (vma->vm_ops && vma->vm_ops->set_policy) + new = mpol_dup(pol); + if (IS_ERR(new)) + return PTR_ERR(new); + + if (vma->vm_ops && vma->vm_ops->set_policy) { err = vma->vm_ops->set_policy(vma, new); - if (!err) { - mpol_get(new); - vma->vm_policy = new; - mpol_put(old); + if (err) + goto err_out; } + + old = vma->vm_policy; + vma->vm_policy = new; /* protected by mmap_sem */ + mpol_put(old); + + return 0; + err_out: + mpol_put(new); return err; } @@ -676,7 +691,7 @@ static int mbind_range(struct mm_struct *mm, unsigned long start, if (err) goto out; } - err = policy_vma(vma, new_pol); + err = vma_replace_policy(vma, new_pol); if (err) goto out; } @@ -2127,15 +2142,24 @@ static void sp_delete(struct shared_policy *sp, struct sp_node *n) static struct sp_node *sp_alloc(unsigned long start, unsigned long end, struct mempolicy *pol) { - struct sp_node *n = kmem_cache_alloc(sn_cache, GFP_KERNEL); + struct sp_node *n; + struct mempolicy *newpol; + n = kmem_cache_alloc(sn_cache, GFP_KERNEL); if (!n) return NULL; + + newpol = mpol_dup(pol); + if (IS_ERR(newpol)) { + kmem_cache_free(sn_cache, n); + return NULL; + } + newpol->flags |= MPOL_F_SHARED; + n->start = start; n->end = end; - mpol_get(pol); - pol->flags |= MPOL_F_SHARED; /* for unref */ - n->policy = pol; + n->policy = newpol; + return n; } -- GitLab From 04a30bd9dccbeee2cc6b035e42a37e9be0fa8c6c Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 8 Oct 2012 16:29:17 -0700 Subject: [PATCH 0727/1799] mempolicy: fix a race in shared_policy_replace() commit b22d127a39ddd10d93deee3d96e643657ad53a49 upstream. shared_policy_replace() use of sp_alloc() is unsafe. 1) sp_node cannot be dereferenced if sp->lock is not held and 2) another thread can modify sp_node between spin_unlock for allocating a new sp node and next spin_lock. The bug was introduced before 2.6.12-rc2. Kosaki's original patch for this problem was to allocate an sp node and policy within shared_policy_replace and initialise it when the lock is reacquired. I was not keen on this approach because it partially duplicates sp_alloc(). As the paths were sp->lock is taken are not that performance critical this patch converts sp->lock to sp->mutex so it can sleep when calling sp_alloc(). [kosaki.motohiro@jp.fujitsu.com: Original patch] Signed-off-by: Mel Gorman Acked-by: KOSAKI Motohiro Reviewed-by: Christoph Lameter Cc: Josh Boyer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/mempolicy.h | 2 +- mm/mempolicy.c | 37 ++++++++++++++++--------------------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 7c727a90d70d..0abf1d436b12 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -188,7 +188,7 @@ struct sp_node { struct shared_policy { struct rb_root root; - spinlock_t lock; + struct mutex mutex; }; void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol); diff --git a/mm/mempolicy.c b/mm/mempolicy.c index c2efa3ddf62b..30850253c06c 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2057,7 +2057,7 @@ bool __mpol_equal(struct mempolicy *a, struct mempolicy *b) */ /* lookup first element intersecting start-end */ -/* Caller holds sp->lock */ +/* Caller holds sp->mutex */ static struct sp_node * sp_lookup(struct shared_policy *sp, unsigned long start, unsigned long end) { @@ -2121,13 +2121,13 @@ mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx) if (!sp->root.rb_node) return NULL; - spin_lock(&sp->lock); + mutex_lock(&sp->mutex); sn = sp_lookup(sp, idx, idx+1); if (sn) { mpol_get(sn->policy); pol = sn->policy; } - spin_unlock(&sp->lock); + mutex_unlock(&sp->mutex); return pol; } @@ -2167,10 +2167,10 @@ static struct sp_node *sp_alloc(unsigned long start, unsigned long end, static int shared_policy_replace(struct shared_policy *sp, unsigned long start, unsigned long end, struct sp_node *new) { - struct sp_node *n, *new2 = NULL; + struct sp_node *n; + int ret = 0; -restart: - spin_lock(&sp->lock); + mutex_lock(&sp->mutex); n = sp_lookup(sp, start, end); /* Take care of old policies in the same range. */ while (n && n->start < end) { @@ -2183,16 +2183,14 @@ static int shared_policy_replace(struct shared_policy *sp, unsigned long start, } else { /* Old policy spanning whole new range. */ if (n->end > end) { + struct sp_node *new2; + new2 = sp_alloc(end, n->end, n->policy); if (!new2) { - spin_unlock(&sp->lock); - new2 = sp_alloc(end, n->end, n->policy); - if (!new2) - return -ENOMEM; - goto restart; + ret = -ENOMEM; + goto out; } n->end = start; sp_insert(sp, new2); - new2 = NULL; break; } else n->end = start; @@ -2203,12 +2201,9 @@ static int shared_policy_replace(struct shared_policy *sp, unsigned long start, } if (new) sp_insert(sp, new); - spin_unlock(&sp->lock); - if (new2) { - mpol_put(new2->policy); - kmem_cache_free(sn_cache, new2); - } - return 0; +out: + mutex_unlock(&sp->mutex); + return ret; } /** @@ -2226,7 +2221,7 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol) int ret; sp->root = RB_ROOT; /* empty tree == default mempolicy */ - spin_lock_init(&sp->lock); + mutex_init(&sp->mutex); if (mpol) { struct vm_area_struct pvma; @@ -2292,7 +2287,7 @@ void mpol_free_shared_policy(struct shared_policy *p) if (!p->root.rb_node) return; - spin_lock(&p->lock); + mutex_lock(&p->mutex); next = rb_first(&p->root); while (next) { n = rb_entry(next, struct sp_node, nd); @@ -2301,7 +2296,7 @@ void mpol_free_shared_policy(struct shared_policy *p) mpol_put(n->policy); kmem_cache_free(sn_cache, n); } - spin_unlock(&p->lock); + mutex_unlock(&p->mutex); } /* assumes fs == KERNEL_DS */ -- GitLab From 04ea8a8388992ad12bc1b32cc16f4220300ea167 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Mon, 8 Oct 2012 16:29:19 -0700 Subject: [PATCH 0728/1799] mempolicy: fix refcount leak in mpol_set_shared_policy() commit 63f74ca21f1fad36d075e063f06dcc6d39fe86b2 upstream. When shared_policy_replace() fails to allocate new->policy is not freed correctly by mpol_set_shared_policy(). The problem is that shared mempolicy code directly call kmem_cache_free() in multiple places where it is easy to make a mistake. This patch creates an sp_free wrapper function and uses it. The bug was introduced pre-git age (IOW, before 2.6.12-rc2). [mgorman@suse.de: Editted changelog] Signed-off-by: KOSAKI Motohiro Signed-off-by: Mel Gorman Reviewed-by: Christoph Lameter Cc: Josh Boyer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mempolicy.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 30850253c06c..06531fc365e5 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2131,12 +2131,17 @@ mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx) return pol; } +static void sp_free(struct sp_node *n) +{ + mpol_put(n->policy); + kmem_cache_free(sn_cache, n); +} + static void sp_delete(struct shared_policy *sp, struct sp_node *n) { pr_debug("deleting %lx-l%lx\n", n->start, n->end); rb_erase(&n->nd, &sp->root); - mpol_put(n->policy); - kmem_cache_free(sn_cache, n); + sp_free(n); } static struct sp_node *sp_alloc(unsigned long start, unsigned long end, @@ -2275,7 +2280,7 @@ int mpol_set_shared_policy(struct shared_policy *info, } err = shared_policy_replace(info, vma->vm_pgoff, vma->vm_pgoff+sz, new); if (err && new) - kmem_cache_free(sn_cache, new); + sp_free(new); return err; } @@ -2292,9 +2297,7 @@ void mpol_free_shared_policy(struct shared_policy *p) while (next) { n = rb_entry(next, struct sp_node, nd); next = rb_next(&n->nd); - rb_erase(&n->nd, &p->root); - mpol_put(n->policy); - kmem_cache_free(sn_cache, n); + sp_delete(p, n); } mutex_unlock(&p->mutex); } -- GitLab From d9302b128e4640df707c99335b3f3ad0e13d0148 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 8 Oct 2012 16:29:20 -0700 Subject: [PATCH 0729/1799] mempolicy: fix a memory corruption by refcount imbalance in alloc_pages_vma() commit 00442ad04a5eac08a98255697c510e708f6082e2 upstream. Commit cc9a6c877661 ("cpuset: mm: reduce large amounts of memory barrier related damage v3") introduced a potential memory corruption. shmem_alloc_page() uses a pseudo vma and it has one significant unique combination, vma->vm_ops=NULL and vma->policy->flags & MPOL_F_SHARED. get_vma_policy() does NOT increase a policy ref when vma->vm_ops=NULL and mpol_cond_put() DOES decrease a policy ref when a policy has MPOL_F_SHARED. Therefore, when a cpuset update race occurs, alloc_pages_vma() falls in 'goto retry_cpuset' path, decrements the reference count and frees the policy prematurely. Signed-off-by: KOSAKI Motohiro Signed-off-by: Mel Gorman Reviewed-by: Christoph Lameter Cc: Josh Boyer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mempolicy.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 06531fc365e5..d1e4beffbe1f 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1532,8 +1532,18 @@ struct mempolicy *get_vma_policy(struct task_struct *task, addr); if (vpol) pol = vpol; - } else if (vma->vm_policy) + } else if (vma->vm_policy) { pol = vma->vm_policy; + + /* + * shmem_alloc_page() passes MPOL_F_SHARED policy with + * a pseudo vma whose vma->vm_ops=NULL. Take a reference + * count on these policies which will be dropped by + * mpol_cond_put() later + */ + if (mpol_needs_cond_ref(pol)) + mpol_get(pol); + } } if (!pol) pol = &default_policy; -- GitLab From b4bec66863ab1c55ccc1a9b01988b8b6b5abac87 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 26 Jul 2012 18:00:00 -0400 Subject: [PATCH 0730/1799] efi: Build EFI stub with EFI-appropriate options commit 9dead5bbb825d7c25c0400e61de83075046322d0 upstream. We can't assume the presence of the red zone while we're still in a boot services environment, so we should build with -fno-red-zone to avoid problems. Change the size of wchar at the same time to make string handling simpler. Signed-off-by: Matthew Garrett Signed-off-by: Matt Fleming Acked-by: Josh Boyer Signed-off-by: Greg Kroah-Hartman --- arch/x86/boot/compressed/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index e398bb5d63bb..8a84501acb1b 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -28,6 +28,9 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ $(obj)/piggy.o +$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone +$(obj)/efi_stub_$(BITS).o: KBUILD_CLFAGS += -fshort-wchar -mno-red-zone + ifeq ($(CONFIG_EFI_STUB), y) VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o endif -- GitLab From 0c9673834740afdfa7c172b1b19c6b3ec5bc3907 Mon Sep 17 00:00:00 2001 From: Seiji Aguchi Date: Tue, 24 Jul 2012 13:27:23 +0000 Subject: [PATCH 0731/1799] efi: initialize efi.runtime_version to make query_variable_info/update_capsule workable commit d6cf86d8f23253225fe2a763d627ecf7dfee9dae upstream. A value of efi.runtime_version is checked before calling update_capsule()/query_variable_info() as follows. But it isn't initialized anywhere. static efi_status_t virt_efi_query_variable_info(u32 attr, u64 *storage_space, u64 *remaining_space, u64 *max_variable_size) { if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) return EFI_UNSUPPORTED; This patch initializes a value of efi.runtime_version at boot time. Signed-off-by: Seiji Aguchi Acked-by: Matthew Garrett Signed-off-by: Matt Fleming Signed-off-by: Ivan Hu Signed-off-by: Greg Kroah-Hartman --- arch/x86/platform/efi/efi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 92660edaa1e7..f55a4ce6dc49 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -890,6 +890,7 @@ void __init efi_enter_virtual_mode(void) * * Call EFI services through wrapper functions. */ + efi.runtime_version = efi_systab.fw_revision; efi.get_time = virt_efi_get_time; efi.set_time = virt_efi_set_time; efi.get_wakeup_time = virt_efi_get_wakeup_time; -- GitLab From c62f9945efea31db203fd4fb77e830ddffdcabf6 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Thu, 24 May 2012 19:46:26 +0530 Subject: [PATCH 0732/1799] CPU hotplug, cpusets, suspend: Don't modify cpusets during suspend/resume commit d35be8bab9b0ce44bed4b9453f86ebf64062721e upstream. In the event of CPU hotplug, the kernel modifies the cpusets' cpus_allowed masks as and when necessary to ensure that the tasks belonging to the cpusets have some place (online CPUs) to run on. And regular CPU hotplug is destructive in the sense that the kernel doesn't remember the original cpuset configurations set by the user, across hotplug operations. However, suspend/resume (which uses CPU hotplug) is a special case in which the kernel has the responsibility to restore the system (during resume), to exactly the same state it was in before suspend. In order to achieve that, do the following: 1. Don't modify cpusets during suspend/resume. At all. In particular, don't move the tasks from one cpuset to another, and don't modify any cpuset's cpus_allowed mask. So, simply ignore cpusets during the CPU hotplug operations that are carried out in the suspend/resume path. 2. However, cpusets and sched domains are related. We just want to avoid altering cpusets alone. So, to keep the sched domains updated, build a single sched domain (containing all active cpus) during each of the CPU hotplug operations carried out in s/r path, effectively ignoring the cpusets' cpus_allowed masks. (Since userspace is frozen while doing all this, it will go unnoticed.) 3. During the last CPU online operation during resume, build the sched domains by looking up the (unaltered) cpusets' cpus_allowed masks. That will bring back the system to the same original state as it was in before suspend. Ultimately, this will not only solve the cpuset problem related to suspend resume (ie., restores the cpusets to exactly what it was before suspend, by not touching it at all) but also speeds up suspend/resume because we avoid running cpuset update code for every CPU being offlined/onlined. Signed-off-by: Srivatsa S. Bhat Signed-off-by: Peter Zijlstra Cc: Linus Torvalds Cc: Andrew Morton Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20120524141611.3692.20155.stgit@srivatsabhat.in.ibm.com Signed-off-by: Ingo Molnar Signed-off-by: Preeti U Murthy Signed-off-by: Greg Kroah-Hartman --- kernel/cpuset.c | 3 +++ kernel/sched/core.c | 40 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 14f7070b4ba2..5fc1570e64c1 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2065,6 +2065,9 @@ static void scan_for_empty_cpusets(struct cpuset *root) * (of no affect) on systems that are actively using CPU hotplug * but making no active use of cpusets. * + * The only exception to this is suspend/resume, where we don't + * modify cpusets at all. + * * This routine ensures that top_cpuset.cpus_allowed tracks * cpu_active_mask on each CPU hotplug (cpuhp) event. * diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 593087b2baf0..1d22981cd431 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -6937,34 +6937,66 @@ int __init sched_create_sysfs_power_savings_entries(struct device *dev) } #endif /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */ +static int num_cpus_frozen; /* used to mark begin/end of suspend/resume */ + /* * Update cpusets according to cpu_active mask. If cpusets are * disabled, cpuset_update_active_cpus() becomes a simple wrapper * around partition_sched_domains(). + * + * If we come here as part of a suspend/resume, don't touch cpusets because we + * want to restore it back to its original state upon resume anyway. */ static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action, void *hcpu) { - switch (action & ~CPU_TASKS_FROZEN) { + switch (action) { + case CPU_ONLINE_FROZEN: + case CPU_DOWN_FAILED_FROZEN: + + /* + * num_cpus_frozen tracks how many CPUs are involved in suspend + * resume sequence. As long as this is not the last online + * operation in the resume sequence, just build a single sched + * domain, ignoring cpusets. + */ + num_cpus_frozen--; + if (likely(num_cpus_frozen)) { + partition_sched_domains(1, NULL, NULL); + break; + } + + /* + * This is the last CPU online operation. So fall through and + * restore the original sched domains by considering the + * cpuset configurations. + */ + case CPU_ONLINE: case CPU_DOWN_FAILED: cpuset_update_active_cpus(); - return NOTIFY_OK; + break; default: return NOTIFY_DONE; } + return NOTIFY_OK; } static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action, void *hcpu) { - switch (action & ~CPU_TASKS_FROZEN) { + switch (action) { case CPU_DOWN_PREPARE: cpuset_update_active_cpus(); - return NOTIFY_OK; + break; + case CPU_DOWN_PREPARE_FROZEN: + num_cpus_frozen++; + partition_sched_domains(1, NULL, NULL); + break; default: return NOTIFY_DONE; } + return NOTIFY_OK; } void __init sched_init_smp(void) -- GitLab From e82df24e733c04385e8d8c32d3062292668bf8c0 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Sat, 18 Aug 2012 13:07:41 -0400 Subject: [PATCH 0733/1799] mtd: mtdpart: break it as soon as we parse out the partitions commit c51803ddba10d80d9f246066802c6e359cf1d44c upstream. We may cause a memory leak when the @types has more then one parser. Take the `default_mtd_part_types` for example. The default_mtd_part_types has two parsers now: `cmdlinepart` and `ofpart`. Assume the following case: The kernel command line sets the partitions like: #gpmi-nand:20m(boot),20m(kernel),1g(rootfs),-(user) But the devicetree file(such as arch/arm/boot/dts/imx28-evk.dts) also sets the same partitions as the kernel command line does. In the current code, the partitions parsed out by the `ofpart` will overwrite the @pparts which has already set by the `cmdlinepart` parser, and the the partitions parsed out by the `cmdlinepart` is missed. A memory leak occurs. So we should break the code as soon as we parse out the partitions, In actually, this patch makes a priority order between the parsers. If one parser has already parsed out the partitions successfully, it's no need to use another parser anymore. Signed-off-by: Huang Shijie Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/mtdpart.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 9651c06de0a9..bf24aa77175d 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -709,6 +709,8 @@ static const char *default_mtd_part_types[] = { * partition parsers, specified in @types. However, if @types is %NULL, then * the default list of parsers is used. The default list contains only the * "cmdlinepart" and "ofpart" parsers ATM. + * Note: If there are more then one parser in @types, the kernel only takes the + * partitions parsed out by the first parser. * * This function may return: * o a negative error code in case of failure @@ -733,11 +735,12 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types, if (!parser) continue; ret = (*parser->parse_fn)(master, pparts, data); + put_partition_parser(parser); if (ret > 0) { printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", ret, parser->name, master->name); + break; } - put_partition_parser(parser); } return ret; } -- GitLab From 2640a717145425d59c066e7de9350719912bd418 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Wed, 15 Aug 2012 20:28:05 +0400 Subject: [PATCH 0734/1799] mtd: autcpu12-nvram: Fix compile breakage commit d1f55c680e5d021e7066f4461dd678d42af18898 upstream. Update driver autcpu12-nvram.c so it compiles; map_read32/map_write32 no longer exist in the kernel so the driver is totally broken. Additionally, map_info name passed to simple_map_init is incorrect. Signed-off-by: Alexander Shiyan Acked-by: Arnd Bergmann Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/maps/autcpu12-nvram.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c index e5bfd0e093bb..0598d52eaf9f 100644 --- a/drivers/mtd/maps/autcpu12-nvram.c +++ b/drivers/mtd/maps/autcpu12-nvram.c @@ -43,7 +43,8 @@ struct map_info autcpu12_sram_map = { static int __init init_autcpu12_sram (void) { - int err, save0, save1; + map_word tmp, save0, save1; + int err; autcpu12_sram_map.virt = ioremap(0x12000000, SZ_128K); if (!autcpu12_sram_map.virt) { @@ -51,7 +52,7 @@ static int __init init_autcpu12_sram (void) err = -EIO; goto out; } - simple_map_init(&autcpu_sram_map); + simple_map_init(&autcpu12_sram_map); /* * Check for 32K/128K @@ -61,20 +62,22 @@ static int __init init_autcpu12_sram (void) * Read and check result on ofs 0x0 * Restore contents */ - save0 = map_read32(&autcpu12_sram_map,0); - save1 = map_read32(&autcpu12_sram_map,0x10000); - map_write32(&autcpu12_sram_map,~save0,0x10000); + save0 = map_read(&autcpu12_sram_map, 0); + save1 = map_read(&autcpu12_sram_map, 0x10000); + tmp.x[0] = ~save0.x[0]; + map_write(&autcpu12_sram_map, tmp, 0x10000); /* if we find this pattern on 0x0, we have 32K size * restore contents and exit */ - if ( map_read32(&autcpu12_sram_map,0) != save0) { - map_write32(&autcpu12_sram_map,save0,0x0); + tmp = map_read(&autcpu12_sram_map, 0); + if (!map_word_equal(&autcpu12_sram_map, tmp, save0)) { + map_write(&autcpu12_sram_map, save0, 0x0); goto map; } /* We have a 128K found, restore 0x10000 and set size * to 128K */ - map_write32(&autcpu12_sram_map,save1,0x10000); + map_write(&autcpu12_sram_map, save1, 0x10000); autcpu12_sram_map.size = SZ_128K; map: -- GitLab From 70b22c795bbe61ab4935649bb6b4135f29d164bd Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Wed, 12 Sep 2012 14:26:26 +0200 Subject: [PATCH 0735/1799] mtd: nandsim: bugfix: fail if overridesize is too big commit bb0a13a13411c4ce24c48c8ff3cdf7b48d237240 upstream. If override size is too big, the module was actually loaded instead of failing, because retval was not set. This lead to memory corruption with the use of the freed structs nandsim and nand_chip. Signed-off-by: Richard Genoud Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/nandsim.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index c606b6afd7aa..b9cbd65f49b5 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -2355,6 +2355,7 @@ static int __init ns_init_module(void) uint64_t new_size = (uint64_t)nsmtd->erasesize << overridesize; if (new_size >> overridesize != nsmtd->erasesize) { NS_ERR("overridesize is too big\n"); + retval = -EINVAL; goto err_exit; } /* N.B. This relies on nand_scan not doing anything with the size before we change it */ -- GitLab From 196f9c71e5f46965325f31532f1d55c4a809f6ff Mon Sep 17 00:00:00 2001 From: Shmulik Ladkani Date: Sun, 10 Jun 2012 13:58:12 +0300 Subject: [PATCH 0736/1799] mtd: nand: Use the mirror BBT descriptor when reading its version commit 7bb9c75436212813b38700c34df4bbb6eb82debe upstream. The code responsible for reading the version of the mirror bbt was incorrectly using the descriptor of the main bbt. Pass the mirror bbt descriptor to 'scan_read_raw' when reading the version of the mirror bbt. Signed-off-by: Shmulik Ladkani Acked-by: Sebastian Andrzej Siewior Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/nand_bbt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 30d1319ff065..c126469b0645 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -390,7 +390,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, /* Read the mirror version, if available */ if (md && (md->options & NAND_BBT_VERSION)) { scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift, - mtd->writesize, td); + mtd->writesize, md); md->version[0] = buf[bbt_get_ver_offs(mtd, md)]; pr_info("Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]); -- GitLab From 7c6313717892eabf93b53d8a112263f41646ed4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Bie=C3=9Fmann?= Date: Fri, 31 Aug 2012 13:35:41 +0200 Subject: [PATCH 0737/1799] mtd: omap2: fix omap_nand_remove segfault MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7d9b110269253b1d5858cfa57d68dfc7bf50dd77 upstream. Do not kfree() the mtd_info; it is handled in the mtd subsystem and already freed by nand_release(). Instead kfree() the struct omap_nand_info allocated in omap_nand_probe which was not freed before. This patch fixes following error when unloading the omap2 module: ---8<--- ~ $ rmmod omap2 ------------[ cut here ]------------ kernel BUG at mm/slab.c:3126! Internal error: Oops - BUG: 0 [#1] PREEMPT ARM Modules linked in: omap2(-) CPU: 0 Not tainted (3.6.0-rc3-00230-g155e36d-dirty #3) PC is at cache_free_debugcheck+0x2d4/0x36c LR is at kfree+0xc8/0x2ac pc : [] lr : [] psr: 200d0193 sp : c521fe08 ip : c0e8ef90 fp : c521fe5c r10: bf0001fc r9 : c521e000 r8 : c0d99c8c r7 : c661ebc0 r6 : c065d5a4 r5 : c65c4060 r4 : c78005c0 r3 : 00000000 r2 : 00001000 r1 : c65c4000 r0 : 00000001 Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: 86694019 DAC: 00000015 Process rmmod (pid: 549, stack limit = 0xc521e2f0) Stack: (0xc521fe08 to 0xc5220000) fe00: c008a874 c00bf44c c515c6d0 200d0193 c65c4860 c515c240 fe20: c521fe3c c521fe30 c008a9c0 c008a854 c521fe5c c65c4860 c78005c0 bf0001fc fe40: c780ff40 a00d0113 c521e000 00000000 c521fe84 c521fe60 c0112efc c01122d8 fe60: c65c4860 c0673778 c06737ac 00000000 00070013 00000000 c521fe9c c521fe88 fe80: bf0001fc c0112e40 c0673778 bf001ca8 c521feac c521fea0 c02ca11c bf0001ac fea0: c521fec4 c521feb0 c02c82c4 c02ca100 c0673778 bf001ca8 c521fee4 c521fec8 fec0: c02c8dd8 c02c8250 00000000 bf001ca8 bf001ca8 c0804ee0 c521ff04 c521fee8 fee0: c02c804c c02c8d20 bf001924 00000000 bf001ca8 c521e000 c521ff1c c521ff08 ff00: c02c950c c02c7fbc bf001d48 00000000 c521ff2c c521ff20 c02ca3a4 c02c94b8 ff20: c521ff3c c521ff30 bf001938 c02ca394 c521ffa4 c521ff40 c009beb4 bf001930 ff40: c521ff6c 70616d6f b6fe0032 c0014f84 70616d6f b6fe0032 00000081 60070010 ff60: c521ff84 c521ff70 c008e1f4 c00bf328 0001a004 70616d6f c521ff94 0021ff88 ff80: c008e368 0001a004 70616d6f b6fe0032 00000081 c0015028 00000000 c521ffa8 ffa0: c0014dc0 c009bcd0 0001a004 70616d6f bec2ab38 00000880 bec2ab38 00000880 ffc0: 0001a004 70616d6f b6fe0032 00000081 00000319 00000000 b6fe1000 00000000 ffe0: bec2ab30 bec2ab20 00019f00 b6f539c0 60070010 bec2ab38 aaaaaaaa aaaaaaaa Backtrace: [] (cache_free_debugcheck+0x0/0x36c) from [] (kfree+0xc8/0x2ac) [] (kfree+0x0/0x2ac) from [] (omap_nand_remove+0x5c/0x64 [omap2]) [] (omap_nand_remove+0x0/0x64 [omap2]) from [] (platform_drv_remove+0x28/0x2c) r5:bf001ca8 r4:c0673778 [] (platform_drv_remove+0x0/0x2c) from [] (__device_release_driver+0x80/0xdc) [] (__device_release_driver+0x0/0xdc) from [] (driver_detach+0xc4/0xc8) r5:bf001ca8 r4:c0673778 [] (driver_detach+0x0/0xc8) from [] (bus_remove_driver+0x9c/0x104) r6:c0804ee0 r5:bf001ca8 r4:bf001ca8 r3:00000000 [] (bus_remove_driver+0x0/0x104) from [] (driver_unregister+0x60/0x80) r6:c521e000 r5:bf001ca8 r4:00000000 r3:bf001924 [] (driver_unregister+0x0/0x80) from [] (platform_driver_unregister+0x1c/0x20) r5:00000000 r4:bf001d48 [] (platform_driver_unregister+0x0/0x20) from [] (omap_nand_driver_exit+0x14/0x1c [omap2]) [] (omap_nand_driver_exit+0x0/0x1c [omap2]) from [] (sys_delete_module+0x1f0/0x2ec) [] (sys_delete_module+0x0/0x2ec) from [] (ret_fast_syscall+0x0/0x48) r8:c0015028 r7:00000081 r6:b6fe0032 r5:70616d6f r4:0001a004 Code: e1a00005 eb0d9172 e7f001f2 e7f001f2 (e7f001f2) ---[ end trace 6a30b24d8c0cc2ee ]--- Segmentation fault --->8--- This error was introduced in 67ce04bf2746f8a1f8c2a104b313d20c63f68378 which was the first commit of this driver. Signed-off-by: Andreas Bießmann Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/omap2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index c2b0bba9d8b3..618d3475dd87 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1133,7 +1133,7 @@ static int omap_nand_remove(struct platform_device *pdev) /* Release NAND device, its internal structures and partitions */ nand_release(&info->mtd); iounmap(info->nand.IO_ADDR_R); - kfree(&info->mtd); + kfree(info); return 0; } -- GitLab From dbb28ef5cf5318b0abb95712f1cfafaa032796e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Bie=C3=9Fmann?= Date: Fri, 31 Aug 2012 13:35:42 +0200 Subject: [PATCH 0738/1799] mtd: omap2: fix module loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4d3d688da8e7016f15483e9319b41311e1db9515 upstream. Unloading the omap2 nand driver missed to release the memory region which will result in not being able to request it again if one want to load the driver later on. This patch fixes following error when loading omap2 module after unloading: ---8<--- ~ $ rmmod omap2 ~ $ modprobe omap2 [ 37.420928] omap2-nand: probe of omap2-nand.0 failed with error -16 ~ $ --->8--- This error was introduced in 67ce04bf2746f8a1f8c2a104b313d20c63f68378 which was the first commit of this driver. Signed-off-by: Andreas Bießmann Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/omap2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 618d3475dd87..62d039af1023 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1133,6 +1133,7 @@ static int omap_nand_remove(struct platform_device *pdev) /* Release NAND device, its internal structures and partitions */ nand_release(&info->mtd); iounmap(info->nand.IO_ADDR_R); + release_mem_region(info->phys_base, NAND_IO_SIZE); kfree(info); return 0; } -- GitLab From 3883e2826411675a47cab6e8e8f49288c4452e34 Mon Sep 17 00:00:00 2001 From: Vaibhav Bedia Date: Thu, 13 Sep 2012 06:31:03 +0000 Subject: [PATCH 0739/1799] mmc: omap_hsmmc: Pass on the suspend failure to the PM core commit c4c8eeb4df00aabb641553d6fbcd46f458e56cd9 upstream. In some cases mmc_suspend_host() is not able to claim the host and proceed with the suspend process. The core returns -EBUSY to the host controller driver. Unfortunately, the host controller driver does not pass on this information to the PM core and hence the system suspend process continues. ret = mmc_suspend_host(host->mmc); if (ret) { host->suspended = 0; if (host->pdata->resume) { ret = host->pdata->resume(dev, host->slot_id); The return status from mmc_suspend_host() is overwritten by return status from host->pdata->resume. So the original return status is lost. In these cases the MMC core gets to an unexpected state during resume and multiple issues related to MMC crop up. 1. Host controller driver starts accessing the device registers before the clocks are enabled which leads to a prefetch abort. 2. A file copy thread which was launched before suspend gets stuck due to the host not being reclaimed during resume. To avoid such problems pass on the -EBUSY status to the PM core from the host controller driver. With this change, MMC core suspend might still fail but it does not end up making the system unusable. Suspend gets aborted and the user can try suspending the system again. Signed-off-by: Vaibhav Bedia Signed-off-by: Hebbar, Gururaja Acked-by: Venkatraman S Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/omap_hsmmc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 71a0c4ea1bc0..102537733482 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2097,8 +2097,7 @@ static int omap_hsmmc_suspend(struct device *dev) if (ret) { host->suspended = 0; if (host->pdata->resume) { - ret = host->pdata->resume(dev, host->slot_id); - if (ret) + if (host->pdata->resume(dev, host->slot_id)) dev_dbg(dev, "Unmask interrupt failed\n"); } goto err; -- GitLab From 719740d5deffe22dfdb2bbb06717c1763ebf178e Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 18 Sep 2012 06:42:42 +0000 Subject: [PATCH 0740/1799] mmc: sh-mmcif: avoid oops on spurious interrupts commit 8464dd52d3198dd05cafb005371d76e5339eb842 upstream. On some systems, e.g., kzm9g, MMCIF interfaces can produce spurious interrupts without any active request. To prevent the Oops, that results in such cases, don't dereference the mmc request pointer until we make sure, that we are indeed processing such a request. Reported-by: Tetsuyuki Kobayashi Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sh_mmcif.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 724b35e85a26..3b8236bedee5 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1191,6 +1191,10 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) host->sd_error = true; dev_dbg(&host->pd->dev, "int err state = %08x\n", state); } + if (host->state == STATE_IDLE) { + dev_info(&host->pd->dev, "Spurious IRQ status 0x%x", state); + return IRQ_HANDLED; + } if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) { if (!host->dma_active) return IRQ_WAKE_THREAD; -- GitLab From b9190164feb7046a23029eb00d0bb67f500d03b7 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 31 Aug 2012 15:01:19 -0700 Subject: [PATCH 0741/1799] JFFS2: don't fail on bitflips in OOB commit 74d83beaa229aac7d126ac1ed9414658ff1a89d2 upstream. JFFS2 was designed without thought for OOB bitflips, it seems, but they can occur and will be reported to JFFS2 via mtd_read_oob()[1]. We don't want to fail on these transactions, since the data was corrected. [1] Few drivers report bitflips for OOB-only transactions. With such drivers, this patch should have no effect. Signed-off-by: Brian Norris Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- fs/jffs2/wbuf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 74d9be19df3f..6bec5c0bc268 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -1043,10 +1043,10 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c, ops.datbuf = NULL; ret = mtd_read_oob(c->mtd, jeb->offset, &ops); - if (ret || ops.oobretlen != ops.ooblen) { + if ((ret && !mtd_is_bitflip(ret)) || ops.oobretlen != ops.ooblen) { pr_err("cannot read OOB for EB at %08x, requested %zd bytes, read %zd bytes, error %d\n", jeb->offset, ops.ooblen, ops.oobretlen, ret); - if (!ret) + if (!ret || mtd_is_bitflip(ret)) ret = -EIO; return ret; } @@ -1085,10 +1085,10 @@ int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, ops.datbuf = NULL; ret = mtd_read_oob(c->mtd, jeb->offset, &ops); - if (ret || ops.oobretlen != ops.ooblen) { + if ((ret && !mtd_is_bitflip(ret)) || ops.oobretlen != ops.ooblen) { pr_err("cannot read OOB for EB at %08x, requested %zd bytes, read %zd bytes, error %d\n", jeb->offset, ops.ooblen, ops.oobretlen, ret); - if (!ret) + if (!ret || mtd_is_bitflip(ret)) ret = -EIO; return ret; } -- GitLab From 84b7167f1ab14715edb851b17c011d645dbdd312 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 3 Oct 2012 16:02:36 -0400 Subject: [PATCH 0742/1799] cifs: reinstate the forcegid option commit 72bd481f860f0125c810bb43d878ce5f9c060c58 upstream. Apparently this was lost when we converted to the standard option parser in 8830d7e07a5e38bc47650a7554b7c1cfd49902bf Reported-by: Gregory Lee Bartholomew Cc: Sachin Prabhu Signed-off-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/connect.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 65a78e9a5d40..f771e9f98f9f 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -70,6 +70,7 @@ enum { /* Mount options that take no arguments */ Opt_user_xattr, Opt_nouser_xattr, Opt_forceuid, Opt_noforceuid, + Opt_forcegid, Opt_noforcegid, Opt_noblocksend, Opt_noautotune, Opt_hard, Opt_soft, Opt_perm, Opt_noperm, Opt_mapchars, Opt_nomapchars, Opt_sfu, @@ -121,6 +122,8 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_nouser_xattr, "nouser_xattr" }, { Opt_forceuid, "forceuid" }, { Opt_noforceuid, "noforceuid" }, + { Opt_forcegid, "forcegid" }, + { Opt_noforcegid, "noforcegid" }, { Opt_noblocksend, "noblocksend" }, { Opt_noautotune, "noautotune" }, { Opt_hard, "hard" }, @@ -1287,6 +1290,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, case Opt_noforceuid: override_uid = 0; break; + case Opt_forcegid: + override_gid = 1; + break; + case Opt_noforcegid: + override_gid = 0; + break; case Opt_noblocksend: vol->noblocksnd = 1; break; -- GitLab From a71d78897ad4b0df7239269f5772bd059a0a2541 Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Tue, 7 Aug 2012 04:33:03 -0500 Subject: [PATCH 0743/1799] Convert properly UTF-8 to UTF-16 commit fd3ba42c76d3d4b776120c2b24c1791e7bb3deb1 upstream. wchar_t is currently 16bit so converting a utf8 encoded characters not in plane 0 (>= 0x10000) to wchar_t (that is calling char2uni) lead to a -EINVAL return. This patch detect utf8 in cifs_strtoUTF16 and add special code calling utf8s_to_utf16s. Signed-off-by: Frediano Ziglio Acked-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifs_unicode.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 33ef60d8e2fb..6a8568c6466f 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -203,6 +203,27 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len, int i; wchar_t wchar_to; /* needed to quiet sparse */ + /* special case for utf8 to handle no plane0 chars */ + if (!strcmp(codepage->charset, "utf8")) { + /* + * convert utf8 -> utf16, we assume we have enough space + * as caller should have assumed conversion does not overflow + * in destination len is length in wchar_t units (16bits) + */ + i = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN, + (wchar_t *) to, len); + + /* if success terminate and exit */ + if (i >= 0) + goto success; + /* + * if fails fall back to UCS encoding as this + * function should not return negative values + * currently can fail only if source contains + * invalid encoded characters + */ + } + for (i = 0; len && *from; i++, from += charlen, len -= charlen) { charlen = codepage->char2uni(from, len, &wchar_to); if (charlen < 1) { @@ -215,6 +236,7 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len, put_unaligned_le16(wchar_to, &to[i]); } +success: put_unaligned_le16(0, &to[i]); return i; } -- GitLab From e08ea4c7d4e90aab75307c3c8018d2d4bbeebc0b Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Wed, 15 Aug 2012 00:38:08 +0200 Subject: [PATCH 0744/1799] udf: fix retun value on error path in udf_load_logicalvol commit 68766a2edcd5cd744262a70a2f67a320ac944760 upstream. In case we detect a problem and bail out, we fail to set "ret" to a nonzero value, and udf_load_logicalvol will mistakenly report success. Signed-off-by: Nikola Pajkovsky Signed-off-by: Jan Kara Cc: Herton Ronaldo Krzesinski Signed-off-by: Greg Kroah-Hartman --- fs/udf/super.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/udf/super.c b/fs/udf/super.c index e660ffdd91b6..4988a8afcc8f 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1287,6 +1287,7 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, udf_err(sb, "error loading logical volume descriptor: " "Partition table too long (%u > %lu)\n", table_len, sb->s_blocksize - sizeof(*lvd)); + ret = 1; goto out_bh; } @@ -1331,8 +1332,10 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE))) { if (udf_load_sparable_map(sb, map, - (struct sparablePartitionMap *)gpm) < 0) + (struct sparablePartitionMap *)gpm) < 0) { + ret = 1; goto out_bh; + } } else if (!strncmp(upm2->partIdent.ident, UDF_ID_METADATA, strlen(UDF_ID_METADATA))) { -- GitLab From 93875bc33f71bf7a4851b44d387743866b13b130 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Sat, 4 Aug 2012 05:44:14 +0200 Subject: [PATCH 0745/1799] sched: Fix migration thread runtime bogosity commit 8f6189684eb4e85e6c593cd710693f09c944450a upstream. Make stop scheduler class do the same accounting as other classes, Migration threads can be caught in the act while doing exec balancing, leading to the below due to use of unmaintained ->se.exec_start. The load that triggered this particular instance was an apparently out of control heavily threaded application that does system monitoring in what equated to an exec bomb, with one of the VERY frequently migrated tasks being ps. %CPU PID USER CMD 99.3 45 root [migration/10] 97.7 53 root [migration/12] 97.0 57 root [migration/13] 90.1 49 root [migration/11] 89.6 65 root [migration/15] 88.7 17 root [migration/3] 80.4 37 root [migration/8] 78.1 41 root [migration/9] 44.2 13 root [migration/2] Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1344051854.6739.19.camel@marge.simpson.net Signed-off-by: Thomas Gleixner Cc: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/sched/stop_task.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c index 7b386e86fd23..da5eb5bed84a 100644 --- a/kernel/sched/stop_task.c +++ b/kernel/sched/stop_task.c @@ -27,8 +27,10 @@ static struct task_struct *pick_next_task_stop(struct rq *rq) { struct task_struct *stop = rq->stop; - if (stop && stop->on_rq) + if (stop && stop->on_rq) { + stop->se.exec_start = rq->clock_task; return stop; + } return NULL; } @@ -52,6 +54,21 @@ static void yield_task_stop(struct rq *rq) static void put_prev_task_stop(struct rq *rq, struct task_struct *prev) { + struct task_struct *curr = rq->curr; + u64 delta_exec; + + delta_exec = rq->clock_task - curr->se.exec_start; + if (unlikely((s64)delta_exec < 0)) + delta_exec = 0; + + schedstat_set(curr->se.statistics.exec_max, + max(curr->se.statistics.exec_max, delta_exec)); + + curr->se.sum_exec_runtime += delta_exec; + account_group_exec_runtime(curr, delta_exec); + + curr->se.exec_start = rq->clock_task; + cpuacct_charge(curr, delta_exec); } static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued) @@ -60,6 +77,9 @@ static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued) static void set_curr_task_stop(struct rq *rq) { + struct task_struct *stop = rq->stop; + + stop->se.exec_start = rq->clock_task; } static void switched_to_stop(struct rq *rq, struct task_struct *p) -- GitLab From e3f681ae691bd64d1dc06bab9ad4c98ad4effa82 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Oct 2012 05:44:59 +0900 Subject: [PATCH 0746/1799] Linux 3.4.14 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 75b37ce4f1ee..d174c84cc738 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 13 +SUBLEVEL = 14 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From db0a62c4cce1011c6412648cdd9c8767206befc7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 9 Oct 2012 11:13:26 +0100 Subject: [PATCH 0747/1799] ARM: vfp: fix saving d16-d31 vfp registers on v6+ kernels commit 846a136881b8f73c1f74250bf6acfaa309cab1f2 upstream. Michael Olbrich reported that his test program fails when built with -O2 -mcpu=cortex-a8 -mfpu=neon, and a kernel which supports v6 and v7 CPUs: volatile int x = 2; volatile int64_t y = 2; int main() { volatile int a = 0; volatile int64_t b = 0; while (1) { a = (a + x) % (1 << 30); b = (b + y) % (1 << 30); assert(a == b); } } and two instances are run. When built for just v7 CPUs, this program works fine. It uses the "vadd.i64 d19, d18, d16" VFP instruction. It appears that we do not save the high-16 double VFP registers across context switches when the kernel is built for v6 CPUs. Fix that. Tested-By: Michael Olbrich Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/vfpmacros.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h index 3d5fc41ae8d3..bf5304797c76 100644 --- a/arch/arm/include/asm/vfpmacros.h +++ b/arch/arm/include/asm/vfpmacros.h @@ -28,7 +28,7 @@ ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, [\tmp, #0] tst \tmp, #HWCAP_VFPv3D16 - ldceq p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} + ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} addne \base, \base, #32*4 @ step over unused register space #else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 @@ -52,7 +52,7 @@ ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, [\tmp, #0] tst \tmp, #HWCAP_VFPv3D16 - stceq p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} + stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} addne \base, \base, #32*4 @ step over unused register space #else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 -- GitLab From 17170f0bbf4842a5a52dc61cf4d66a824fee9aaf Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 29 Aug 2012 15:21:58 -0700 Subject: [PATCH 0748/1799] nfsd4: fix nfs4 stateid leak commit cf9182e90b2af04245ac4fae497fe73fc71285b4 upstream. Processes that open and close multiple files may end up setting this oo_last_closed_stid without freeing what was previously pointed to. This can result in a major leak, visible for example by watching the nfsd4_stateids line of /proc/slabinfo. Reported-by: Cyril B. Tested-by: Cyril B. Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4state.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index e79c24e232f4..a2f99d155840 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3783,6 +3783,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); nfsd4_close_open_stateid(stp); + release_last_closed_stateid(oo); oo->oo_last_closed_stid = stp; /* place unused nfs4_stateowners on so_close_lru list to be -- GitLab From 2bb06038d0dfb47acb64de01a13a7bf963d216f4 Mon Sep 17 00:00:00 2001 From: Malahal Naineni Date: Sun, 9 Sep 2012 10:25:47 -0500 Subject: [PATCH 0749/1799] NFSD: pass null terminated buf to kstrtouint() commit 9959ba0c241a71c7ed8133401cfbbee2720da0b5 upstream. The 'buf' is prepared with null termination with intention of using it for this purpose, but 'name' is passed instead! Signed-off-by: Malahal Naineni Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4idmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 322d11ce06a4..01b090d135b7 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -581,7 +581,7 @@ numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namel /* Just to make sure it's null-terminated: */ memcpy(buf, name, namelen); buf[namelen] = '\0'; - ret = kstrtouint(name, 10, id); + ret = kstrtouint(buf, 10, id); return ret == 0; } -- GitLab From 586046257ea1a0e09a58e2d756e760102a60d6d3 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Tue, 18 Sep 2012 13:37:18 +0400 Subject: [PATCH 0750/1799] lockd: use rpc client's cl_nodename for id encoding commit 303a7ce92064c285a04c870f2dc0192fdb2968cb upstream. Taking hostname from uts namespace if not safe, because this cuold be performind during umount operation on child reaper death. And in this case current->nsproxy is NULL already. Signed-off-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/lockd/mon.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 7ef14b3c5bee..606a8dd8818c 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -40,6 +40,7 @@ struct nsm_args { u32 proc; char *mon_name; + char *nodename; }; struct nsm_res { @@ -94,6 +95,7 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, .vers = 3, .proc = NLMPROC_NSM_NOTIFY, .mon_name = nsm->sm_mon_name, + .nodename = utsname()->nodename, }; struct rpc_message msg = { .rpc_argp = &args, @@ -430,7 +432,7 @@ static void encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp) { __be32 *p; - encode_nsm_string(xdr, utsname()->nodename); + encode_nsm_string(xdr, argp->nodename); p = xdr_reserve_space(xdr, 4 + 4 + 4); *p++ = cpu_to_be32(argp->prog); *p++ = cpu_to_be32(argp->vers); -- GitLab From 11a464392c21789b03f08cfd35a3e1b21ae2eaf4 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Fri, 28 Sep 2012 15:22:00 +0800 Subject: [PATCH 0751/1799] ACPI: EC: Make the GPE storm threshold a module parameter commit a520d52e99b14ba7db135e916348f12f2a6e09be upstream. The Linux EC driver includes a mechanism to detect GPE storms, and switch from interrupt-mode to polling mode. However, polling mode sometimes doesn't work, so the workaround is problematic. Also, different systems seem to need the threshold for detecting the GPE storm at different levels. ACPI_EC_STORM_THRESHOLD was initially 20 when it's created, and was changed to 8 in 2.6.28 commit 06cf7d3c7 "ACPI: EC: lower interrupt storm threshold" to fix kernel bug 11892 by forcing the laptop in that bug to work in polling mode. However in bug 45151, it works fine in interrupt mode if we lift the threshold back to 20. This patch makes the threshold a module parameter so that user has a flexible option to debug/workaround this issue. The default is unchanged. This is also a preparation patch to fix specific systems: https://bugzilla.kernel.org/show_bug.cgi?id=45151 Signed-off-by: Feng Tang Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/ec.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7edaccce6640..615264c89c31 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -71,9 +71,6 @@ enum ec_command { #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ #define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */ -#define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts - per one transaction */ - enum { EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_GPE_STORM, /* GPE storm detected */ @@ -87,6 +84,15 @@ static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY; module_param(ec_delay, uint, 0644); MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes"); +/* + * If the number of false interrupts per one transaction exceeds + * this threshold, will think there is a GPE storm happened and + * will disable the GPE for normal transaction. + */ +static unsigned int ec_storm_threshold __read_mostly = 8; +module_param(ec_storm_threshold, uint, 0644); +MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm"); + /* If we find an EC via the ECDT, we need to keep a ptr to its context */ /* External interfaces use first EC only, so remember */ typedef int (*acpi_ec_query_func) (void *data); @@ -319,7 +325,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) msleep(1); /* It is safe to enable the GPE outside of the transaction. */ acpi_enable_gpe(NULL, ec->gpe); - } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { + } else if (t->irq_count > ec_storm_threshold) { pr_info(PREFIX "GPE storm detected, " "transactions will use polling mode\n"); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); -- GitLab From b9d5c7a86da8517506a2a8f3f9ee2ce94ffbd3e2 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Fri, 28 Sep 2012 15:22:01 +0800 Subject: [PATCH 0752/1799] ACPI: EC: Add a quirk for CLEVO M720T/M730T laptop commit 67bfa9b60bd689601554526d144b21d529f78a09 upstream. By enlarging the GPE storm threshold back to 20, that laptop's EC works fine with interrupt mode instead of polling mode. https://bugzilla.kernel.org/show_bug.cgi?id=45151 Reported-and-Tested-by: Francesco Signed-off-by: Feng Tang Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/ec.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 615264c89c31..a51df9681319 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -930,6 +930,17 @@ static int ec_flag_msi(const struct dmi_system_id *id) return 0; } +/* + * Clevo M720 notebook actually works ok with IRQ mode, if we lifted + * the GPE storm threshold back to 20 + */ +static int ec_enlarge_storm_threshold(const struct dmi_system_id *id) +{ + pr_debug("Setting the EC GPE storm threshold to 20\n"); + ec_storm_threshold = 20; + return 0; +} + static struct dmi_system_id __initdata ec_dmi_table[] = { { ec_skip_dsdt_scan, "Compal JFL92", { @@ -961,10 +972,13 @@ static struct dmi_system_id __initdata ec_dmi_table[] = { { ec_validate_ecdt, "ASUS hardware", { DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL}, + { + ec_enlarge_storm_threshold, "CLEVO hardware", { + DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."), + DMI_MATCH(DMI_PRODUCT_NAME, "M720T/M730T"),}, NULL}, {}, }; - int __init acpi_ec_ecdt_probe(void) { acpi_status status; -- GitLab From ccb6ce1dde608e368df136e7776a1d992b8c3001 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 10 Oct 2012 16:32:09 +0200 Subject: [PATCH 0753/1799] ALSA: hda - do not detect jack on internal speakers for Realtek commit f7f4b2322bf7b8c5929b7eb5a667091f32592580 upstream. This caused the internal speaker to mute itself because it was present, which happened after powersave. It was found on Dell XPS 15 (L502x), ALC665. Reported-by: Da Fox Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e7cb4bd25d22..94747f8a2493 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -602,6 +602,8 @@ static void alc_line_automute(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) + return; /* check LO jack only when it's different from HP */ if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0]) return; -- GitLab From 531db9f3addc4664300aa14af6130f160150970f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 10 Oct 2012 08:50:35 +0200 Subject: [PATCH 0754/1799] ALSA: hda - Fix memory leaks at error path in patch_cirrus.c commit c5e0b6dbad9b4d18c561af90b384d02373f1c994 upstream. The proper destructor should be called at the error path. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_cirrus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index c83ccdba1e5a..2bc6c51f58e7 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -1427,7 +1427,7 @@ static int patch_cs420x(struct hda_codec *codec) return 0; error: - kfree(codec->spec); + cs_free(codec); codec->spec = NULL; return err; } @@ -1984,7 +1984,7 @@ static int patch_cs4210(struct hda_codec *codec) return 0; error: - kfree(codec->spec); + cs_free(codec); codec->spec = NULL; return err; } @@ -2009,7 +2009,7 @@ static int patch_cs4213(struct hda_codec *codec) return 0; error: - kfree(codec->spec); + cs_free(codec); codec->spec = NULL; return err; } -- GitLab From fb2ca533f518dabf814c6aab3b7ce3c236959a68 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Fri, 10 Aug 2012 12:21:15 -0500 Subject: [PATCH 0755/1799] mips,kgdb: fix recursive page fault with CONFIG_KPROBES commit f0a996eeeda214f4293e234df33b29bec003b536 upstream. This fault was detected using the kgdb test suite on boot and it crashes recursively due to the fact that CONFIG_KPROBES on mips adds an extra die notifier in the page fault handler. The crash signature looks like this: kgdbts:RUN bad memory access test KGDB: re-enter exception: ALL breakpoints killed Call Trace: [<807b7548>] dump_stack+0x20/0x54 [<807b7548>] dump_stack+0x20/0x54 The fix for now is to have kgdb return immediately if the fault type is DIE_PAGE_FAULT and allow the kprobe code to decide what is supposed to happen. Signed-off-by: Jason Wessel Cc: Masami Hiramatsu Cc: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/mips/kernel/kgdb.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index f4546e97c60d..23817a6e32b6 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c @@ -283,6 +283,15 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd, struct pt_regs *regs = args->regs; int trap = (regs->cp0_cause & 0x7c) >> 2; +#ifdef CONFIG_KPROBES + /* + * Return immediately if the kprobes fault notifier has set + * DIE_PAGE_FAULT. + */ + if (cmd == DIE_PAGE_FAULT) + return NOTIFY_DONE; +#endif /* CONFIG_KPROBES */ + /* Userspace events, ignore. */ if (user_mode(regs)) return NOTIFY_DONE; -- GitLab From 530258fceacd8c17075906c648c1ba20928c940b Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Sun, 7 Oct 2012 20:32:51 -0700 Subject: [PATCH 0756/1799] tmpfs,ceph,gfs2,isofs,reiserfs,xfs: fix fh_len checking commit 35c2a7f4908d404c9124c2efc6ada4640ca4d5d5 upstream. Fuzzing with trinity oopsed on the 1st instruction of shmem_fh_to_dentry(), u64 inum = fid->raw[2]; which is unhelpfully reported as at the end of shmem_alloc_inode(): BUG: unable to handle kernel paging request at ffff880061cd3000 IP: [] shmem_alloc_inode+0x40/0x40 Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC Call Trace: [] ? exportfs_decode_fh+0x79/0x2d0 [] do_handle_open+0x163/0x2c0 [] sys_open_by_handle_at+0xc/0x10 [] tracesys+0xe1/0xe6 Right, tmpfs is being stupid to access fid->raw[2] before validating that fh_len includes it: the buffer kmalloc'ed by do_sys_name_to_handle() may fall at the end of a page, and the next page not be present. But some other filesystems (ceph, gfs2, isofs, reiserfs, xfs) are being careless about fh_len too, in fh_to_dentry() and/or fh_to_parent(), and could oops in the same way: add the missing fh_len checks to those. Reported-by: Sasha Levin Signed-off-by: Hugh Dickins Cc: Al Viro Cc: Sage Weil Cc: Steven Whitehouse Cc: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- fs/ceph/export.c | 18 ++++++++++++++---- fs/gfs2/export.c | 4 ++++ fs/isofs/export.c | 2 +- fs/reiserfs/inode.c | 6 +++++- fs/xfs/xfs_export.c | 3 +++ mm/shmem.c | 6 ++++-- 6 files changed, 31 insertions(+), 8 deletions(-) diff --git a/fs/ceph/export.c b/fs/ceph/export.c index fbb2a643ef10..4098ccf8cb98 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -89,7 +89,7 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len, * FIXME: we should try harder by querying the mds for the ino. */ static struct dentry *__fh_to_dentry(struct super_block *sb, - struct ceph_nfs_fh *fh) + struct ceph_nfs_fh *fh, int fh_len) { struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; struct inode *inode; @@ -97,6 +97,9 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, struct ceph_vino vino; int err; + if (fh_len < sizeof(*fh) / 4) + return ERR_PTR(-ESTALE); + dout("__fh_to_dentry %llx\n", fh->ino); vino.ino = fh->ino; vino.snap = CEPH_NOSNAP; @@ -140,7 +143,7 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, * convert connectable fh to dentry */ static struct dentry *__cfh_to_dentry(struct super_block *sb, - struct ceph_nfs_confh *cfh) + struct ceph_nfs_confh *cfh, int fh_len) { struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; struct inode *inode; @@ -148,6 +151,9 @@ static struct dentry *__cfh_to_dentry(struct super_block *sb, struct ceph_vino vino; int err; + if (fh_len < sizeof(*cfh) / 4) + return ERR_PTR(-ESTALE); + dout("__cfh_to_dentry %llx (%llx/%x)\n", cfh->ino, cfh->parent_ino, cfh->parent_name_hash); @@ -197,9 +203,11 @@ static struct dentry *ceph_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, int fh_type) { if (fh_type == 1) - return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw); + return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw, + fh_len); else - return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw); + return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw, + fh_len); } /* @@ -220,6 +228,8 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb, if (fh_type == 1) return ERR_PTR(-ESTALE); + if (fh_len < sizeof(*cfh) / 4) + return ERR_PTR(-ESTALE); pr_debug("fh_to_parent %llx/%d\n", cfh->parent_ino, cfh->parent_name_hash); diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c index 70ba891654f8..fdef7f0e28ab 100644 --- a/fs/gfs2/export.c +++ b/fs/gfs2/export.c @@ -168,6 +168,8 @@ static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid, case GFS2_SMALL_FH_SIZE: case GFS2_LARGE_FH_SIZE: case GFS2_OLD_FH_SIZE: + if (fh_len < GFS2_SMALL_FH_SIZE) + return NULL; this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32; this.no_formal_ino |= be32_to_cpu(fh[1]); this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32; @@ -187,6 +189,8 @@ static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid, switch (fh_type) { case GFS2_LARGE_FH_SIZE: case GFS2_OLD_FH_SIZE: + if (fh_len < GFS2_LARGE_FH_SIZE) + return NULL; parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; parent.no_formal_ino |= be32_to_cpu(fh[5]); parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32; diff --git a/fs/isofs/export.c b/fs/isofs/export.c index dd4687ff30d0..516eb21895c6 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c @@ -179,7 +179,7 @@ static struct dentry *isofs_fh_to_parent(struct super_block *sb, { struct isofs_fid *ifid = (struct isofs_fid *)fid; - if (fh_type != 2) + if (fh_len < 2 || fh_type != 2) return NULL; return isofs_export_iget(sb, diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 494c315c7417..f99c1b4fa5fd 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1573,8 +1573,10 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, reiserfs_warning(sb, "reiserfs-13077", "nfsd/reiserfs, fhtype=%d, len=%d - odd", fh_type, fh_len); - fh_type = 5; + fh_type = fh_len; } + if (fh_len < 2) + return NULL; return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1], (fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0); @@ -1583,6 +1585,8 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len, int fh_type) { + if (fh_type > fh_len) + fh_type = fh_len; if (fh_type < 4) return NULL; diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c index 558910f5e3c0..5703fb85f6bb 100644 --- a/fs/xfs/xfs_export.c +++ b/fs/xfs/xfs_export.c @@ -195,6 +195,9 @@ xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid, struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; struct inode *inode = NULL; + if (fh_len < xfs_fileid_length(fileid_type)) + return NULL; + switch (fileid_type) { case FILEID_INO32_GEN_PARENT: inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino, diff --git a/mm/shmem.c b/mm/shmem.c index 9d65a02a8799..40383cddc916 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2018,12 +2018,14 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb, { struct inode *inode; struct dentry *dentry = NULL; - u64 inum = fid->raw[2]; - inum = (inum << 32) | fid->raw[1]; + u64 inum; if (fh_len < 3) return NULL; + inum = fid->raw[2]; + inum = (inum << 32) | fid->raw[1]; + inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]), shmem_match, fid->raw); if (inode) { -- GitLab From 8892290fcc4476db20bbe591d9c0d401096d6275 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Tue, 1 May 2012 11:43:42 -0500 Subject: [PATCH 0757/1799] SCSI: hpsa: dial down lockup detection during firmware flash commit e85c59746957fd6e3595d02cf614370056b5816e upstream. Dial back the aggressiveness of the controller lockup detection thread. Currently it will declare the controller to be locked up if it goes for 10 seconds with no interrupts and no change in the heartbeat register. Dial back this to 30 seconds with no heartbeat change, and also snoop the ioctl path and if a firmware flash command is detected, dial it back further to 4 minutes until the firmware flash command completes. The reason for this is that during the firmware flash operation, the controller apparently doesn't update the heartbeat register as frequently as it is supposed to, and we can get a false positive. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/hpsa.c | 39 ++++++++++++++++++++++++++++++++++----- drivers/scsi/hpsa.h | 2 ++ drivers/scsi/hpsa_cmd.h | 1 + 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 8a5e25d2f21b..b0fefc435c03 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -548,12 +548,42 @@ static void set_performant_mode(struct ctlr_info *h, struct CommandList *c) c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1); } +static int is_firmware_flash_cmd(u8 *cdb) +{ + return cdb[0] == BMIC_WRITE && cdb[6] == BMIC_FLASH_FIRMWARE; +} + +/* + * During firmware flash, the heartbeat register may not update as frequently + * as it should. So we dial down lockup detection during firmware flash. and + * dial it back up when firmware flash completes. + */ +#define HEARTBEAT_SAMPLE_INTERVAL_DURING_FLASH (240 * HZ) +#define HEARTBEAT_SAMPLE_INTERVAL (30 * HZ) +static void dial_down_lockup_detection_during_fw_flash(struct ctlr_info *h, + struct CommandList *c) +{ + if (!is_firmware_flash_cmd(c->Request.CDB)) + return; + atomic_inc(&h->firmware_flash_in_progress); + h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL_DURING_FLASH; +} + +static void dial_up_lockup_detection_on_fw_flash_complete(struct ctlr_info *h, + struct CommandList *c) +{ + if (is_firmware_flash_cmd(c->Request.CDB) && + atomic_dec_and_test(&h->firmware_flash_in_progress)) + h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; +} + static void enqueue_cmd_and_start_io(struct ctlr_info *h, struct CommandList *c) { unsigned long flags; set_performant_mode(h, c); + dial_down_lockup_detection_during_fw_flash(h, c); spin_lock_irqsave(&h->lock, flags); addQ(&h->reqQ, c); h->Qdepth++; @@ -3049,6 +3079,7 @@ static inline int bad_tag(struct ctlr_info *h, u32 tag_index, static inline void finish_cmd(struct CommandList *c, u32 raw_tag) { removeQ(c); + dial_up_lockup_detection_on_fw_flash_complete(c->h, c); if (likely(c->cmd_type == CMD_SCSI)) complete_scsi_command(c); else if (c->cmd_type == CMD_IOCTL_PEND) @@ -4189,9 +4220,6 @@ static void controller_lockup_detected(struct ctlr_info *h) spin_unlock_irqrestore(&h->lock, flags); } -#define HEARTBEAT_SAMPLE_INTERVAL (10 * HZ) -#define HEARTBEAT_CHECK_MINIMUM_INTERVAL (HEARTBEAT_SAMPLE_INTERVAL / 2) - static void detect_controller_lockup(struct ctlr_info *h) { u64 now; @@ -4202,7 +4230,7 @@ static void detect_controller_lockup(struct ctlr_info *h) now = get_jiffies_64(); /* If we've received an interrupt recently, we're ok. */ if (time_after64(h->last_intr_timestamp + - (HEARTBEAT_CHECK_MINIMUM_INTERVAL), now)) + (h->heartbeat_sample_interval), now)) return; /* @@ -4211,7 +4239,7 @@ static void detect_controller_lockup(struct ctlr_info *h) * otherwise don't care about signals in this thread. */ if (time_after64(h->last_heartbeat_timestamp + - (HEARTBEAT_CHECK_MINIMUM_INTERVAL), now)) + (h->heartbeat_sample_interval), now)) return; /* If heartbeat has not changed since we last looked, we're not ok. */ @@ -4253,6 +4281,7 @@ static void add_ctlr_to_lockup_detector_list(struct ctlr_info *h) { unsigned long flags; + h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; spin_lock_irqsave(&lockup_detector_lock, flags); list_add_tail(&h->lockup_list, &hpsa_ctlr_list); spin_unlock_irqrestore(&lockup_detector_lock, flags); diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 7b28d54fa878..6f30a6f477ce 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -123,6 +123,8 @@ struct ctlr_info { u64 last_intr_timestamp; u32 last_heartbeat; u64 last_heartbeat_timestamp; + u32 heartbeat_sample_interval; + atomic_t firmware_flash_in_progress; u32 lockup_detected; struct list_head lockup_list; }; diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 8049815d8c1e..cdd742e4406a 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -162,6 +162,7 @@ struct SenseSubsystem_info { #define BMIC_WRITE 0x27 #define BMIC_CACHE_FLUSH 0xc2 #define HPSA_CACHE_FLUSH 0x01 /* C2 was already being used by HPSA */ +#define BMIC_FLASH_FIRMWARE 0xF7 /* Command List Structure */ union SCSI3Addr { -- GitLab From 1faef9285ad868082403da1cec5adefc0c505c2e Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sat, 22 Sep 2012 17:21:06 -0700 Subject: [PATCH 0758/1799] iscsi-target: Correctly set 0xffffffff field within ISCSI_OP_REJECT PDU commit f25590f39d543272f7ae7b00d533359c8d7ff331 upstream. This patch adds a missing iscsi_reject->ffffffff assignment within iscsit_send_reject() code to properly follow RFC-3720 Section 10.17 Bytes 16 -> 19 for the PDU format definition of ISCSI_OP_REJECT. We've not seen any initiators care about this bytes in practice, but as Ronnie reported this was causing trouble with wireshark packet decoding lets go ahead and fix this up now. Reported-by: Ronnie Sahlberg Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index e326d17e05a8..20572be94148 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3349,6 +3349,7 @@ static int iscsit_send_reject( hdr->opcode = ISCSI_OP_REJECT; hdr->flags |= ISCSI_FLAG_CMD_FINAL; hton24(hdr->dlength, ISCSI_HDR_LEN); + hdr->ffffffff = 0xffffffff; cmd->stat_sn = conn->stat_sn++; hdr->statsn = cpu_to_be32(cmd->stat_sn); hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); -- GitLab From b095d61243b5f2333e2ae11a9051cd9d47597002 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 26 Sep 2012 08:00:37 -0400 Subject: [PATCH 0759/1799] iscsit: remove incorrect unlock in iscsit_build_sendtargets_resp commit 904753da183566c71211d23c169a80184648c121 upstream. Fix a potential multiple spin-unlock -> deadlock scenario during the overflow check within iscsit_build_sendtargets_resp() as found by sparse static checking. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 20572be94148..23e122a5daf1 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3196,7 +3196,6 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) len += 1; if ((len + payload_len) > buffer_len) { - spin_unlock(&tiqn->tiqn_tpg_lock); end_of_buf = 1; goto eob; } -- GitLab From a114a8b43b038c327aff0298cfb69509469e84b4 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sun, 30 Sep 2012 12:20:02 -0700 Subject: [PATCH 0760/1799] iscsi-target: Add explicit set of cache_dynamic_acls=1 for TPG demo-mode commit 38b11bae6ba02da352340aff12ee25755977b222 upstream. We've had reports in the past about this specific case, so it's time to go ahead and explicitly set cache_dynamic_acls=1 for generate_node_acls=1 (TPG demo-mode) operation. During normal generate_node_acls=0 operation with explicit NodeACLs -> se_node_acl memory is persistent to the configfs group located at /sys/kernel/config/target/$TARGETNAME/$TPGT/acls/$INITIATORNAME, so in the generate_node_acls=1 case we want the reservation logic to reference existing per initiator IQN se_node_acl memory (not to generate a new se_node_acl), so go ahead and always set cache_dynamic_acls=1 when TPG demo-mode is enabled. Reported-by: Ronnie Sahlberg Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target_tpg.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index 879d8d0fa3fe..c3d7bf54f3de 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -672,6 +672,12 @@ int iscsit_ta_generate_node_acls( pr_debug("iSCSI_TPG[%hu] - Generate Initiator Portal Group ACLs: %s\n", tpg->tpgt, (a->generate_node_acls) ? "Enabled" : "Disabled"); + if (flag == 1 && a->cache_dynamic_acls == 0) { + pr_debug("Explicitly setting cache_dynamic_acls=1 when " + "generate_node_acls=1\n"); + a->cache_dynamic_acls = 1; + } + return 0; } @@ -711,6 +717,12 @@ int iscsit_ta_cache_dynamic_acls( return -EINVAL; } + if (a->generate_node_acls == 1 && flag == 0) { + pr_debug("Skipping cache_dynamic_acls=0 when" + " generate_node_acls=1\n"); + return 0; + } + a->cache_dynamic_acls = flag; pr_debug("iSCSI_TPG[%hu] - Cache Dynamic Initiator Portal Group" " ACLs %s\n", tpg->tpgt, (a->cache_dynamic_acls) ? -- GitLab From 2a7c11208e542071eee2240dde98e1673f5c01d4 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 3 Oct 2012 15:42:48 -0700 Subject: [PATCH 0761/1799] iscsi-target: Bump defaults for nopin_timeout + nopin_response_timeout values commit cf0eb28d3ba60098865bf7dbcbfdd6b1cc483e3b upstream. This patch increases the default for nopin_timeout to 15 seconds (wait between sending a new NopIN ping) and nopin_response_timeout to 30 seconds (wait for NopOUT response before failing the connection) in order to avoid false positives by iSCSI Initiators who are not always able (under load) to respond to NopIN echo PING requests within the current 5 second window. False positives have been observed recently using Open-iSCSI code on v3.3.x with heavy large-block READ workloads over small MTU 1 Gb/sec ports, and increasing these values to more reasonable defaults significantly reduces the possibility of false positive NopIN response timeout events under this specific workload. Historically these have been set low to initiate connection recovery as soon as possible if we don't hear a ping back, but for modern v3.x code on 1 -> 10 Gb/sec ports these new defaults make alot more sense. Signed-off-by: Nicholas Bellinger Cc: Christoph Hellwig Cc: Andy Grover Cc: Mike Christie Cc: Hannes Reinecke Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target_core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index d1c4bc22cca4..1596aec0c3d7 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -25,10 +25,10 @@ #define NA_DATAOUT_TIMEOUT_RETRIES 5 #define NA_DATAOUT_TIMEOUT_RETRIES_MAX 15 #define NA_DATAOUT_TIMEOUT_RETRIES_MIN 1 -#define NA_NOPIN_TIMEOUT 5 +#define NA_NOPIN_TIMEOUT 15 #define NA_NOPIN_TIMEOUT_MAX 60 #define NA_NOPIN_TIMEOUT_MIN 3 -#define NA_NOPIN_RESPONSE_TIMEOUT 5 +#define NA_NOPIN_RESPONSE_TIMEOUT 30 #define NA_NOPIN_RESPONSE_TIMEOUT_MAX 60 #define NA_NOPIN_RESPONSE_TIMEOUT_MIN 3 #define NA_RANDOM_DATAIN_PDU_OFFSETS 0 -- GitLab From 791f153c5bea0636537ceb417bfea78f0f232d4f Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 2 Oct 2012 11:03:31 -0700 Subject: [PATCH 0762/1799] SCSI: storvsc: Account for in-transit packets in the RESET path commit 5c1b10ab7f93d24f29b5630286e323d1c5802d5c upstream. Properly account for I/O in transit before returning from the RESET call. In the absense of this patch, we could have a situation where the host may respond to a command that was issued prior to the issuance of the RESET command at some arbitrary time after responding to the RESET command. Currently, the host does not do anything with the RESET command. Signed-off-by: K. Y. Srinivasan Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/storvsc_drv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 83a1972a1999..40a45700c8db 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1211,7 +1211,12 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) /* * At this point, all outstanding requests in the adapter * should have been flushed out and return to us + * There is a potential race here where the host may be in + * the process of responding when we return from here. + * Just wait for all in-transit packets to be accounted for + * before we return from here. */ + storvsc_wait_to_drain(stor_device); return SUCCESS; } -- GitLab From 023f18fee60cd9ef86c8299dd9debccad1f93351 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Thu, 16 Aug 2012 16:38:45 +0200 Subject: [PATCH 0763/1799] SCSI: scsi_debug: Fix off-by-one bug when unmapping region commit bc977749e967daa56de1922cf4cb38525631c51c upstream. Currently it is possible to unmap one more block than user requested to due to the off-by-one error in unmap_region(). This is probably due to the fact that the end variable despite its name actually points to the last block to unmap + 1. However in the condition it is handled as the last block of the region to unmap. The bug was not previously spotted probably due to the fact that the region was not zeroed, which has changed with commit be1dd78de5686c062bb3103f9e86d444a10ed783. With that commit we were able to corrupt the ext4 file system on 256M scsi_debug device with LBPRZ enabled using fstrim. Since the 'end' semantic is the same in several functions there this commit just fixes the condition to use the 'end' variable correctly in that context. Reported-by: Paolo Bonzini Signed-off-by: Lukas Czerner Reviewed-by: Martin K. Petersen Acked-by: Douglas Gilbert Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 182d5a57ab74..f4cc4139ada8 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -2054,7 +2054,7 @@ static void unmap_region(sector_t lba, unsigned int len) block = lba + alignment; rem = do_div(block, granularity); - if (rem == 0 && lba + granularity <= end && block < map_size) { + if (rem == 0 && lba + granularity < end && block < map_size) { clear_bit(block, map_storep); if (scsi_debug_lbprz) memset(fake_storep + -- GitLab From 90e4ed1b7de612e4ed18029e61134ab2fea6233e Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 28 Sep 2012 02:12:45 +0100 Subject: [PATCH 0764/1799] ARM: 7541/1: Add ARM ERRATA 775420 workaround commit 7253b85cc62d6ff84143d96fe6cd54f73736f4d7 upstream. arm: Add ARM ERRATA 775420 workaround Workaround for the 775420 Cortex-A9 (r2p2, r2p6,r2p8,r2p10,r3p0) erratum. In case a date cache maintenance operation aborts with MMU exception, it might cause the processor to deadlock. This workaround puts DSB before executing ISB if an abort may occur on cache maintenance. Based on work by Kouei Abe and feedback from Catalin Marinas. Signed-off-by: Kouei Abe [ horms@verge.net.au: Changed to implementation suggested by catalin.marinas@arm.com ] Acked-by: Catalin Marinas Signed-off-by: Simon Horman Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/Kconfig | 10 ++++++++++ arch/arm/mm/cache-v7.S | 3 +++ 2 files changed, 13 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 352322a67651..e14ae1141429 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1405,6 +1405,16 @@ config PL310_ERRATA_769419 on systems with an outer cache, the store buffer is drained explicitly. +config ARM_ERRATA_775420 + bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock" + depends on CPU_V7 + help + This option enables the workaround for the 775420 Cortex-A9 (r2p2, + r2p6,r2p8,r2p10,r3p0) erratum. In case a date cache maintenance + operation aborts with MMU exception, it might cause the processor + to deadlock. This workaround puts DSB before executing ISB if + an abort may occur on cache maintenance. + endmenu source "arch/arm/common/Kconfig" diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index a655d3da386d..82ab2c5b4ac4 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -211,6 +211,9 @@ ENTRY(v7_coherent_user_range) * isn't mapped, just try the next page. */ 9001: +#ifdef CONFIG_ARM_ERRATA_775420 + dsb +#endif mov r12, r12, lsr #12 mov r12, r12, lsl #12 add r12, r12, #4096 -- GitLab From 0bd1ed9ead1a2b7fc1534bff04729c3712a6fb25 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 6 Oct 2012 14:12:56 +0200 Subject: [PATCH 0765/1799] firewire: cdev: fix user memory corruption (i386 userland on amd64 kernel) commit 790198f74c9d1b46b6a89504361b1a844670d050 upstream. Fix two bugs of the /dev/fw* character device concerning the FW_CDEV_IOC_GET_INFO ioctl with nonzero fw_cdev_get_info.bus_reset. (Practically all /dev/fw* clients issue this ioctl right after opening the device.) Both bugs are caused by sizeof(struct fw_cdev_event_bus_reset) being 36 without natural alignment and 40 with natural alignment. 1) Memory corruption, affecting i386 userland on amd64 kernel: Userland reserves a 36 bytes large buffer, kernel writes 40 bytes. This has been first found and reported against libraw1394 if compiled with gcc 4.7 which happens to order libraw1394's stack such that the bug became visible as data corruption. 2) Information leak, affecting all kernel architectures except i386: 4 bytes of random kernel stack data were leaked to userspace. Hence limit the respective copy_to_user() to the 32-bit aligned size of struct fw_cdev_event_bus_reset. Reported-by: Simon Kirby Signed-off-by: Stefan Richter Signed-off-by: Greg Kroah-Hartman --- drivers/firewire/core-cdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 2e6b24547e2a..b8e4809cae0e 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -471,8 +471,8 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg) client->bus_reset_closure = a->bus_reset_closure; if (a->bus_reset != 0) { fill_bus_reset_event(&bus_reset, client); - ret = copy_to_user(u64_to_uptr(a->bus_reset), - &bus_reset, sizeof(bus_reset)); + /* unaligned size of bus_reset is 36 bytes */ + ret = copy_to_user(u64_to_uptr(a->bus_reset), &bus_reset, 36); } if (ret == 0 && list_empty(&client->link)) list_add_tail(&client->link, &client->device->client_list); -- GitLab From b77a7a0e9f3ed51b523857f26c42e350faf43add Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 12 Sep 2012 16:49:15 -0400 Subject: [PATCH 0766/1799] SUNRPC: Ensure that the TCP socket is closed when in CLOSE_WAIT commit a519fc7a70d1a918574bb826cc6905b87b482eb9 upstream. Instead of doing a shutdown() call, we need to do an actual close(). Ditto if/when the server is sending us junk RPC headers. Signed-off-by: Trond Myklebust Tested-by: Simon Kirby Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index b88c6bf657ba..00ff34343bae 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1028,6 +1028,16 @@ static void xs_udp_data_ready(struct sock *sk, int len) read_unlock_bh(&sk->sk_callback_lock); } +/* + * Helper function to force a TCP close if the server is sending + * junk and/or it has put us in CLOSE_WAIT + */ +static void xs_tcp_force_close(struct rpc_xprt *xprt) +{ + set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); + xprt_force_disconnect(xprt); +} + static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) { struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); @@ -1054,7 +1064,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea /* Sanity check of the record length */ if (unlikely(transport->tcp_reclen < 8)) { dprintk("RPC: invalid TCP record fragment length\n"); - xprt_force_disconnect(xprt); + xs_tcp_force_close(xprt); return; } dprintk("RPC: reading TCP record fragment of length %d\n", @@ -1135,7 +1145,7 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport, break; default: dprintk("RPC: invalid request message type\n"); - xprt_force_disconnect(&transport->xprt); + xs_tcp_force_close(&transport->xprt); } xs_tcp_check_fraghdr(transport); } @@ -1458,6 +1468,8 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt) static void xs_sock_mark_closed(struct rpc_xprt *xprt) { smp_mb__before_clear_bit(); + clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); + clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state); clear_bit(XPRT_CLOSE_WAIT, &xprt->state); clear_bit(XPRT_CLOSING, &xprt->state); smp_mb__after_clear_bit(); @@ -1515,8 +1527,8 @@ static void xs_tcp_state_change(struct sock *sk) break; case TCP_CLOSE_WAIT: /* The server initiated a shutdown of the socket */ - xprt_force_disconnect(xprt); xprt->connect_cookie++; + xs_tcp_force_close(xprt); case TCP_CLOSING: /* * If the server closed down the connection, make sure that @@ -2159,8 +2171,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) /* We're probably in TIME_WAIT. Get rid of existing socket, * and retry */ - set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); - xprt_force_disconnect(xprt); + xs_tcp_force_close(xprt); break; case -ECONNREFUSED: case -ECONNRESET: -- GitLab From e1621ec4754097582c73c0ed8c394dcc50b1e0fd Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Mon, 17 Sep 2012 20:05:33 +0200 Subject: [PATCH 0767/1799] target: fix return code in target_core_init_configfs error path commit 37bb7899ca366dc212b71b150e78566d04808cc0 upstream. This patch fixes error cases within target_core_init_configfs() to properly set ret = -ENOMEM before jumping to the out_global exception path. This was originally discovered with the following Coccinelle semantic match information: Convert a nonnegative error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Peter Senna Tschudin Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_configfs.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index cbb66537d230..3f90d4b03e64 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -3115,6 +3115,7 @@ static int __init target_core_init_configfs(void) GFP_KERNEL); if (!target_cg->default_groups) { pr_err("Unable to allocate target_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } @@ -3130,6 +3131,7 @@ static int __init target_core_init_configfs(void) GFP_KERNEL); if (!hba_cg->default_groups) { pr_err("Unable to allocate hba_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } config_group_init_type_name(&alua_group, @@ -3145,6 +3147,7 @@ static int __init target_core_init_configfs(void) GFP_KERNEL); if (!alua_cg->default_groups) { pr_err("Unable to allocate alua_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } @@ -3156,14 +3159,17 @@ static int __init target_core_init_configfs(void) * Add core/alua/lu_gps/default_lu_gp */ lu_gp = core_alua_allocate_lu_gp("default_lu_gp", 1); - if (IS_ERR(lu_gp)) + if (IS_ERR(lu_gp)) { + ret = -ENOMEM; goto out_global; + } lu_gp_cg = &alua_lu_gps_group; lu_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, GFP_KERNEL); if (!lu_gp_cg->default_groups) { pr_err("Unable to allocate lu_gp_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } -- GitLab From c525d8ee0c7701d72d8144f536d47a5bd30159e9 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 10 Oct 2012 13:25:48 -0400 Subject: [PATCH 0768/1799] xen/bootup: allow {read|write}_cr8 pvops call. commit 1a7bbda5b1ab0e02622761305a32dc38735b90b2 upstream. We actually do not do anything about it. Just return a default value of zero and if the kernel tries to write anything but 0 we BUG_ON. This fixes the case when an user tries to suspend the machine and it blows up in save_processor_state b/c 'read_cr8' is set to NULL and we get: kernel BUG at /home/konrad/ssd/linux/arch/x86/include/asm/paravirt.h:100! invalid opcode: 0000 [#1] SMP Pid: 2687, comm: init.late Tainted: G O 3.6.0upstream-00002-gac264ac-dirty #4 Bochs Bochs RIP: e030:[] [] save_processor_state+0x212/0x270 .. snip.. Call Trace: [] do_suspend_lowlevel+0xf/0xac [] ? x86_acpi_suspend_lowlevel+0x10c/0x150 [] acpi_suspend_enter+0x57/0xd5 Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/enlighten.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 40edfc37a6fd..5fa38a80000c 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -942,7 +942,16 @@ static void xen_write_cr4(unsigned long cr4) native_write_cr4(cr4); } - +#ifdef CONFIG_X86_64 +static inline unsigned long xen_read_cr8(void) +{ + return 0; +} +static inline void xen_write_cr8(unsigned long val) +{ + BUG_ON(val); +} +#endif static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) { int ret; @@ -1111,6 +1120,11 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .read_cr4_safe = native_read_cr4_safe, .write_cr4 = xen_write_cr4, +#ifdef CONFIG_X86_64 + .read_cr8 = xen_read_cr8, + .write_cr8 = xen_write_cr8, +#endif + .wbinvd = native_wbinvd, .read_msr = native_read_msr_safe, -- GitLab From e299f8abb241b52fe0de458143a537ac91b269a2 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 10 Oct 2012 13:30:47 -0400 Subject: [PATCH 0769/1799] xen/bootup: allow read_tscp call for Xen PV guests. commit cd0608e71e9757f4dae35bcfb4e88f4d1a03a8ab upstream. The hypervisor will trap it. However without this patch, we would crash as the .read_tscp is set to NULL. This patch fixes it and sets it to the native_read_tscp call. Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/enlighten.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 5fa38a80000c..59100548cbdb 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1135,6 +1135,8 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .read_tsc = native_read_tsc, .read_pmc = native_read_pmc, + .read_tscp = native_read_tscp, + .iret = xen_iret, .irq_enable_sysexit = xen_sysexit, #ifdef CONFIG_X86_64 -- GitLab From 7fce34e1a40c49a2f579ffd1342884cf8bca8e96 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Sep 2012 14:09:30 -0700 Subject: [PATCH 0770/1799] block: fix request_queue->flags initialization commit 60ea8226cbd5c8301f9a39edc574ddabcb8150e0 upstream. A queue newly allocated with blk_alloc_queue_node() has only QUEUE_FLAG_BYPASS set. For request-based drivers, blk_init_allocated_queue() is called and q->queue_flags is overwritten with QUEUE_FLAG_DEFAULT which doesn't include BYPASS even though the initial bypass is still in effect. In blk_init_allocated_queue(), or QUEUE_FLAG_DEFAULT to q->queue_flags instead of overwriting. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/blk-core.c b/block/blk-core.c index 1f61b74867e4..85fd41003434 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -601,7 +601,7 @@ blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn, q->request_fn = rfn; q->prep_rq_fn = NULL; q->unprep_rq_fn = NULL; - q->queue_flags = QUEUE_FLAG_DEFAULT; + q->queue_flags |= QUEUE_FLAG_DEFAULT; /* Override internal queue lock with supplied lock pointer */ if (lock) -- GitLab From 865221d84f23dafcf63485e9081fe972646fef0a Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Thu, 11 Oct 2012 08:00:33 +0800 Subject: [PATCH 0771/1799] autofs4 - fix reset pending flag on mount fail commit 49999ab27eab6289a8e4f450e148bdab521361b2 upstream. In autofs4_d_automount(), if a mount fail occurs the AUTOFS_INF_PENDING mount pending flag is not cleared. One effect of this is when using the "browse" option, directory entry attributes show up with all "?"s due to the incorrect callback and subsequent failure return (when in fact no callback should be made). Signed-off-by: Ian Kent Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/autofs4/root.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 75e5f1c8e028..8c4292f89eef 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -392,10 +392,12 @@ static struct vfsmount *autofs4_d_automount(struct path *path) ino->flags |= AUTOFS_INF_PENDING; spin_unlock(&sbi->fs_lock); status = autofs4_mount_wait(dentry); - if (status) - return ERR_PTR(status); spin_lock(&sbi->fs_lock); ino->flags &= ~AUTOFS_INF_PENDING; + if (status) { + spin_unlock(&sbi->fs_lock); + return ERR_PTR(status); + } } done: if (!(ino->flags & AUTOFS_INF_EXPIRING)) { -- GitLab From 08de372d6c39473773fc303b9253a2be938badbd Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Fri, 22 Jun 2012 13:49:31 -0400 Subject: [PATCH 0772/1799] module: taint kernel when lve module is loaded commit c99af3752bb52ba3aece5315279a57a477edfaf1 upstream. Cloudlinux have a product called lve that includes a kernel module. This was previously GPLed but is now under a proprietary license, but the module continues to declare MODULE_LICENSE("GPL") and makes use of some EXPORT_SYMBOL_GPL symbols. Forcibly taint it in order to avoid this. Signed-off-by: Matthew Garrett Cc: Alex Lyashkov Signed-off-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- kernel/module.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/module.c b/kernel/module.c index 78ac6ec1e425..61ea75eaeec6 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2729,6 +2729,10 @@ static int check_module_license_and_versions(struct module *mod) if (strcmp(mod->name, "driverloader") == 0) add_taint_module(mod, TAINT_PROPRIETARY_MODULE); + /* lve claims to be GPL but upstream won't provide source */ + if (strcmp(mod->name, "lve") == 0) + add_taint_module(mod, TAINT_PROPRIETARY_MODULE); + #ifdef CONFIG_MODVERSIONS if ((mod->num_syms && !mod->crcs) || (mod->num_gpl_syms && !mod->gpl_crcs) -- GitLab From a065f95a851f18c2b4531808c0a9503f14aa9624 Mon Sep 17 00:00:00 2001 From: Alexander Holler Date: Tue, 14 Aug 2012 09:11:09 +0200 Subject: [PATCH 0773/1799] video/udlfb: fix line counting in fb_write commit b8c4321f3d194469007f5f5f2b34ec278c264a04 upstream. Line 0 and 1 were both written to line 0 (on the display) and all subsequent lines had an offset of -1. The result was that the last line on the display was never overwritten by writes to /dev/fbN. Signed-off-by: Alexander Holler Acked-by: Bernie Thompson Signed-off-by: Florian Tobias Schandinat Signed-off-by: Greg Kroah-Hartman --- drivers/video/udlfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index a159b63e18b9..85d81103c1f9 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c @@ -647,7 +647,7 @@ static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf, result = fb_sys_write(info, buf, count, ppos); if (result > 0) { - int start = max((int)(offset / info->fix.line_length) - 1, 0); + int start = max((int)(offset / info->fix.line_length), 0); int lines = min((u32)((result / info->fix.line_length) + 1), (u32)info->var.yres); -- GitLab From 3dca360fc8484e40f50205a09f6dbbb591791663 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 4 Sep 2012 11:45:32 -0400 Subject: [PATCH 0774/1799] viafb: don't touch clock state on OLPC XO-1.5 commit 012a1211845eab69a5488d59eb87d24cc518c627 upstream. As detailed in the thread titled "viafb PLL/clock tweaking causes XO-1.5 instability," enabling or disabling the IGA1/IGA2 clocks causes occasional stability problems during suspend/resume cycles on this platform. This is rather odd, as the documentation suggests that clocks have two states (on/off) and the default (stable) configuration is configured to enable the clock only when it is needed. However, explicitly enabling *or* disabling the clock triggers this system instability, suggesting that there is a 3rd state at play here. Leaving the clock enable/disable registers alone solves this problem. This fixes spurious reboots during suspend/resume behaviour introduced by commit b692a63a. Signed-off-by: Daniel Drake Signed-off-by: Florian Tobias Schandinat Signed-off-by: Greg Kroah-Hartman --- drivers/video/via/via_clock.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/video/via/via_clock.c b/drivers/video/via/via_clock.c index af8f26b643c1..db1e39277e32 100644 --- a/drivers/video/via/via_clock.c +++ b/drivers/video/via/via_clock.c @@ -25,6 +25,7 @@ #include #include +#include #include "via_clock.h" #include "global.h" #include "debug.h" @@ -289,6 +290,10 @@ static void dummy_set_pll(struct via_pll_config config) printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap); } +static void noop_set_clock_state(u8 state) +{ +} + void via_clock_init(struct via_clock *clock, int gfx_chip) { switch (gfx_chip) { @@ -346,4 +351,18 @@ void via_clock_init(struct via_clock *clock, int gfx_chip) break; } + + if (machine_is_olpc()) { + /* The OLPC XO-1.5 cannot suspend/resume reliably if the + * IGA1/IGA2 clocks are set as on or off (memory rot + * occasionally happens during suspend under such + * configurations). + * + * The only known stable scenario is to leave this bits as-is, + * which in their default states are documented to enable the + * clock only when it is needed. + */ + clock->set_primary_clock_state = noop_set_clock_state; + clock->set_secondary_clock_state = noop_set_clock_state; + } } -- GitLab From 00dff266efe889d4fc6569f3e39ae7195cb83da7 Mon Sep 17 00:00:00 2001 From: "Hildner, Christian" Date: Mon, 8 Oct 2012 15:49:03 +0200 Subject: [PATCH 0775/1799] timers: Fix endless looping between cascade() and internal_add_timer() commit 26cff4e2aa4d666dc6a120ea34336b5057e3e187 upstream. Adding two (or more) timers with large values for "expires" (they have to reside within tv5 in the same list) leads to endless looping between cascade() and internal_add_timer() in case CONFIG_BASE_SMALL is one and jiffies are crossing the value 1 << 18. The bug was introduced between 2.6.11 and 2.6.12 (and survived for quite some time). This patch ensures that when cascade() is called timers within tv5 are not added endlessly to their own list again, instead they are added to the next lower tv level tv4 (as expected). Signed-off-by: Christian Hildner Reviewed-by: Jan Kiszka Link: http://lkml.kernel.org/r/98673C87CB31274881CFFE0B65ECC87B0F5FC1963E@DEFTHW99EA4MSX.ww902.siemens.net Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/timer.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/kernel/timer.c b/kernel/timer.c index a297ffcf888e..6dfdb72828ff 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -63,6 +63,7 @@ EXPORT_SYMBOL(jiffies_64); #define TVR_SIZE (1 << TVR_BITS) #define TVN_MASK (TVN_SIZE - 1) #define TVR_MASK (TVR_SIZE - 1) +#define MAX_TVAL ((unsigned long)((1ULL << (TVR_BITS + 4*TVN_BITS)) - 1)) struct tvec { struct list_head vec[TVN_SIZE]; @@ -356,11 +357,12 @@ static void internal_add_timer(struct tvec_base *base, struct timer_list *timer) vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK); } else { int i; - /* If the timeout is larger than 0xffffffff on 64-bit - * architectures then we use the maximum timeout: + /* If the timeout is larger than MAX_TVAL (on 64-bit + * architectures or with CONFIG_BASE_SMALL=1) then we + * use the maximum timeout. */ - if (idx > 0xffffffffUL) { - idx = 0xffffffffUL; + if (idx > MAX_TVAL) { + idx = MAX_TVAL; expires = idx + base->timer_jiffies; } i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK; -- GitLab From a0fee8de3ae5784d4308b7bd18c303a4144ece18 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 3 Oct 2012 21:07:52 +0200 Subject: [PATCH 0776/1799] ath9k: use ieee80211_free_txskb commit 249ee72249140fe5b9adc988f97298f0aa5db2fc upstream. Using ieee80211_free_txskb for tx frames is required, since mac80211 clones skbs for which socket tx status is requested. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/beacon.c | 2 +- drivers/net/wireless/ath/ath9k/main.c | 2 +- drivers/net/wireless/ath/ath9k/xmit.c | 53 ++++++++++++++----------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 626418222c85..5eb53c98d75e 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -121,7 +121,7 @@ static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) if (ath_tx_start(hw, skb, &txctl) != 0) { ath_dbg(common, XMIT, "CABQ TX failed\n"); - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); } } diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index d5dabcb61a0a..91e2c4f53d14 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1147,7 +1147,7 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return; exit: - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); } static void ath9k_stop(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 4d571394c7a8..b78773b48dba 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -64,8 +64,7 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, - struct sk_buff *skb, - bool dequeue); + struct sk_buff *skb); enum { MCS_HT20, @@ -201,7 +200,15 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) fi = get_frame_info(skb); bf = fi->bf; - if (bf && fi->retries) { + if (!bf) { + bf = ath_tx_setup_buffer(sc, txq, tid, skb); + if (!bf) { + ieee80211_free_txskb(sc->hw, skb); + continue; + } + } + + if (fi->retries) { list_add_tail(&bf->list, &bf_head); ath_tx_update_baw(sc, tid, bf->bf_state.seqno); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); @@ -812,10 +819,13 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, fi = get_frame_info(skb); bf = fi->bf; if (!fi->bf) - bf = ath_tx_setup_buffer(sc, txq, tid, skb, true); + bf = ath_tx_setup_buffer(sc, txq, tid, skb); - if (!bf) + if (!bf) { + __skb_unlink(skb, &tid->buf_q); + ieee80211_free_txskb(sc->hw, skb); continue; + } bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; seqno = bf->bf_state.seqno; @@ -1717,9 +1727,11 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, return; } - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); - if (!bf) + bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); + if (!bf) { + ieee80211_free_txskb(sc->hw, skb); return; + } bf->bf_state.bf_type = BUF_AMPDU; INIT_LIST_HEAD(&bf_head); @@ -1743,11 +1755,6 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf; bf = fi->bf; - if (!bf) - bf = ath_tx_setup_buffer(sc, txq, tid, skb, false); - - if (!bf) - return; INIT_LIST_HEAD(&bf_head); list_add_tail(&bf->list, &bf_head); @@ -1820,8 +1827,7 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, - struct sk_buff *skb, - bool dequeue) + struct sk_buff *skb) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_frame_info *fi = get_frame_info(skb); @@ -1833,7 +1839,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, bf = ath_tx_get_buffer(sc); if (!bf) { ath_dbg(common, XMIT, "TX buffers are full\n"); - goto error; + return NULL; } ATH_TXBUF_RESET(bf); @@ -1862,18 +1868,12 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, ath_err(ath9k_hw_common(sc->sc_ah), "dma_mapping_error() on TX\n"); ath_tx_return_buffer(sc, bf); - goto error; + return NULL; } fi->bf = bf; return bf; - -error: - if (dequeue) - __skb_unlink(skb, &tid->buf_q); - dev_kfree_skb_any(skb); - return NULL; } /* FIXME: tx power */ @@ -1902,9 +1902,14 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, */ ath_tx_send_ampdu(sc, tid, skb, txctl); } else { - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); - if (!bf) + bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); + if (!bf) { + if (txctl->paprd) + dev_kfree_skb_any(skb); + else + ieee80211_free_txskb(sc->hw, skb); return; + } bf->bf_state.bfs_paprd = txctl->paprd; -- GitLab From 9b38cc4a70f2c83857fd37707570a18c1027effe Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 11 Oct 2012 14:20:58 +1100 Subject: [PATCH 0777/1799] md/raid10: use correct limit variable commit 91502f099dfc5a1e8812898e26ee280713e1d002 upstream. Clang complains that we are assigning a variable to itself. This should be using bad_sectors like the similar earlier check does. Bug has been present since 3.1-rc1. It is minor but could conceivably cause corruption or other bad behaviour. Signed-off-by: Dan Carpenter Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 1f7e8cd44e5c..4a038cdc0b54 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -3019,7 +3019,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, else { bad_sectors -= (sector - first_bad); if (max_sync > bad_sectors) - max_sync = max_sync; + max_sync = bad_sectors; continue; } } -- GitLab From c4c493a4adcee75e1e44af044d0b7fc1b5192b61 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Sun, 26 Aug 2012 22:37:03 -0500 Subject: [PATCH 0778/1799] kdb,vt_console: Fix missed data due to pager overruns commit 17b572e82032bc246324ce136696656b66d4e3f1 upstream. It is possible to miss data when using the kdb pager. The kdb pager does not pay attention to the maximum column constraint of the screen or serial terminal. This result is not incrementing the shown lines correctly and the pager will print more lines that fit on the screen. Obviously that is less than useful when using a VGA console where you cannot scroll back. The pager will now look at the kdb_buffer string to see how many characters are printed. It might not be perfect considering you can output ASCII that might move the cursor position, but it is a substantially better approximation for viewing dmesg and trace logs. This also means that the vt screen needs to set the kdb COLUMNS variable. Signed-off-by: Jason Wessel Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 13 +++++++++++++ kernel/debug/kdb/kdb_io.c | 33 ++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 2156188db4a6..18d06be8c9bd 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -3475,6 +3475,19 @@ int con_debug_enter(struct vc_data *vc) kdb_set(2, setargs); } } + if (vc->vc_cols < 999) { + int colcount; + char cols[4]; + const char *setargs[3] = { + "set", + "COLUMNS", + cols, + }; + if (kdbgetintenv(setargs[0], &colcount)) { + snprintf(cols, 4, "%i", vc->vc_cols); + kdb_set(2, setargs); + } + } #endif /* CONFIG_KGDB_KDB */ return ret; } diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index bb9520f0f6ff..572e604c5621 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c @@ -552,6 +552,7 @@ int vkdb_printf(const char *fmt, va_list ap) { int diag; int linecount; + int colcount; int logging, saved_loglevel = 0; int saved_trap_printk; int got_printf_lock = 0; @@ -584,6 +585,10 @@ int vkdb_printf(const char *fmt, va_list ap) if (diag || linecount <= 1) linecount = 24; + diag = kdbgetintenv("COLUMNS", &colcount); + if (diag || colcount <= 1) + colcount = 80; + diag = kdbgetintenv("LOGGING", &logging); if (diag) logging = 0; @@ -690,7 +695,7 @@ int vkdb_printf(const char *fmt, va_list ap) gdbstub_msg_write(kdb_buffer, retlen); } else { if (dbg_io_ops && !dbg_io_ops->is_console) { - len = strlen(kdb_buffer); + len = retlen; cp = kdb_buffer; while (len--) { dbg_io_ops->write_char(*cp); @@ -709,11 +714,29 @@ int vkdb_printf(const char *fmt, va_list ap) printk(KERN_INFO "%s", kdb_buffer); } - if (KDB_STATE(PAGER) && strchr(kdb_buffer, '\n')) - kdb_nextline++; + if (KDB_STATE(PAGER)) { + /* + * Check printed string to decide how to bump the + * kdb_nextline to control when the more prompt should + * show up. + */ + int got = 0; + len = retlen; + while (len--) { + if (kdb_buffer[len] == '\n') { + kdb_nextline++; + got = 0; + } else if (kdb_buffer[len] == '\r') { + got = 0; + } else { + got++; + } + } + kdb_nextline += got / (colcount + 1); + } /* check for having reached the LINES number of printed lines */ - if (kdb_nextline == linecount) { + if (kdb_nextline >= linecount) { char buf1[16] = ""; #if defined(CONFIG_SMP) char buf2[32]; @@ -776,7 +799,7 @@ int vkdb_printf(const char *fmt, va_list ap) kdb_grepping_flag = 0; kdb_printf("\n"); } else if (buf1[0] == ' ') { - kdb_printf("\n"); + kdb_printf("\r"); suspend_grep = 1; /* for this recursion */ } else if (buf1[0] == '\n') { kdb_nextline = linecount - 1; -- GitLab From c8479435f2191c22871a4b27e7eb2d501f4661e8 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Tue, 9 Oct 2012 17:48:16 +0000 Subject: [PATCH 0779/1799] pktgen: fix crash when generating IPv6 packets commit 5aa8b572007c4bca1e6d3dd4c4820f1ae49d6bb2 upstream. For IPv6, sizeof(struct ipv6hdr) = 40, thus the following expression will result negative: datalen = pkt_dev->cur_pkt_size - 14 - sizeof(struct ipv6hdr) - sizeof(struct udphdr) - pkt_dev->pkt_overhead; And, the check "if (datalen < sizeof(struct pktgen_hdr))" will be passed as "datalen" is promoted to unsigned, therefore will cause a crash later. This is a quick fix by checking if "datalen" is negative. The following patch will increase the default value of 'min_pkt_size' for IPv6. This bug should exist for a long time, so Cc -stable too. Signed-off-by: Cong Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/pktgen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index b81369b6ddc0..8dae76f481ee 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2932,7 +2932,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, sizeof(struct ipv6hdr) - sizeof(struct udphdr) - pkt_dev->pkt_overhead; - if (datalen < sizeof(struct pktgen_hdr)) { + if (datalen < 0 || datalen < sizeof(struct pktgen_hdr)) { datalen = sizeof(struct pktgen_hdr); if (net_ratelimit()) pr_info("increased datalen to %d\n", datalen); -- GitLab From 486aaeb0b972820ed704bdf416270ec4b0950da3 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Sat, 7 Jul 2012 20:30:11 +0300 Subject: [PATCH 0780/1799] ipvs: fix oops in ip_vs_dst_event on rmmod commit 283283c4da91adc44b03519f434ee1e7e91d6fdb upstream. After commit 39f618b4fd95ae243d940ec64c961009c74e3333 (3.4) "ipvs: reset ipvs pointer in netns" we can oops in ip_vs_dst_event on rmmod ip_vs because ip_vs_control_cleanup is called after the ipvs_core_ops subsys is unregistered and net->ipvs is NULL. Fix it by exiting early from ip_vs_dst_event if ipvs is NULL. It is safe because all services and dests for the net are already freed. Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman Signed-off-by: Pablo Neira Ayuso Acked-by: David Miller Signed-off-by: Greg Kroah-Hartman --- net/netfilter/ipvs/ip_vs_ctl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 97e73806bacc..cbc5bfd8c8e4 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1521,11 +1521,12 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, { struct net_device *dev = ptr; struct net *net = dev_net(dev); + struct netns_ipvs *ipvs = net_ipvs(net); struct ip_vs_service *svc; struct ip_vs_dest *dest; unsigned int idx; - if (event != NETDEV_UNREGISTER) + if (event != NETDEV_UNREGISTER || !ipvs) return NOTIFY_DONE; IP_VS_DBG(3, "%s() dev=%s\n", __func__, dev->name); EnterFunction(2); @@ -1551,7 +1552,7 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, } } - list_for_each_entry(dest, &net_ipvs(net)->dest_trash, n_list) { + list_for_each_entry(dest, &ipvs->dest_trash, n_list) { __ip_vs_dev_reset(dest, dev); } mutex_unlock(&__ip_vs_mutex); -- GitLab From 7fcbcdc96302e9d3e3b36df4fbc86a4c82761092 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 29 Aug 2012 16:25:49 +0000 Subject: [PATCH 0781/1799] netfilter: nf_conntrack: fix racy timer handling with reliable events commit 5b423f6a40a0327f9d40bc8b97ce9be266f74368 upstream. Existing code assumes that del_timer returns true for alive conntrack entries. However, this is not true if reliable events are enabled. In that case, del_timer may return true for entries that were just inserted in the dying list. Note that packets / ctnetlink may hold references to conntrack entries that were just inserted to such list. This patch fixes the issue by adding an independent timer for event delivery. This increases the size of the ecache extension. Still we can revisit this later and use variable size extensions to allocate this area on demand. Tested-by: Oliver Smith Signed-off-by: Pablo Neira Ayuso Acked-by: David Miller Signed-off-by: Greg Kroah-Hartman --- include/net/netfilter/nf_conntrack_ecache.h | 1 + net/netfilter/nf_conntrack_core.c | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index a88fb6939387..ea6f8a48ffe5 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -18,6 +18,7 @@ struct nf_conntrack_ecache { u16 ctmask; /* bitmask of ct events to be delivered */ u16 expmask; /* bitmask of expect events to be delivered */ u32 pid; /* netlink pid of destroyer */ + struct timer_list timeout; }; static inline struct nf_conntrack_ecache * diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 729f157a0efa..9a171b2445b1 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -249,12 +249,15 @@ static void death_by_event(unsigned long ul_conntrack) { struct nf_conn *ct = (void *)ul_conntrack; struct net *net = nf_ct_net(ct); + struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct); + + BUG_ON(ecache == NULL); if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) { /* bad luck, let's retry again */ - ct->timeout.expires = jiffies + + ecache->timeout.expires = jiffies + (random32() % net->ct.sysctl_events_retry_timeout); - add_timer(&ct->timeout); + add_timer(&ecache->timeout); return; } /* we've got the event delivered, now it's dying */ @@ -268,6 +271,9 @@ static void death_by_event(unsigned long ul_conntrack) void nf_ct_insert_dying_list(struct nf_conn *ct) { struct net *net = nf_ct_net(ct); + struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct); + + BUG_ON(ecache == NULL); /* add this conntrack to the dying list */ spin_lock_bh(&nf_conntrack_lock); @@ -275,10 +281,10 @@ void nf_ct_insert_dying_list(struct nf_conn *ct) &net->ct.dying); spin_unlock_bh(&nf_conntrack_lock); /* set a new timer to retry event delivery */ - setup_timer(&ct->timeout, death_by_event, (unsigned long)ct); - ct->timeout.expires = jiffies + + setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct); + ecache->timeout.expires = jiffies + (random32() % net->ct.sysctl_events_retry_timeout); - add_timer(&ct->timeout); + add_timer(&ecache->timeout); } EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list); -- GitLab From 0fc58b2ff3f70a6bcfac562c68ec62939c37268a Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Mon, 7 May 2012 02:35:44 +0000 Subject: [PATCH 0782/1799] netfilter: ipset: fix timeout value overflow bug commit 127f559127f5175e4bec3dab725a34845d956591 upstream. Large timeout parameters could result wrong timeout values due to an overflow at msec to jiffies conversion (reported by Andreas Herz) [ This patch was mangled by Pablo Neira Ayuso since David Laight and Eric Dumazet noticed that we were using hardcoded 1000 instead of MSEC_PER_SEC to calculate the timeout ] Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso Acked-by: David Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/netfilter/ipset/ip_set_timeout.h | 4 ++++ net/netfilter/xt_set.c | 15 +++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h index 47923205a4ad..41d9cfa08167 100644 --- a/include/linux/netfilter/ipset/ip_set_timeout.h +++ b/include/linux/netfilter/ipset/ip_set_timeout.h @@ -30,6 +30,10 @@ ip_set_timeout_uget(struct nlattr *tb) { unsigned int timeout = ip_set_get_h32(tb); + /* Normalize to fit into jiffies */ + if (timeout > UINT_MAX/MSEC_PER_SEC) + timeout = UINT_MAX/MSEC_PER_SEC; + /* Userspace supplied TIMEOUT parameter: adjust crazy size */ return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout; } diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c index 0ec8138aa470..035960ec5cb9 100644 --- a/net/netfilter/xt_set.c +++ b/net/netfilter/xt_set.c @@ -44,6 +44,14 @@ const struct ip_set_adt_opt n = { \ .cmdflags = cfs, \ .timeout = t, \ } +#define ADT_MOPT(n, f, d, fs, cfs, t) \ +struct ip_set_adt_opt n = { \ + .family = f, \ + .dim = d, \ + .flags = fs, \ + .cmdflags = cfs, \ + .timeout = t, \ +} /* Revision 0 interface: backward compatible with netfilter/iptables */ @@ -296,11 +304,14 @@ static unsigned int set_target_v2(struct sk_buff *skb, const struct xt_action_param *par) { const struct xt_set_info_target_v2 *info = par->targinfo; - ADT_OPT(add_opt, par->family, info->add_set.dim, - info->add_set.flags, info->flags, info->timeout); + ADT_MOPT(add_opt, par->family, info->add_set.dim, + info->add_set.flags, info->flags, info->timeout); ADT_OPT(del_opt, par->family, info->del_set.dim, info->del_set.flags, 0, UINT_MAX); + /* Normalize to fit into jiffies */ + if (add_opt.timeout > UINT_MAX/MSEC_PER_SEC) + add_opt.timeout = UINT_MAX/MSEC_PER_SEC; if (info->add_set.index != IPSET_INVALID_ID) ip_set_add(info->add_set.index, skb, par, &add_opt); if (info->del_set.index != IPSET_INVALID_ID) -- GitLab From 285ff6c4a762f556275182bcef767b61174c0424 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Fri, 29 Jun 2012 09:42:28 +0000 Subject: [PATCH 0783/1799] netfilter: ipset: timeout fixing bug broke SET target special timeout value commit a73f89a61f92b364f0b4a3be412b5b70553afc23 upstream. The patch "127f559 netfilter: ipset: fix timeout value overflow bug" broke the SET target when no timeout was specified. Reported-by: Jean-Philippe Menil Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso Acked-by: David Miller Signed-off-by: Greg Kroah-Hartman --- net/netfilter/xt_set.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c index 035960ec5cb9..c6f7db720d84 100644 --- a/net/netfilter/xt_set.c +++ b/net/netfilter/xt_set.c @@ -16,6 +16,7 @@ #include #include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); @@ -310,7 +311,8 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par) info->del_set.flags, 0, UINT_MAX); /* Normalize to fit into jiffies */ - if (add_opt.timeout > UINT_MAX/MSEC_PER_SEC) + if (add_opt.timeout != IPSET_NO_TIMEOUT && + add_opt.timeout > UINT_MAX/MSEC_PER_SEC) add_opt.timeout = UINT_MAX/MSEC_PER_SEC; if (info->add_set.index != IPSET_INVALID_ID) ip_set_add(info->add_set.index, skb, par, &add_opt); -- GitLab From 0b0ea6a363eb3f5802adcb07c8c23e052a10d6bb Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Sat, 7 Jul 2012 18:26:10 +0800 Subject: [PATCH 0784/1799] ipvs: fix oops on NAT reply in br_nf context commit 9e33ce453f8ac8452649802bee1f410319408f4b upstream. IPVS should not reset skb->nf_bridge in FORWARD hook by calling nf_reset for NAT replies. It triggers oops in br_nf_forward_finish. [ 579.781508] BUG: unable to handle kernel NULL pointer dereference at 0000000000000004 [ 579.781669] IP: [] br_nf_forward_finish+0x58/0x112 [ 579.781792] PGD 218f9067 PUD 0 [ 579.781865] Oops: 0000 [#1] SMP [ 579.781945] CPU 0 [ 579.781983] Modules linked in: [ 579.782047] [ 579.782080] [ 579.782114] Pid: 4644, comm: qemu Tainted: G W 3.5.0-rc5-00006-g95e69f9 #282 Hewlett-Packard /30E8 [ 579.782300] RIP: 0010:[] [] br_nf_forward_finish+0x58/0x112 [ 579.782455] RSP: 0018:ffff88007b003a98 EFLAGS: 00010287 [ 579.782541] RAX: 0000000000000008 RBX: ffff8800762ead00 RCX: 000000000001670a [ 579.782653] RDX: 0000000000000000 RSI: 000000000000000a RDI: ffff8800762ead00 [ 579.782845] RBP: ffff88007b003ac8 R08: 0000000000016630 R09: ffff88007b003a90 [ 579.782957] R10: ffff88007b0038e8 R11: ffff88002da37540 R12: ffff88002da01a02 [ 579.783066] R13: ffff88002da01a80 R14: ffff88002d83c000 R15: ffff88002d82a000 [ 579.783177] FS: 0000000000000000(0000) GS:ffff88007b000000(0063) knlGS:00000000f62d1b70 [ 579.783306] CS: 0010 DS: 002b ES: 002b CR0: 000000008005003b [ 579.783395] CR2: 0000000000000004 CR3: 00000000218fe000 CR4: 00000000000027f0 [ 579.783505] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 579.783684] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 579.783795] Process qemu (pid: 4644, threadinfo ffff880021b20000, task ffff880021aba760) [ 579.783919] Stack: [ 579.783959] ffff88007693cedc ffff8800762ead00 ffff88002da01a02 ffff8800762ead00 [ 579.784110] ffff88002da01a02 ffff88002da01a80 ffff88007b003b18 ffffffff817b26c7 [ 579.784260] ffff880080000000 ffffffff81ef59f0 ffff8800762ead00 ffffffff81ef58b0 [ 579.784477] Call Trace: [ 579.784523] [ 579.784562] [ 579.784603] [] br_nf_forward_ip+0x275/0x2c8 [ 579.784707] [] nf_iterate+0x47/0x7d [ 579.784797] [] ? br_dev_queue_push_xmit+0xae/0xae [ 579.784906] [] nf_hook_slow+0x6d/0x102 [ 579.784995] [] ? br_dev_queue_push_xmit+0xae/0xae [ 579.785175] [] ? _raw_write_unlock_bh+0x19/0x1b [ 579.785179] [] __br_forward+0x97/0xa2 [ 579.785179] [] br_handle_frame_finish+0x1a6/0x257 [ 579.785179] [] br_nf_pre_routing_finish+0x26d/0x2cb [ 579.785179] [] br_nf_pre_routing+0x55d/0x5c1 [ 579.785179] [] nf_iterate+0x47/0x7d [ 579.785179] [] ? br_handle_local_finish+0x44/0x44 [ 579.785179] [] nf_hook_slow+0x6d/0x102 [ 579.785179] [] ? br_handle_local_finish+0x44/0x44 [ 579.785179] [] ? sky2_poll+0xb35/0xb54 [ 579.785179] [] br_handle_frame+0x213/0x229 [ 579.785179] [] ? br_handle_frame_finish+0x257/0x257 [ 579.785179] [] __netif_receive_skb+0x2b4/0x3f1 [ 579.785179] [] process_backlog+0x99/0x1e2 [ 579.785179] [] net_rx_action+0xdf/0x242 [ 579.785179] [] __do_softirq+0xc1/0x1e0 [ 579.785179] [] ? trace_hardirqs_off_thunk+0x3a/0x6c [ 579.785179] [] call_softirq+0x1c/0x30 The steps to reproduce as follow, 1. On Host1, setup brige br0(192.168.1.106) 2. Boot a kvm guest(192.168.1.105) on Host1 and start httpd 3. Start IPVS service on Host1 ipvsadm -A -t 192.168.1.106:80 -s rr ipvsadm -a -t 192.168.1.106:80 -r 192.168.1.105:80 -m 4. Run apache benchmark on Host2(192.168.1.101) ab -n 1000 http://192.168.1.106/ ip_vs_reply4 ip_vs_out handle_response ip_vs_notrack nf_reset() { skb->nf_bridge = NULL; } Actually, IPVS wants in this case just to replace nfct with untracked version. So replace the nf_reset(skb) call in ip_vs_notrack() with a nf_conntrack_put(skb->nfct) call. Signed-off-by: Lin Ming Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman Signed-off-by: Pablo Neira Ayuso Acked-by: David Miller Signed-off-by: Greg Kroah-Hartman --- include/net/ip_vs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 72522f087375..2389959464c3 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -1356,7 +1356,7 @@ static inline void ip_vs_notrack(struct sk_buff *skb) struct nf_conn *ct = nf_ct_get(skb, &ctinfo); if (!ct || !nf_ct_is_untracked(ct)) { - nf_reset(skb); + nf_conntrack_put(skb->nfct); skb->nfct = &nf_ct_untracked_get()->ct_general; skb->nfctinfo = IP_CT_NEW; nf_conntrack_get(skb->nfct); -- GitLab From 6ebe631c590aa6c5e61ccec9ab1808f99705f9d5 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 29 Aug 2012 15:24:09 +0000 Subject: [PATCH 0785/1799] netfilter: nf_nat_sip: fix incorrect handling of EBUSY for RTCP expectation commit 3f509c689a07a4aa989b426893d8491a7ffcc410 upstream. We're hitting bug while trying to reinsert an already existing expectation: kernel BUG at kernel/timer.c:895! invalid opcode: 0000 [#1] SMP [...] Call Trace: [] nf_ct_expect_related_report+0x4a0/0x57a [nf_conntrack] [] ? in4_pton+0x72/0x131 [] ip_nat_sdp_media+0xeb/0x185 [nf_nat_sip] [] set_expected_rtp_rtcp+0x32d/0x39b [nf_conntrack_sip] [] process_sdp+0x30c/0x3ec [nf_conntrack_sip] [] ? irq_exit+0x9a/0x9c [] ? ip_nat_sdp_media+0x185/0x185 [nf_nat_sip] We have to remove the RTP expectation if the RTCP expectation hits EBUSY since we keep trying with other ports until we succeed. Reported-by: Rafal Fitt Acked-by: David Miller Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/ipv4/netfilter/nf_nat_sip.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index 57932c43960e..0ba0394bb2c8 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -501,7 +501,10 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff, ret = nf_ct_expect_related(rtcp_exp); if (ret == 0) break; - else if (ret != -EBUSY) { + else if (ret == -EBUSY) { + nf_ct_unexpect_related(rtp_exp); + continue; + } else if (ret < 0) { nf_ct_unexpect_related(rtp_exp); port = 0; break; -- GitLab From 7ea0513ee0bc8c8e85ade576caaf13a58b2cb55d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 9 Aug 2012 10:08:47 +0000 Subject: [PATCH 0786/1799] netfilter: nf_nat_sip: fix via header translation with multiple parameters commit f22eb25cf5b1157b29ef88c793b71972efc47143 upstream. Via-headers are parsed beginning at the first character after the Via-address. When the address is translated first and its length decreases, the offset to start parsing at is incorrect and header parameters might be missed. Update the offset after translating the Via-address to fix this. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso Acked-by: David Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/netfilter/nf_nat_sip.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index 0ba0394bb2c8..566be2dd73f4 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -148,7 +148,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, hdr, NULL, &matchoff, &matchlen, &addr, &port) > 0) { - unsigned int matchend, poff, plen, buflen, n; + unsigned int olen, matchend, poff, plen, buflen, n; char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; /* We're only interested in headers related to this @@ -163,11 +163,12 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, goto next; } + olen = *datalen; if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, &addr, port)) return NF_DROP; - matchend = matchoff + matchlen; + matchend = matchoff + matchlen + *datalen - olen; /* The maddr= parameter (RFC 2361) specifies where to send * the reply. */ -- GitLab From 29f0d1b362fcdcd7bb3071782184f4035d5784bd Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 16 Aug 2012 02:25:24 +0200 Subject: [PATCH 0787/1799] netfilter: nf_ct_expect: fix possible access to uninitialized timer commit 2614f86490122bf51eb7c12ec73927f1900f4e7d upstream. In __nf_ct_expect_check, the function refresh_timer returns 1 if a matching expectation is found and its timer is successfully refreshed. This results in nf_ct_expect_related returning 0. Note that at this point: - the passed expectation is not inserted in the expectation table and its timer was not initialized, since we have refreshed one matching/existing expectation. - nf_ct_expect_alloc uses kmem_cache_alloc, so the expectation timer is in some undefined state just after the allocation, until it is appropriately initialized. This can be a problem for the SIP helper during the expectation addition: ... if (nf_ct_expect_related(rtp_exp) == 0) { if (nf_ct_expect_related(rtcp_exp) != 0) nf_ct_unexpect_related(rtp_exp); ... Note that nf_ct_expect_related(rtp_exp) may return 0 for the timer refresh case that is detailed above. Then, if nf_ct_unexpect_related(rtcp_exp) returns != 0, nf_ct_unexpect_related(rtp_exp) is called, which does: spin_lock_bh(&nf_conntrack_lock); if (del_timer(&exp->timeout)) { nf_ct_unlink_expect(exp); nf_ct_expect_put(exp); } spin_unlock_bh(&nf_conntrack_lock); Note that del_timer always returns false if the timer has been initialized. However, the timer was not initialized since setup_timer was not called, therefore, the expectation timer remains in some undefined state. If I'm not missing anything, this may lead to the removal an unexistent expectation. To fix this, the optimization that allows refreshing an expectation is removed. Now nf_conntrack_expect_related looks more consistent to me since it always add the expectation in case that it returns success. Thanks to Patrick McHardy for participating in the discussion of this patch. I think this may be the source of the problem described by: http://marc.info/?l=netfilter-devel&m=134073514719421&w=2 Reported-by: Rafal Fitt Acked-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso Acked-by: David Miller Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_conntrack_expect.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 4147ba3f653c..e41ec849120a 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -361,23 +361,6 @@ static void evict_oldest_expect(struct nf_conn *master, } } -static inline int refresh_timer(struct nf_conntrack_expect *i) -{ - struct nf_conn_help *master_help = nfct_help(i->master); - const struct nf_conntrack_expect_policy *p; - - if (!del_timer(&i->timeout)) - return 0; - - p = &rcu_dereference_protected( - master_help->helper, - lockdep_is_held(&nf_conntrack_lock) - )->expect_policy[i->class]; - i->timeout.expires = jiffies + p->timeout * HZ; - add_timer(&i->timeout); - return 1; -} - static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) { const struct nf_conntrack_expect_policy *p; @@ -386,7 +369,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) struct nf_conn_help *master_help = nfct_help(master); struct nf_conntrack_helper *helper; struct net *net = nf_ct_exp_net(expect); - struct hlist_node *n; + struct hlist_node *n, *next; unsigned int h; int ret = 1; @@ -395,12 +378,12 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) goto out; } h = nf_ct_expect_dst_hash(&expect->tuple); - hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) { + hlist_for_each_entry_safe(i, n, next, &net->ct.expect_hash[h], hnode) { if (expect_matches(i, expect)) { - /* Refresh timer: if it's dying, ignore.. */ - if (refresh_timer(i)) { - ret = 0; - goto out; + if (del_timer(&i->timeout)) { + nf_ct_unlink_expect(i); + nf_ct_expect_put(i); + break; } } else if (expect_clash(i, expect)) { ret = -EBUSY; -- GitLab From aee054fb840f6fca8067a42f44df0e2a22e0378c Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 7 May 2012 10:51:43 +0000 Subject: [PATCH 0788/1799] netfilter: limit, hashlimit: avoid duplicated inline commit 7a909ac70f6b0823d9f23a43f19598d4b57ac901 upstream. credit_cap can be set to credit, which avoids inlining user2credits twice. Also, remove inline keyword and let compiler decide. old: 684 192 0 876 36c net/netfilter/xt_limit.o 4927 344 32 5303 14b7 net/netfilter/xt_hashlimit.o now: 668 192 0 860 35c net/netfilter/xt_limit.o 4793 344 32 5169 1431 net/netfilter/xt_hashlimit.o Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Acked-by: David Miller Signed-off-by: Greg Kroah-Hartman --- net/netfilter/xt_hashlimit.c | 8 +++----- net/netfilter/xt_limit.c | 5 ++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index d95f9c963cde..2195eb0727a3 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -389,8 +389,7 @@ static void htable_put(struct xt_hashlimit_htable *hinfo) #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) /* Precision saver. */ -static inline u_int32_t -user2credits(u_int32_t user) +static u32 user2credits(u32 user) { /* If multiplying would overflow... */ if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) @@ -400,7 +399,7 @@ user2credits(u_int32_t user) return (user * HZ * CREDITS_PER_JIFFY) / XT_HASHLIMIT_SCALE; } -static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now) +static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now) { dh->rateinfo.credit += (now - dh->rateinfo.prev) * CREDITS_PER_JIFFY; if (dh->rateinfo.credit > dh->rateinfo.credit_cap) @@ -535,8 +534,7 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par) dh->rateinfo.prev = jiffies; dh->rateinfo.credit = user2credits(hinfo->cfg.avg * hinfo->cfg.burst); - dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * - hinfo->cfg.burst); + dh->rateinfo.credit_cap = dh->rateinfo.credit; dh->rateinfo.cost = user2credits(hinfo->cfg.avg); } else { /* update expiration timeout */ diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c index 32b7a579a032..5c22ce8ab309 100644 --- a/net/netfilter/xt_limit.c +++ b/net/netfilter/xt_limit.c @@ -88,8 +88,7 @@ limit_mt(const struct sk_buff *skb, struct xt_action_param *par) } /* Precision saver. */ -static u_int32_t -user2credits(u_int32_t user) +static u32 user2credits(u32 user) { /* If multiplying would overflow... */ if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) @@ -123,7 +122,7 @@ static int limit_mt_check(const struct xt_mtchk_param *par) 128. */ priv->prev = jiffies; priv->credit = user2credits(r->avg * r->burst); /* Credits full. */ - r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ + r->credit_cap = priv->credit; /* Credits full. */ r->cost = user2credits(r->avg); } return 0; -- GitLab From 7ae3bb7d050f8c7e3ef46c830968f3bb5ca2e232 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 21 Sep 2012 22:26:52 +0000 Subject: [PATCH 0789/1799] netfilter: xt_limit: have r->cost != 0 case work commit 82e6bfe2fbc4d48852114c4f979137cd5bf1d1a8 upstream. Commit v2.6.19-rc1~1272^2~41 tells us that r->cost != 0 can happen when a running state is saved to userspace and then reinstated from there. Make sure that private xt_limit area is initialized with correct values. Otherwise, random matchings due to use of uninitialized memory. Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso Acked-by: David Miller Signed-off-by: Greg Kroah-Hartman --- net/netfilter/xt_limit.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c index 5c22ce8ab309..a4c1e4528cac 100644 --- a/net/netfilter/xt_limit.c +++ b/net/netfilter/xt_limit.c @@ -117,11 +117,11 @@ static int limit_mt_check(const struct xt_mtchk_param *par) /* For SMP, we only want to use one set of state. */ r->master = priv; + /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * + 128. */ + priv->prev = jiffies; + priv->credit = user2credits(r->avg * r->burst); /* Credits full. */ if (r->cost == 0) { - /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * - 128. */ - priv->prev = jiffies; - priv->credit = user2credits(r->avg * r->burst); /* Credits full. */ r->credit_cap = priv->credit; /* Credits full. */ r->cost = user2credits(r->avg); } -- GitLab From 525383548a58de3cf3c1f35abfebed453d3d190c Mon Sep 17 00:00:00 2001 From: Jean-Christian de Rivaz Date: Wed, 10 Oct 2012 12:49:02 +0000 Subject: [PATCH 0790/1799] Add CDC-ACM support for the CX93010-2x UCMxx USB Modem commit e7d491a19d3e3aac544070293891a2542ae0c565 upstream. This USB V.92/V.32bis Controllered Modem have the USB vendor ID 0x0572 and device ID 0x1340. It need the NO_UNION_NORMAL quirk to be recognized. Reference: http://www.conexant.com/servlets/DownloadServlet/DSH-201723-005.pdf?docid=1725&revid=5 See idVendor and idProduct in table 6-1. Device Descriptors Signed-off-by: Jean-Christian de Rivaz Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 1b632cb88acf..7f2fac162a7e 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1551,6 +1551,9 @@ static const struct usb_device_id acm_ids[] = { Maybe we should define a new quirk for this. */ }, + { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ + .driver_info = NO_UNION_NORMAL, + }, { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ }, -- GitLab From ab8cd49a6e1984398984e1657f7b6787c37a9a45 Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Mon, 15 Oct 2012 08:21:39 +0200 Subject: [PATCH 0791/1799] drm/radeon: Don't destroy I2C Bus Rec in radeon_ext_tmds_enc_destroy(). commit 082918471139b07964967cfe5f70230909c82ae1 upstream. radeon_i2c_fini() walks thru the list of I2C bus recs rdev->i2c_bus[] to destroy each of them. radeon_ext_tmds_enc_destroy() however also has code to destroy it's associated I2C bus rec which has been obtained by radeon_i2c_lookup() and is therefore also in the i2c_bus[] list. This causes a double free resulting in a kernel panic when unloading the radeon driver. Removing destroy code from radeon_ext_tmds_enc_destroy() fixes this problem. agd5f: fix compiler warning Signed-off-by: Egbert Eich Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 42db254f6bb0..1461e2ce359e 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -973,11 +973,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv; - if (tmds) { - if (tmds->i2c_bus) - radeon_i2c_destroy(tmds->i2c_bus); - } + /* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */ kfree(radeon_encoder->enc_priv); drm_encoder_cleanup(encoder); kfree(radeon_encoder); -- GitLab From 6a52f3c682cf4c191885d1029449d68fd60b40e6 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 26 Sep 2012 18:43:10 +0300 Subject: [PATCH 0792/1799] drm/i915: use adjusted_mode instead of mode for checking the 6bpc force flag commit 0c96c65b48fba3ffe9822a554cbc0cd610765cd5 upstream. The dithering introduced in commit 3b5c78a35cf7511c15e09a9b0ffab290a42d9bcf Author: Adam Jackson Date: Tue Dec 13 15:41:00 2011 -0800 drm/i915/dp: Dither down to 6bpc if it makes the mode fit stores the INTEL_MODE_DP_FORCE_6BPC flag in the private_flags of the adjusted mode, while i9xx_crtc_mode_set() and ironlake_crtc_mode_set() use the original mode, without the flag, so it would never have any effect. However, the BPC was clamped by VBT settings, making things work by coincidence, until that part was removed in commit 4344b813f105a19f793f1fd93ad775b784648b95 Author: Daniel Vetter Date: Fri Aug 10 11:10:20 2012 +0200 Use adjusted_mode instead of mode when checking for INTEL_MODE_DP_FORCE_6BPC to make the flag have effect. v2: Don't forget to fix this in i9xx_crtc_mode_set() also, pointed out by Daniel both before and after sending the first patch. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47621 CC: Adam Jackson Signed-off-by: Jani Nikula Reviewed-by: Adam Jackson Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 498bcbeb992f..f3b06f04e011 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5318,7 +5318,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, /* default to 8bpc */ pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN); if (is_dp) { - if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { + if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { pipeconf |= PIPECONF_BPP_6 | PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP; @@ -5782,7 +5782,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, /* determine panel color depth */ temp = I915_READ(PIPECONF(pipe)); temp &= ~PIPE_BPC_MASK; - dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode); + dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, adjusted_mode); switch (pipe_bpp) { case 18: temp |= PIPE_6BPC; -- GitLab From ea05dc56faeea5a3e0eaafe6de9fae196ed7f036 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 11 Jul 2012 23:16:25 +0200 Subject: [PATCH 0793/1799] jbd: Fix assertion failure in commit code due to lacking transaction credits commit 09e05d4805e6c524c1af74e524e5d0528bb3fef3 upstream. ext3 users of data=journal mode with blocksize < pagesize were occasionally hitting assertion failure in journal_commit_transaction() checking whether the transaction has at least as many credits reserved as buffers attached. The core of the problem is that when a file gets truncated, buffers that still need checkpointing or that are attached to the committing transaction are left with buffer_mapped set. When this happens to buffers beyond i_size attached to a page stradding i_size, subsequent write extending the file will see these buffers and as they are mapped (but underlying blocks were freed) things go awry from here. The assertion failure just coincidentally (and in this case luckily as we would start corrupting filesystem) triggers due to journal_head not being properly cleaned up as well. Under some rare circumstances this bug could even hit data=ordered mode users. There the assertion won't trigger and we would end up corrupting the filesystem. We fix the problem by unmapping buffers if possible (in lots of cases we just need a buffer attached to a transaction as a place holder but it must not be written out anyway). And in one case, we just have to bite the bullet and wait for transaction commit to finish. Reviewed-by: Josef Bacik Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/jbd/commit.c | 45 +++++++++++++++++++++++-------- fs/jbd/transaction.c | 64 ++++++++++++++++++++++++++++++-------------- 2 files changed, 78 insertions(+), 31 deletions(-) diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index f2b9a571f4cf..9626bc8cbbd4 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -86,7 +86,12 @@ static void release_buffer_page(struct buffer_head *bh) static void release_data_buffer(struct buffer_head *bh) { if (buffer_freed(bh)) { + WARN_ON_ONCE(buffer_dirty(bh)); clear_buffer_freed(bh); + clear_buffer_mapped(bh); + clear_buffer_new(bh); + clear_buffer_req(bh); + bh->b_bdev = NULL; release_buffer_page(bh); } else put_bh(bh); @@ -853,17 +858,35 @@ void journal_commit_transaction(journal_t *journal) * there's no point in keeping a checkpoint record for * it. */ - /* A buffer which has been freed while still being - * journaled by a previous transaction may end up still - * being dirty here, but we want to avoid writing back - * that buffer in the future after the "add to orphan" - * operation been committed, That's not only a performance - * gain, it also stops aliasing problems if the buffer is - * left behind for writeback and gets reallocated for another - * use in a different page. */ - if (buffer_freed(bh) && !jh->b_next_transaction) { - clear_buffer_freed(bh); - clear_buffer_jbddirty(bh); + /* + * A buffer which has been freed while still being journaled by + * a previous transaction. + */ + if (buffer_freed(bh)) { + /* + * If the running transaction is the one containing + * "add to orphan" operation (b_next_transaction != + * NULL), we have to wait for that transaction to + * commit before we can really get rid of the buffer. + * So just clear b_modified to not confuse transaction + * credit accounting and refile the buffer to + * BJ_Forget of the running transaction. If the just + * committed transaction contains "add to orphan" + * operation, we can completely invalidate the buffer + * now. We are rather throughout in that since the + * buffer may be still accessible when blocksize < + * pagesize and it is attached to the last partial + * page. + */ + jh->b_modified = 0; + if (!jh->b_next_transaction) { + clear_buffer_freed(bh); + clear_buffer_jbddirty(bh); + clear_buffer_mapped(bh); + clear_buffer_new(bh); + clear_buffer_req(bh); + bh->b_bdev = NULL; + } } if (buffer_jbddirty(bh)) { diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index b2a7e5244e39..841cabc94df8 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1845,15 +1845,16 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction) * We're outside-transaction here. Either or both of j_running_transaction * and j_committing_transaction may be NULL. */ -static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) +static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh, + int partial_page) { transaction_t *transaction; struct journal_head *jh; int may_free = 1; - int ret; BUFFER_TRACE(bh, "entry"); +retry: /* * It is safe to proceed here without the j_list_lock because the * buffers cannot be stolen by try_to_free_buffers as long as we are @@ -1881,10 +1882,18 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * clear the buffer dirty bit at latest at the moment when the * transaction marking the buffer as freed in the filesystem * structures is committed because from that moment on the - * buffer can be reallocated and used by a different page. + * block can be reallocated and used by a different page. * Since the block hasn't been freed yet but the inode has * already been added to orphan list, it is safe for us to add * the buffer to BJ_Forget list of the newest transaction. + * + * Also we have to clear buffer_mapped flag of a truncated buffer + * because the buffer_head may be attached to the page straddling + * i_size (can happen only when blocksize < pagesize) and thus the + * buffer_head can be reused when the file is extended again. So we end + * up keeping around invalidated buffers attached to transactions' + * BJ_Forget list just to stop checkpointing code from cleaning up + * the transaction this buffer was modified in. */ transaction = jh->b_transaction; if (transaction == NULL) { @@ -1911,13 +1920,9 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * committed, the buffer won't be needed any * longer. */ JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget"); - ret = __dispose_buffer(jh, + may_free = __dispose_buffer(jh, journal->j_running_transaction); - journal_put_journal_head(jh); - spin_unlock(&journal->j_list_lock); - jbd_unlock_bh_state(bh); - spin_unlock(&journal->j_state_lock); - return ret; + goto zap_buffer; } else { /* There is no currently-running transaction. So the * orphan record which we wrote for this file must have @@ -1925,13 +1930,9 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * the committing transaction, if it exists. */ if (journal->j_committing_transaction) { JBUFFER_TRACE(jh, "give to committing trans"); - ret = __dispose_buffer(jh, + may_free = __dispose_buffer(jh, journal->j_committing_transaction); - journal_put_journal_head(jh); - spin_unlock(&journal->j_list_lock); - jbd_unlock_bh_state(bh); - spin_unlock(&journal->j_state_lock); - return ret; + goto zap_buffer; } else { /* The orphan record's transaction has * committed. We can cleanse this buffer */ @@ -1952,10 +1953,24 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) } /* * The buffer is committing, we simply cannot touch - * it. So we just set j_next_transaction to the - * running transaction (if there is one) and mark - * buffer as freed so that commit code knows it should - * clear dirty bits when it is done with the buffer. + * it. If the page is straddling i_size we have to wait + * for commit and try again. + */ + if (partial_page) { + tid_t tid = journal->j_committing_transaction->t_tid; + + journal_put_journal_head(jh); + spin_unlock(&journal->j_list_lock); + jbd_unlock_bh_state(bh); + spin_unlock(&journal->j_state_lock); + log_wait_commit(journal, tid); + goto retry; + } + /* + * OK, buffer won't be reachable after truncate. We just set + * j_next_transaction to the running transaction (if there is + * one) and mark buffer as freed so that commit code knows it + * should clear dirty bits when it is done with the buffer. */ set_buffer_freed(bh); if (journal->j_running_transaction && buffer_jbddirty(bh)) @@ -1978,6 +1993,14 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) } zap_buffer: + /* + * This is tricky. Although the buffer is truncated, it may be reused + * if blocksize < pagesize and it is attached to the page straddling + * EOF. Since the buffer might have been added to BJ_Forget list of the + * running transaction, journal_get_write_access() won't clear + * b_modified and credit accounting gets confused. So clear b_modified + * here. */ + jh->b_modified = 0; journal_put_journal_head(jh); zap_buffer_no_jh: spin_unlock(&journal->j_list_lock); @@ -2026,7 +2049,8 @@ void journal_invalidatepage(journal_t *journal, if (offset <= curr_off) { /* This block is wholly outside the truncation point */ lock_buffer(bh); - may_free &= journal_unmap_buffer(journal, bh); + may_free &= journal_unmap_buffer(journal, bh, + offset > 0); unlock_buffer(bh); } curr_off = next_off; -- GitLab From f5e37c549d200e3b899b66d6a84e99c8e2cf5e59 Mon Sep 17 00:00:00 2001 From: Hiroaki SHIMODA Date: Wed, 10 Oct 2012 15:34:20 +0000 Subject: [PATCH 0794/1799] e1000e: Change wthresh to 1 to avoid possible Tx stalls commit 8edc0e624db3756783233e464879eb2e3b904c13 upstream. This patch originated from Hiroaki SHIMODA but has been modified by Intel with some minor cleanups and additional commit log text. Denys Fedoryshchenko and others reported Tx stalls on e1000e with BQL enabled. Issue was root caused to hardware delays. They were introduced because some of the e1000e hardware with transmit writeback bursting enabled, waits until the driver does an explict flush OR there are WTHRESH descriptors to write back. Sometimes the delays in question were on the order of seconds, causing visible lag for ssh sessions and unacceptable tx completion latency, especially for BQL enabled kernels. To avoid possible Tx stalls, change WTHRESH back to 1. The current plan is to investigate a method for re-enabling WTHRESH while not harming BQL, but those patches will be later for net-next if they work. please enqueue for stable since v3.3 as this bug was introduced in commit 3f0cfa3bc11e7f00c9994e0f469cbc0e7da7b00c Author: Tom Herbert Date: Mon Nov 28 16:33:16 2011 +0000 e1000e: Support for byte queue limits Changes to e1000e to use byte queue limits. Reported-by: Denys Fedoryshchenko Tested-by: Denys Fedoryshchenko Signed-off-by: Hiroaki SHIMODA CC: eric.dumazet@gmail.com CC: therbert@google.com Signed-off-by: Jesse Brandeburg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/intel/e1000e/e1000.h | 6 +++--- drivers/net/ethernet/intel/e1000e/netdev.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index b83897f76ee3..1ab8067b028b 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -175,13 +175,13 @@ struct e1000_info; /* * in the case of WTHRESH, it appears at least the 82571/2 hardware * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when - * WTHRESH=4, and since we want 64 bytes at a time written back, set - * it to 5 + * WTHRESH=4, so a setting of 5 gives the most efficient bus + * utilization but to avoid possible Tx stalls, set it to 1 */ #define E1000_TXDCTL_DMA_BURST_ENABLE \ (E1000_TXDCTL_GRAN | /* set descriptor granularity */ \ E1000_TXDCTL_COUNT_DESC | \ - (5 << 16) | /* wthresh must be +1 more than desired */\ + (1 << 16) | /* wthresh must be +1 more than desired */\ (1 << 8) | /* hthresh */ \ 0x1f) /* pthresh */ diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 5621d5b28765..7e88aaff6ecc 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -2806,7 +2806,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) * set up some performance related parameters to encourage the * hardware to use the bus more efficiently in bursts, depends * on the tx_int_delay to be enabled, - * wthresh = 5 ==> burst write a cacheline (64 bytes) at a time + * wthresh = 1 ==> burst write is disabled to avoid Tx stalls * hthresh = 1 ==> prefetch when one or more available * pthresh = 0x1f ==> prefetch if internal cache 31 or less * BEWARE: this seems to work but should be considered first if -- GitLab From 8abffa895c8a6c6079e93db68f5eb5e4a2332a82 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 27 Sep 2012 16:09:33 +0200 Subject: [PATCH 0795/1799] tpm: Propagate error from tpm_transmit to fix a timeout hang commit abce9ac292e13da367bbd22c1f7669f988d931ac upstream. tpm_write calls tpm_transmit without checking the return value and assigns the return value unconditionally to chip->pending_data, even if it's an error value. This causes three bugs. So if we write to /dev/tpm0 with a tpm_param_size bigger than TPM_BUFSIZE=0x1000 (e.g. 0x100a) and a bufsize also bigger than TPM_BUFSIZE (e.g. 0x100a) tpm_transmit returns -E2BIG which is assigned to chip->pending_data as -7, but tpm_write returns that TPM_BUFSIZE bytes have been successfully been written to the TPM, altough this is not true (bug #1). As we did write more than than TPM_BUFSIZE bytes but tpm_write reports that only TPM_BUFSIZE bytes have been written the vfs tries to write the remaining bytes (in this case 10 bytes) to the tpm device driver via tpm_write which then blocks at /* cannot perform a write until the read has cleared either via tpm_read or a user_read_timer timeout */ while (atomic_read(&chip->data_pending) != 0) msleep(TPM_TIMEOUT); for 60 seconds, since data_pending is -7 and nobody is able to read it (since tpm_read luckily checks if data_pending is greater than 0) (#bug 2). After that the remaining bytes are written to the TPM which are interpreted by the tpm as a normal command. (bug #3) So if the last bytes of the command stream happen to be a e.g. tpm_force_clear this gets accidentally sent to the TPM. This patch fixes all three bugs, by propagating the error code of tpm_write and returning -E2BIG if the input buffer is too big, since the response from the tpm for a truncated value is bogus anyway. Moreover it returns -EBUSY to userspace if there is a response ready to be read. Signed-off-by: Peter Huewe Signed-off-by: Kent Yoder Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 08427abf5fa5..27f8ddf09d4f 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -1186,17 +1186,20 @@ ssize_t tpm_write(struct file *file, const char __user *buf, size_t size, loff_t *off) { struct tpm_chip *chip = file->private_data; - size_t in_size = size, out_size; + size_t in_size = size; + ssize_t out_size; /* cannot perform a write until the read has cleared - either via tpm_read or a user_read_timer timeout */ - while (atomic_read(&chip->data_pending) != 0) - msleep(TPM_TIMEOUT); - - mutex_lock(&chip->buffer_mutex); + either via tpm_read or a user_read_timer timeout. + This also prevents splitted buffered writes from blocking here. + */ + if (atomic_read(&chip->data_pending) != 0) + return -EBUSY; if (in_size > TPM_BUFSIZE) - in_size = TPM_BUFSIZE; + return -E2BIG; + + mutex_lock(&chip->buffer_mutex); if (copy_from_user (chip->data_buffer, (void __user *) buf, in_size)) { @@ -1206,6 +1209,10 @@ ssize_t tpm_write(struct file *file, const char __user *buf, /* atomic tpm command send and result receive */ out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); + if (out_size < 0) { + mutex_unlock(&chip->buffer_mutex); + return out_size; + } atomic_set(&chip->data_pending, out_size); mutex_unlock(&chip->buffer_mutex); -- GitLab From 4fd441539be925bf3cbbfe88f9371317a952529b Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Tue, 22 May 2012 15:09:50 -0500 Subject: [PATCH 0796/1799] eCryptfs: Unlink lower inode when ecryptfs_create() fails commit 8bc2d3cf612994a960c2e8eaea37f6676f67082a upstream. ecryptfs_create() creates a lower inode, allocates an eCryptfs inode, initializes the eCryptfs inode and cryptographic metadata attached to the inode, and then writes the metadata to the header of the file. If an error was to occur after the lower inode was created, an empty lower file would be left in the lower filesystem. This is a problem because ecryptfs_open() refuses to open any lower files which do not have the appropriate metadata in the file header. This patch properly unlinks the lower inode when an error occurs in the later stages of ecryptfs_create(), reducing the chance that an empty lower file will be left in the lower filesystem. https://launchpad.net/bugs/872905 Signed-off-by: Tyler Hicks Cc: John Johansen Cc: Colin Ian King Cc: Jonathan Nieder Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/inode.c | 55 ++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 6f5fb1a0d906..fb4a9d8f225e 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -143,6 +143,31 @@ static int ecryptfs_interpose(struct dentry *lower_dentry, return 0; } +static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry, + struct inode *inode) +{ + struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); + struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir); + struct dentry *lower_dir_dentry; + int rc; + + dget(lower_dentry); + lower_dir_dentry = lock_parent(lower_dentry); + rc = vfs_unlink(lower_dir_inode, lower_dentry); + if (rc) { + printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); + goto out_unlock; + } + fsstack_copy_attr_times(dir, lower_dir_inode); + set_nlink(inode, ecryptfs_inode_to_lower(inode)->i_nlink); + inode->i_ctime = dir->i_ctime; + d_drop(dentry); +out_unlock: + unlock_dir(lower_dir_dentry); + dput(lower_dentry); + return rc; +} + /** * ecryptfs_do_create * @directory_inode: inode of the new file's dentry's parent in ecryptfs @@ -182,8 +207,10 @@ ecryptfs_do_create(struct inode *directory_inode, } inode = __ecryptfs_get_inode(lower_dentry->d_inode, directory_inode->i_sb); - if (IS_ERR(inode)) + if (IS_ERR(inode)) { + vfs_unlink(lower_dir_dentry->d_inode, lower_dentry); goto out_lock; + } fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode); out_lock: @@ -265,7 +292,9 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, * that this on disk file is prepared to be an ecryptfs file */ rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode); if (rc) { - drop_nlink(ecryptfs_inode); + ecryptfs_do_unlink(directory_inode, ecryptfs_dentry, + ecryptfs_inode); + make_bad_inode(ecryptfs_inode); unlock_new_inode(ecryptfs_inode); iput(ecryptfs_inode); goto out; @@ -477,27 +506,7 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir, static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry) { - int rc = 0; - struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); - struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir); - struct dentry *lower_dir_dentry; - - dget(lower_dentry); - lower_dir_dentry = lock_parent(lower_dentry); - rc = vfs_unlink(lower_dir_inode, lower_dentry); - if (rc) { - printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); - goto out_unlock; - } - fsstack_copy_attr_times(dir, lower_dir_inode); - set_nlink(dentry->d_inode, - ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink); - dentry->d_inode->i_ctime = dir->i_ctime; - d_drop(dentry); -out_unlock: - unlock_dir(lower_dir_dentry); - dput(lower_dentry); - return rc; + return ecryptfs_do_unlink(dir, dentry, dentry->d_inode); } static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry, -- GitLab From 47bd3aa366784c052e7e9a1acf80cd8c8e9df10b Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 20 Jun 2012 23:50:59 -0700 Subject: [PATCH 0797/1799] eCryptfs: Initialize empty lower files when opening them commit e3ccaa9761200952cc269b1f4b7d7bb77a5e071b upstream. Historically, eCryptfs has only initialized lower files in the ecryptfs_create() path. Lower file initialization is the act of writing the cryptographic metadata from the inode's crypt_stat to the header of the file. The ecryptfs_open() path already expects that metadata to be in the header of the file. A number of users have reported empty lower files in beneath their eCryptfs mounts. Most of the causes for those empty files being left around have been addressed, but the presence of empty files causes problems due to the lack of proper cryptographic metadata. To transparently solve this problem, this patch initializes empty lower files in the ecryptfs_open() error path. If the metadata is unreadable due to the lower inode size being 0, plaintext passthrough support is not in use, and the metadata is stored in the header of the file (as opposed to the user.ecryptfs extended attribute), the lower file will be initialized. The number of nested conditionals in ecryptfs_open() was getting out of hand, so a helper function was created. To avoid the same nested conditional problem, the conditional logic was reversed inside of the helper function. https://launchpad.net/bugs/911507 Signed-off-by: Tyler Hicks Cc: John Johansen Cc: Colin Ian King Cc: Jonathan Nieder Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/ecryptfs_kernel.h | 2 + fs/ecryptfs/file.c | 71 ++++++++++++++++++++++------------- fs/ecryptfs/inode.c | 4 +- 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 867b64c5d84f..56e3aa57e188 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -568,6 +568,8 @@ struct ecryptfs_open_req { struct inode *ecryptfs_get_inode(struct inode *lower_inode, struct super_block *sb); void ecryptfs_i_size_init(const char *page_virt, struct inode *inode); +int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, + struct inode *ecryptfs_inode); int ecryptfs_decode_and_decrypt_filename(char **decrypted_name, size_t *decrypted_name_size, struct dentry *ecryptfs_dentry, diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 2b17f2f9b121..baf8b0550391 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -161,6 +161,48 @@ static int ecryptfs_file_mmap(struct file *file, struct vm_area_struct *vma) struct kmem_cache *ecryptfs_file_info_cache; +static int read_or_initialize_metadata(struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct ecryptfs_crypt_stat *crypt_stat; + int rc; + + crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; + mount_crypt_stat = &ecryptfs_superblock_to_private( + inode->i_sb)->mount_crypt_stat; + mutex_lock(&crypt_stat->cs_mutex); + + if (crypt_stat->flags & ECRYPTFS_POLICY_APPLIED && + crypt_stat->flags & ECRYPTFS_KEY_VALID) { + rc = 0; + goto out; + } + + rc = ecryptfs_read_metadata(dentry); + if (!rc) + goto out; + + if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED) { + crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED + | ECRYPTFS_ENCRYPTED); + rc = 0; + goto out; + } + + if (!(mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED) && + !i_size_read(ecryptfs_inode_to_lower(inode))) { + rc = ecryptfs_initialize_file(dentry, inode); + if (!rc) + goto out; + } + + rc = -EIO; +out: + mutex_unlock(&crypt_stat->cs_mutex); + return rc; +} + /** * ecryptfs_open * @inode: inode speciying file to open @@ -236,32 +278,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file) rc = 0; goto out; } - mutex_lock(&crypt_stat->cs_mutex); - if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) - || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { - rc = ecryptfs_read_metadata(ecryptfs_dentry); - if (rc) { - ecryptfs_printk(KERN_DEBUG, - "Valid headers not found\n"); - if (!(mount_crypt_stat->flags - & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { - rc = -EIO; - printk(KERN_WARNING "Either the lower file " - "is not in a valid eCryptfs format, " - "or the key could not be retrieved. " - "Plaintext passthrough mode is not " - "enabled; returning -EIO\n"); - mutex_unlock(&crypt_stat->cs_mutex); - goto out_put; - } - rc = 0; - crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED - | ECRYPTFS_ENCRYPTED); - mutex_unlock(&crypt_stat->cs_mutex); - goto out; - } - } - mutex_unlock(&crypt_stat->cs_mutex); + rc = read_or_initialize_metadata(ecryptfs_dentry); + if (rc) + goto out_put; ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = " "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, (unsigned long long)i_size_read(inode)); diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index fb4a9d8f225e..66bd60f60776 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -227,8 +227,8 @@ ecryptfs_do_create(struct inode *directory_inode, * * Returns zero on success */ -static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, - struct inode *ecryptfs_inode) +int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, + struct inode *ecryptfs_inode) { struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; -- GitLab From 068478a54bcd742e34b80f316472f3b06cacd8c6 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Tue, 3 Jul 2012 16:50:57 -0700 Subject: [PATCH 0798/1799] eCryptfs: Revert to a writethrough cache model commit 821f7494a77627fb1ab539591c57b22cdca702d6 upstream. A change was made about a year ago to get eCryptfs to better utilize its page cache during writes. The idea was to do the page encryption operations during page writeback, rather than doing them when initially writing into the page cache, to reduce the number of page encryption operations during sequential writes. This meant that the encrypted page would only be written to the lower filesystem during page writeback, which was a change from how eCryptfs had previously wrote to the lower filesystem in ecryptfs_write_end(). The change caused a few eCryptfs-internal bugs that were shook out. Unfortunately, more grave side effects have been identified that will force changes outside of eCryptfs. Because the lower filesystem isn't consulted until page writeback, eCryptfs has no way to pass lower write errors (ENOSPC, mainly) back to userspace. Additionaly, it was reported that quotas could be bypassed because of the way eCryptfs may sometimes open the lower filesystem using a privileged kthread. It would be nice to resolve the latest issues, but it is best if the eCryptfs commits be reverted to the old behavior in the meantime. This reverts: 32001d6f "eCryptfs: Flush file in vma close" 5be79de2 "eCryptfs: Flush dirty pages in setattr" 57db4e8d "ecryptfs: modify write path to encrypt page in writepage" Signed-off-by: Tyler Hicks Tested-by: Colin King Cc: Colin King Cc: Thieu Le Cc: Jonathan Nieder Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/file.c | 33 ++------------------------------- fs/ecryptfs/inode.c | 6 ------ fs/ecryptfs/mmap.c | 39 +++++++++++++-------------------------- 3 files changed, 15 insertions(+), 63 deletions(-) diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index baf8b0550391..44ce5c6a541d 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -138,27 +138,6 @@ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir) return rc; } -static void ecryptfs_vma_close(struct vm_area_struct *vma) -{ - filemap_write_and_wait(vma->vm_file->f_mapping); -} - -static const struct vm_operations_struct ecryptfs_file_vm_ops = { - .close = ecryptfs_vma_close, - .fault = filemap_fault, -}; - -static int ecryptfs_file_mmap(struct file *file, struct vm_area_struct *vma) -{ - int rc; - - rc = generic_file_mmap(file, vma); - if (!rc) - vma->vm_ops = &ecryptfs_file_vm_ops; - - return rc; -} - struct kmem_cache *ecryptfs_file_info_cache; static int read_or_initialize_metadata(struct dentry *dentry) @@ -311,15 +290,7 @@ static int ecryptfs_release(struct inode *inode, struct file *file) static int ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) { - int rc = 0; - - rc = generic_file_fsync(file, start, end, datasync); - if (rc) - goto out; - rc = vfs_fsync_range(ecryptfs_file_to_lower(file), start, end, - datasync); -out: - return rc; + return vfs_fsync(ecryptfs_file_to_lower(file), datasync); } static int ecryptfs_fasync(int fd, struct file *file, int flag) @@ -388,7 +359,7 @@ const struct file_operations ecryptfs_main_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = ecryptfs_compat_ioctl, #endif - .mmap = ecryptfs_file_mmap, + .mmap = generic_file_mmap, .open = ecryptfs_open, .flush = ecryptfs_flush, .release = ecryptfs_release, diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 66bd60f60776..11030b2fd3b4 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -1016,12 +1016,6 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) goto out; } - if (S_ISREG(inode->i_mode)) { - rc = filemap_write_and_wait(inode->i_mapping); - if (rc) - goto out; - fsstack_copy_attr_all(inode, lower_inode); - } memcpy(&lower_ia, ia, sizeof(lower_ia)); if (ia->ia_valid & ATTR_FILE) lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index a46b3a8fee1e..bd1d57f98f74 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -66,18 +66,6 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc) { int rc; - /* - * Refuse to write the page out if we are called from reclaim context - * since our writepage() path may potentially allocate memory when - * calling into the lower fs vfs_write() which may in turn invoke - * us again. - */ - if (current->flags & PF_MEMALLOC) { - redirty_page_for_writepage(wbc, page); - rc = 0; - goto out; - } - rc = ecryptfs_encrypt_page(page); if (rc) { ecryptfs_printk(KERN_WARNING, "Error encrypting " @@ -498,7 +486,6 @@ static int ecryptfs_write_end(struct file *file, struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; int rc; - int need_unlock_page = 1; ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" "(page w/ index = [0x%.16lx], to = [%d])\n", index, to); @@ -519,26 +506,26 @@ static int ecryptfs_write_end(struct file *file, "zeros in page with index = [0x%.16lx]\n", index); goto out; } - set_page_dirty(page); - unlock_page(page); - need_unlock_page = 0; + rc = ecryptfs_encrypt_page(page); + if (rc) { + ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper " + "index [0x%.16lx])\n", index); + goto out; + } if (pos + copied > i_size_read(ecryptfs_inode)) { i_size_write(ecryptfs_inode, pos + copied); ecryptfs_printk(KERN_DEBUG, "Expanded file size to " "[0x%.16llx]\n", (unsigned long long)i_size_read(ecryptfs_inode)); - balance_dirty_pages_ratelimited(mapping); - rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); - if (rc) { - printk(KERN_ERR "Error writing inode size to metadata; " - "rc = [%d]\n", rc); - goto out; - } } - rc = copied; + rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); + if (rc) + printk(KERN_ERR "Error writing inode size to metadata; " + "rc = [%d]\n", rc); + else + rc = copied; out: - if (need_unlock_page) - unlock_page(page); + unlock_page(page); page_cache_release(page); return rc; } -- GitLab From e7ba1a13e4c4d315d94afb45e6dfaa7c543d9ba2 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 12 Sep 2012 18:02:46 -0700 Subject: [PATCH 0799/1799] eCryptfs: Write out all dirty pages just before releasing the lower file commit 7149f2558d5b5b988726662fe58b1c388337805b upstream. Fixes a regression caused by: 821f749 eCryptfs: Revert to a writethrough cache model That patch reverted some code (specifically, 32001d6f) that was necessary to properly handle open() -> mmap() -> close() -> dirty pages -> munmap(), because the lower file could be closed before the dirty pages are written out. Rather than reapplying 32001d6f, this approach is a better way of ensuring that the lower file is still open in order to handle writing out the dirty pages. It is called from ecryptfs_release(), while we have a lock on the lower file pointer, just before the lower file gets the final fput() and we overwrite the pointer. https://launchpad.net/bugs/1047261 Signed-off-by: Tyler Hicks Reported-by: Artemy Tregubenko Tested-by: Artemy Tregubenko Tested-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 68954937a071..0f04d2eb9a6a 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -162,6 +162,7 @@ void ecryptfs_put_lower_file(struct inode *inode) inode_info = ecryptfs_inode_to_private(inode); if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count, &inode_info->lower_file_mutex)) { + filemap_write_and_wait(inode->i_mapping); fput(inode_info->lower_file); inode_info->lower_file = NULL; mutex_unlock(&inode_info->lower_file_mutex); -- GitLab From a5b9aa5533324fc9e3c2abe24ef335245473c331 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 12 Sep 2012 18:38:00 -0700 Subject: [PATCH 0800/1799] eCryptfs: Call lower ->flush() from ecryptfs_flush() commit 64e6651dcc10e9d2cc6230208a8e6c2cfd19ae18 upstream. Since eCryptfs only calls fput() on the lower file in ecryptfs_release(), eCryptfs should call the lower filesystem's ->flush() from ecryptfs_flush(). If the lower filesystem implements ->flush(), then eCryptfs should try to flush out any dirty pages prior to calling the lower ->flush(). If the lower filesystem does not implement ->flush(), then eCryptfs has no need to do anything in ecryptfs_flush() since dirty pages are now written out to the lower filesystem in ecryptfs_release(). Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/file.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 44ce5c6a541d..d45ba4568128 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -275,8 +275,14 @@ static int ecryptfs_open(struct inode *inode, struct file *file) static int ecryptfs_flush(struct file *file, fl_owner_t td) { - return file->f_mode & FMODE_WRITE - ? filemap_write_and_wait(file->f_mapping) : 0; + struct file *lower_file = ecryptfs_file_to_lower(file); + + if (lower_file->f_op && lower_file->f_op->flush) { + filemap_write_and_wait(file->f_mapping); + return lower_file->f_op->flush(lower_file, td); + } + + return 0; } static int ecryptfs_release(struct inode *inode, struct file *file) -- GitLab From 7ec51fc74149ac5caafffce2b065e25ef621e2c1 Mon Sep 17 00:00:00 2001 From: Fabio Porcedda Date: Fri, 7 Sep 2012 15:27:42 +0200 Subject: [PATCH 0801/1799] usb: gadget: at91_udc: fix dt support commit 9c6d196d5aa35e07482f23c3e37755e7a82140e0 upstream. Don't fail the initialization check for the platform_data if there is avaiable an associated device tree node. Signed-off-by: Fabio Porcedda Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- 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 9d7bcd910074..be6952e2fc5a 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1735,7 +1735,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev) int retval; struct resource *res; - if (!dev->platform_data) { + if (!dev->platform_data && !pdev->dev.of_node) { /* small (so we copy it) but critical! */ DBG("missing platform_data\n"); return -ENODEV; -- GitLab From bb4e97376e84d98994a5f576e2bd080d3aeee232 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 17 Oct 2012 12:43:44 +0200 Subject: [PATCH 0802/1799] ALSA: hda - Always check array bounds in alc_get_line_out_pfx commit 71aa5ebe36a4e936eff281b375a4707b6a8320f2 upstream. Even when CONFIG_SND_DEBUG is not enabled, we don't want to return an arbitrary memory location when the channel count is larger than we expected. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- 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 94747f8a2493..94b765b31ea4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2665,8 +2665,10 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, return "PCM"; break; } - if (snd_BUG_ON(ch >= ARRAY_SIZE(channel_name))) + if (ch >= ARRAY_SIZE(channel_name)) { + snd_BUG(); return "PCM"; + } return channel_name[ch]; } -- GitLab From e9eeac8fd06a74dfcadac8970b7d5797dab652c1 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 3 Oct 2012 14:33:50 +0200 Subject: [PATCH 0803/1799] ASoC: fsi: don't reschedule DMA from an atomic context commit 57451e437796548d658d03c2c4aab659eafcd799 upstream. shdma doesn't support transfer re-scheduling or triggering from callbacks or from atomic context. The fsi driver issues DMA transfers from a tasklet context, which is a bug. To fix it convert tasklet to a work. Reported-by: Do Q.Thang Tested-by: Do Q.Thang Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/sh/fsi.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 74ed2dffbffd..91b728774dba 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -199,7 +200,7 @@ struct fsi_stream { */ struct dma_chan *chan; struct sh_dmae_slave slave; /* see fsi_handler_init() */ - struct tasklet_struct tasklet; + struct work_struct work; dma_addr_t dma; }; @@ -968,9 +969,9 @@ static dma_addr_t fsi_dma_get_area(struct fsi_stream *io) return io->dma + samples_to_bytes(runtime, io->buff_sample_pos); } -static void fsi_dma_do_tasklet(unsigned long data) +static void fsi_dma_do_work(struct work_struct *work) { - struct fsi_stream *io = (struct fsi_stream *)data; + struct fsi_stream *io = container_of(work, struct fsi_stream, work); struct fsi_priv *fsi = fsi_stream_to_priv(io); struct dma_chan *chan; struct snd_soc_dai *dai; @@ -1023,7 +1024,7 @@ static void fsi_dma_do_tasklet(unsigned long data) * FIXME * * In DMAEngine case, codec and FSI cannot be started simultaneously - * since FSI is using tasklet. + * since FSI is using the scheduler work queue. * Therefore, in capture case, probably FSI FIFO will have got * overflow error in this point. * in that case, DMA cannot start transfer until error was cleared. @@ -1047,7 +1048,7 @@ static bool fsi_dma_filter(struct dma_chan *chan, void *param) static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) { - tasklet_schedule(&io->tasklet); + schedule_work(&io->work); return 0; } @@ -1087,14 +1088,14 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) if (!io->chan) return -EIO; - tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io); + INIT_WORK(&io->work, fsi_dma_do_work); return 0; } static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) { - tasklet_kill(&io->tasklet); + cancel_work_sync(&io->work); fsi_stream_stop(fsi, io); -- GitLab From efd9aa3512ecac932b8b9baebd4ca00c3a44394f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Oct 2012 12:02:48 +0100 Subject: [PATCH 0804/1799] ASoC: wm2200: Use rev A register patches on rev B commit 5ae9eb4cbdfd640269dbd66aa3c92ea8e11cc838 upstream. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm2200.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 32682c1b7cde..58ab97a143db 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2091,6 +2091,7 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c, switch (wm2200->rev) { case 0: + case 1: ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch, ARRAY_SIZE(wm2200_reva_patch)); if (ret != 0) { -- GitLab From eb695eec8d6fc5b757c05c6538346ef04d091055 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Oct 2012 19:10:43 +0100 Subject: [PATCH 0805/1799] ASoC: wm2200: Fix non-inverted OUT2 mute control commit a1b98e12b7f8fad2f0aa3c08a3302bcac7ae1ec7 upstream. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 58ab97a143db..c8bff6da5320 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1028,7 +1028,7 @@ SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L, WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0, digital_tlv), SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT, - WM2200_SPK1R_MUTE_SHIFT, 1, 0), + WM2200_SPK1R_MUTE_SHIFT, 1, 1), }; WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE); -- GitLab From 60dd77abe18a5a3eb21c4041f6ea02b45c421cc5 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 2 Oct 2012 15:31:16 +0300 Subject: [PATCH 0806/1799] ASoC: omap-abe-twl6040: Fix typo of Vibrator commit 034940a6b3afbe79022ab6922dd9d2982b78e6d5 upstream. It is not Vinrator but Vibrator. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/omap/omap-abe-twl6040.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index 93bb8eee22b3..9c2f090167cc 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c @@ -181,7 +181,7 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); - twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); + twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vibrator"); twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); -- GitLab From e503f73ae9607b0d4854a40a2f437cfbee529fa3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Oct 2012 16:43:40 +0200 Subject: [PATCH 0807/1799] ALSA: ac97 - Fix missing NULL check in snd_ac97_cvol_new() commit 733a48e5ae5bf28b046fad984d458c747cbb8c21 upstream. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=44721 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/ac97/ac97_codec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 9473fca9681d..8b0f99688303 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1271,6 +1271,8 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne tmp.index = ac97->num; kctl = snd_ctl_new1(&tmp, ac97); } + if (!kctl) + return -ENOMEM; if (reg >= AC97_PHONE && reg <= AC97_PCM) set_tlv_db_scale(kctl, db_scale_5bit_12db_max); else -- GitLab From a6b5c98460148487422c5ceb5bcc88cfdb0a850f Mon Sep 17 00:00:00 2001 From: Maxim Kachur Date: Wed, 17 Oct 2012 18:18:10 +0200 Subject: [PATCH 0808/1799] ALSA: emu10k1: add chip details for E-mu 1010 PCIe card commit 10f571d09106c3eb85951896522c9650596eff2e upstream. Add chip details for E-mu 1010 PCIe card. It has the same chip as found in E-mu 1010b but it uses different PCI id. Signed-off-by: Maxim Kachur Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/emu10k1/emu10k1_main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 754924081d0a..a78fdf466fa7 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1416,6 +1416,15 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0108_chip = 1, .spk71 = 1, .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */ + /* Tested by Maxim Kachur 17th Oct 2012. */ + /* This is MAEM8986, 0202 is MAEM8980 */ + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40071102, + .driver = "Audigy2", .name = "E-mu 1010 PCIe [MAEM8986]", + .id = "EMU1010", + .emu10k2_chip = 1, + .ca0108_chip = 1, + .spk71 = 1, + .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 PCIe */ /* Tested by James@superbug.co.uk 8th July 2005. */ /* This is MAEM8810, 0202 is MAEM8820 */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, -- GitLab From 553f672df76c6213b9a7e644b1d878204a61e013 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 21 Oct 2012 09:28:17 -0700 Subject: [PATCH 0809/1799] Linux 3.4.15 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d174c84cc738..fe9ea67db868 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 14 +SUBLEVEL = 15 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 4319fd00002630a761fa5559a086f11ed7623006 Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Wed, 10 Oct 2012 01:04:58 -0400 Subject: [PATCH 0810/1799] ext4: race-condition protection for ext4_convert_unwritten_extents_endio commit dee1f973ca341c266229faa5a1a5bb268bed3531 upstream. We assumed that at the time we call ext4_convert_unwritten_extents_endio() extent in question is fully inside [map.m_lblk, map->m_len] because it was already split during submission. But this may not be true due to a race between writeback vs fallocate. If extent in question is larger than requested we will split it again. Special precautions should being done if zeroout required because [map.m_lblk, map->m_len] already contains valid data. Signed-off-by: Dmitry Monakhov Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/extents.c | 57 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 8b384cc3b75a..c21598542585 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -52,6 +52,9 @@ #define EXT4_EXT_MARK_UNINIT1 0x2 /* mark first half uninitialized */ #define EXT4_EXT_MARK_UNINIT2 0x4 /* mark second half uninitialized */ +#define EXT4_EXT_DATA_VALID1 0x8 /* first half contains valid data */ +#define EXT4_EXT_DATA_VALID2 0x10 /* second half contains valid data */ + static int ext4_split_extent(handle_t *handle, struct inode *inode, struct ext4_ext_path *path, @@ -2829,6 +2832,9 @@ static int ext4_split_extent_at(handle_t *handle, unsigned int ee_len, depth; int err = 0; + BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) == + (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)); + ext_debug("ext4_split_extents_at: inode %lu, logical" "block %llu\n", inode->i_ino, (unsigned long long)split); @@ -2887,7 +2893,14 @@ static int ext4_split_extent_at(handle_t *handle, err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { - err = ext4_ext_zeroout(inode, &orig_ex); + if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) { + if (split_flag & EXT4_EXT_DATA_VALID1) + err = ext4_ext_zeroout(inode, ex2); + else + err = ext4_ext_zeroout(inode, ex); + } else + err = ext4_ext_zeroout(inode, &orig_ex); + if (err) goto fix_extent_len; /* update the extent length and mark as initialized */ @@ -2940,12 +2953,13 @@ static int ext4_split_extent(handle_t *handle, uninitialized = ext4_ext_is_uninitialized(ex); if (map->m_lblk + map->m_len < ee_block + ee_len) { - split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? - EXT4_EXT_MAY_ZEROOUT : 0; + split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT; flags1 = flags | EXT4_GET_BLOCKS_PRE_IO; if (uninitialized) split_flag1 |= EXT4_EXT_MARK_UNINIT1 | EXT4_EXT_MARK_UNINIT2; + if (split_flag & EXT4_EXT_DATA_VALID2) + split_flag1 |= EXT4_EXT_DATA_VALID1; err = ext4_split_extent_at(handle, inode, path, map->m_lblk + map->m_len, split_flag1, flags1); if (err) @@ -2958,8 +2972,8 @@ static int ext4_split_extent(handle_t *handle, return PTR_ERR(path); if (map->m_lblk >= ee_block) { - split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? - EXT4_EXT_MAY_ZEROOUT : 0; + split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT | + EXT4_EXT_DATA_VALID2); if (uninitialized) split_flag1 |= EXT4_EXT_MARK_UNINIT1; if (split_flag & EXT4_EXT_MARK_UNINIT2) @@ -3237,26 +3251,47 @@ static int ext4_split_unwritten_extents(handle_t *handle, split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0; split_flag |= EXT4_EXT_MARK_UNINIT2; - + if (flags & EXT4_GET_BLOCKS_CONVERT) + split_flag |= EXT4_EXT_DATA_VALID2; flags |= EXT4_GET_BLOCKS_PRE_IO; return ext4_split_extent(handle, inode, path, map, split_flag, flags); } static int ext4_convert_unwritten_extents_endio(handle_t *handle, - struct inode *inode, - struct ext4_ext_path *path) + struct inode *inode, + struct ext4_map_blocks *map, + struct ext4_ext_path *path) { struct ext4_extent *ex; + ext4_lblk_t ee_block; + unsigned int ee_len; int depth; int err = 0; depth = ext_depth(inode); ex = path[depth].p_ext; + ee_block = le32_to_cpu(ex->ee_block); + ee_len = ext4_ext_get_actual_len(ex); ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical" "block %llu, max_blocks %u\n", inode->i_ino, - (unsigned long long)le32_to_cpu(ex->ee_block), - ext4_ext_get_actual_len(ex)); + (unsigned long long)ee_block, ee_len); + + /* If extent is larger than requested then split is required */ + if (ee_block != map->m_lblk || ee_len > map->m_len) { + err = ext4_split_unwritten_extents(handle, inode, map, path, + EXT4_GET_BLOCKS_CONVERT); + if (err < 0) + goto out; + ext4_ext_drop_refs(path); + path = ext4_ext_find_extent(inode, map->m_lblk, path); + if (IS_ERR(path)) { + err = PTR_ERR(path); + goto out; + } + depth = ext_depth(inode); + ex = path[depth].p_ext; + } err = ext4_ext_get_access(handle, inode, path + depth); if (err) @@ -3564,7 +3599,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, } /* IO end_io complete, convert the filled extent to written */ if ((flags & EXT4_GET_BLOCKS_CONVERT)) { - ret = ext4_convert_unwritten_extents_endio(handle, inode, + ret = ext4_convert_unwritten_extents_endio(handle, inode, map, path); if (ret >= 0) { ext4_update_inode_fsync_trans(handle, inode, 1); -- GitLab From 2807664df50419f56b596aa49da8a22102c0e0a3 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Mon, 22 Oct 2012 18:01:19 -0400 Subject: [PATCH 0811/1799] ext4: Avoid underflow in ext4_trim_fs() commit 5de35e8d5c02d271c20e18337e01bc20e6ef472e upstream. Currently if len argument in ext4_trim_fs() is smaller than one block, the 'end' variable underflow. Avoid that by returning EINVAL if len is smaller than file system block. Also remove useless unlikely(). Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/mballoc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 6b0a57eafb53..e77c4fe665a0 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4984,8 +4984,9 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) end = start + (range->len >> sb->s_blocksize_bits) - 1; minlen = range->minlen >> sb->s_blocksize_bits; - if (unlikely(minlen > EXT4_CLUSTERS_PER_GROUP(sb)) || - unlikely(start >= max_blks)) + if (minlen > EXT4_CLUSTERS_PER_GROUP(sb) || + start >= max_blks || + range->len < sb->s_blocksize) return -EINVAL; if (end >= max_blks) end = max_blks - 1; -- GitLab From d39bd2701f0f414aba1376ae61202b526ec7e128 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Wed, 10 Oct 2012 11:51:09 +0530 Subject: [PATCH 0812/1799] nohz: Fix idle ticks in cpu summary line of /proc/stat commit 7386cdbf2f57ea8cff3c9fde93f206e58b9fe13f upstream. Git commit 09a1d34f8535ecf9 "nohz: Make idle/iowait counter update conditional" introduced a bug in regard to cpu hotplug. The effect is that the number of idle ticks in the cpu summary line in /proc/stat is still counting ticks for offline cpus. Reproduction is easy, just start a workload that keeps all cpus busy, switch off one or more cpus and then watch the idle field in top. On a dual-core with one cpu 100% busy and one offline cpu you will get something like this: %Cpu(s): 48.7 us, 1.3 sy, 0.0 ni, 50.0 id, 0.0 wa, 0.0 hi, 0.0 si, %0.0 st The problem is that an offline cpu still has ts->idle_active == 1. To fix this we should make sure that the cpu is online when calling get_cpu_idle_time_us and get_cpu_iowait_time_us. [Srivatsa: Rebased to current mainline] Reported-by: Martin Schwidefsky Signed-off-by: Michal Hocko Reviewed-by: Srivatsa S. Bhat Signed-off-by: Srivatsa S. Bhat Link: http://lkml.kernel.org/r/20121010061820.8999.57245.stgit@srivatsabhat.in.ibm.com Cc: deepthi@linux.vnet.ibm.com Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- fs/proc/stat.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/proc/stat.c b/fs/proc/stat.c index 64c3b3172367..e296572c73ed 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c @@ -45,10 +45,13 @@ static cputime64_t get_iowait_time(int cpu) static u64 get_idle_time(int cpu) { - u64 idle, idle_time = get_cpu_idle_time_us(cpu, NULL); + u64 idle, idle_time = -1ULL; + + if (cpu_online(cpu)) + idle_time = get_cpu_idle_time_us(cpu, NULL); if (idle_time == -1ULL) - /* !NO_HZ so we can rely on cpustat.idle */ + /* !NO_HZ or cpu offline so we can rely on cpustat.idle */ idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE]; else idle = usecs_to_cputime64(idle_time); @@ -58,10 +61,13 @@ static u64 get_idle_time(int cpu) static u64 get_iowait_time(int cpu) { - u64 iowait, iowait_time = get_cpu_iowait_time_us(cpu, NULL); + u64 iowait, iowait_time = -1ULL; + + if (cpu_online(cpu)) + iowait_time = get_cpu_iowait_time_us(cpu, NULL); if (iowait_time == -1ULL) - /* !NO_HZ so we can rely on cpustat.iowait */ + /* !NO_HZ or cpu offline so we can rely on cpustat.iowait */ iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT]; else iowait = usecs_to_cputime64(iowait_time); -- GitLab From 75383fac9206c9dc57a5f153ffabcd5341ad0c28 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 19 Oct 2012 11:43:11 -0400 Subject: [PATCH 0813/1799] arch/tile: avoid generating .eh_frame information in modules commit 627072b06c362bbe7dc256f618aaa63351f0cfe6 upstream. The tile tool chain uses the .eh_frame information for backtracing. The vmlinux build drops any .eh_frame sections at link time, but when present in kernel modules, it causes a module load failure due to the presence of unsupported pc-relative relocations. When compiling to use compiler feedback support, the compiler by default omits .eh_frame information, so we don't see this problem. But when not using feedback, we need to explicitly suppress the .eh_frame. Signed-off-by: Chris Metcalf Signed-off-by: Greg Kroah-Hartman --- arch/tile/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/tile/Makefile b/arch/tile/Makefile index 9520bc5a4b7f..99f461d8d9da 100644 --- a/arch/tile/Makefile +++ b/arch/tile/Makefile @@ -26,6 +26,10 @@ $(error Set TILERA_ROOT or CROSS_COMPILE when building $(ARCH) on $(HOST_ARCH)) endif endif +# The tile compiler may emit .eh_frame information for backtracing. +# In kernel modules, this causes load failures due to unsupported relocations. +KBUILD_CFLAGS += -fno-asynchronous-unwind-tables + ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"") KBUILD_CFLAGS += $(CONFIG_DEBUG_EXTRA_FLAGS) endif -- GitLab From 08eaf6a4ee82eb566c188f71b33f52e780fab57d Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 13 Oct 2012 00:30:28 -0400 Subject: [PATCH 0814/1799] NLM: nlm_lookup_file() may return NLMv4-specific error codes commit cd0b16c1c3cda12dbed1f8de8f1a9b0591990724 upstream. If the filehandle is stale, or open access is denied for some reason, nlm_fopen() may return one of the NLMv4-specific error codes nlm4_stale_fh or nlm4_failed. These get passed right through nlm_lookup_file(), and so when nlmsvc_retrieve_args() calls the latter, it needs to filter the result through the cast_status() machinery. Failure to do so, will trigger the BUG_ON() in encode_nlm_stat... Signed-off-by: Trond Myklebust Reported-by: Larry McVoy Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/lockd/clntxdr.c | 2 +- fs/lockd/svcproc.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c index d269ada7670e..982d2676e1f8 100644 --- a/fs/lockd/clntxdr.c +++ b/fs/lockd/clntxdr.c @@ -223,7 +223,7 @@ static void encode_nlm_stat(struct xdr_stream *xdr, { __be32 *p; - BUG_ON(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); + WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); p = xdr_reserve_space(xdr, 4); *p = stat; } diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index d27aab11f324..d413af338da1 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -67,7 +67,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain file pointer. Not used by FREE_ALL call. */ if (filp != NULL) { - if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0) + error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh)); + if (error != 0) goto no_locks; *filp = file; -- GitLab From d641457de0939adaa140161127f2f72bcfe50b37 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 10 Oct 2012 10:18:35 +0300 Subject: [PATCH 0815/1799] oprofile, x86: Fix wrapping bug in op_x86_get_ctrl() commit 44009105081b51417f311f4c3be0061870b6b8ed upstream. The "event" variable is a u16 so the shift will always wrap to zero making the line a no-op. Signed-off-by: Dan Carpenter Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- arch/x86/oprofile/nmi_int.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 26b8a8514ee5..48768df2471a 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -55,7 +55,7 @@ u64 op_x86_get_ctrl(struct op_x86_model_spec const *model, val |= counter_config->extra; event &= model->event_mask ? model->event_mask : 0xFF; val |= event & 0xFF; - val |= (event & 0x0F00) << 24; + val |= (u64)(event & 0x0F00) << 24; return val; } -- GitLab From 1b91a891bc337ecec08dea5436be0bbb03fec12b Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 18 Oct 2012 11:11:01 +0200 Subject: [PATCH 0816/1799] s390: fix linker script for 31 bit builds commit c985cb37f1b39c2c8035af741a2a0b79f1fbaca7 upstream. Because of a change in the s390 arch backend of binutils (commit 23ecd77 "Pick the default arch depending on the target size" in binutils repo) 31 bit builds will fail since the linker would now try to create 64 bit binary output. Fix this by setting OUTPUT_ARCH to s390:31-bit instead of s390. Thanks to Andreas Krebbel for figuring out the issue. Fixes this build error: LD init/built-in.o s390x-4.7.2-ld: s390:31-bit architecture of input file `arch/s390/kernel/head.o' is incompatible with s390:64-bit output Cc: Andreas Krebbel Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/boot/compressed/vmlinux.lds.S | 2 +- arch/s390/kernel/vmlinux.lds.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/boot/compressed/vmlinux.lds.S b/arch/s390/boot/compressed/vmlinux.lds.S index d80f79d8dd9c..8e1fb8239287 100644 --- a/arch/s390/boot/compressed/vmlinux.lds.S +++ b/arch/s390/boot/compressed/vmlinux.lds.S @@ -5,7 +5,7 @@ OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") OUTPUT_ARCH(s390:64-bit) #else OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") -OUTPUT_ARCH(s390) +OUTPUT_ARCH(s390:31-bit) #endif ENTRY(startup) diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index 21109c63eb12..1343d7cf4443 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -8,7 +8,7 @@ #ifndef CONFIG_64BIT OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") -OUTPUT_ARCH(s390) +OUTPUT_ARCH(s390:31-bit) ENTRY(startup) jiffies = jiffies_64 + 4; #else -- GitLab From baecc6ef799c7ab9a5fc0ba29ee560a5c264f306 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Tue, 17 Jul 2012 00:01:26 +0200 Subject: [PATCH 0817/1799] SUNRPC: Prevent kernel stack corruption on long values of flush commit 212ba90696ab4884e2025b0b13726d67aadc2cd4 upstream. The buffer size in read_flush() is too small for the longest possible values for it. This can lead to a kernel stack corruption: [ 43.047329] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff833e64b4 [ 43.047329] [ 43.049030] Pid: 6015, comm: trinity-child18 Tainted: G W 3.5.0-rc7-next-20120716-sasha #221 [ 43.050038] Call Trace: [ 43.050435] [] panic+0xcd/0x1f4 [ 43.050931] [] ? read_flush.isra.7+0xe4/0x100 [ 43.051602] [] __stack_chk_fail+0x16/0x20 [ 43.052206] [] read_flush.isra.7+0xe4/0x100 [ 43.052951] [] ? read_flush_pipefs+0x30/0x30 [ 43.053594] [] read_flush_procfs+0x2c/0x30 [ 43.053596] [] proc_reg_read+0x9c/0xd0 [ 43.053596] [] ? proc_reg_write+0xd0/0xd0 [ 43.053596] [] do_loop_readv_writev+0x4b/0x90 [ 43.053596] [] do_readv_writev+0xf6/0x1d0 [ 43.053596] [] vfs_readv+0x3e/0x60 [ 43.053596] [] sys_readv+0x48/0xb0 [ 43.053596] [] system_call_fastpath+0x1a/0x1f Signed-off-by: Sasha Levin Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index de0b0f39d9d8..76cb304f3f1a 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1406,11 +1406,11 @@ static ssize_t read_flush(struct file *file, char __user *buf, size_t count, loff_t *ppos, struct cache_detail *cd) { - char tbuf[20]; + char tbuf[22]; unsigned long p = *ppos; size_t len; - sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time)); + snprintf(tbuf, sizeof(tbuf), "%lu\n", convert_to_wallclock(cd->flush_time)); len = strlen(tbuf); if (p >= len) return 0; -- GitLab From 9b62355a6daff8696ec7f7b1283b6a39650b9f14 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 22 Oct 2012 12:56:58 -0400 Subject: [PATCH 0818/1799] SUNRPC: Fix a UDP transport regression commit f39c1bfb5a03e2d255451bff05be0d7255298fa4 and commit 84e28a307e376f271505af65a7b7e212dd6f61f4 upstream. Commit 43cedbf0e8dfb9c5610eb7985d5f21263e313802 (SUNRPC: Ensure that we grab the XPRT_LOCK before calling xprt_alloc_slot) is causing hangs in the case of NFS over UDP mounts. Since neither the UDP or the RDMA transport mechanism use dynamic slot allocation, we can skip grabbing the socket lock for those transports. Add a new rpc_xprt_op to allow switching between the TCP and UDP/RDMA case. Note that the NFSv4.1 back channel assigns the slot directly through rpc_run_bc_task, so we can ignore that case. Reported-by: Dick Streefland Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- include/linux/sunrpc/xprt.h | 3 +++ net/sunrpc/xprt.c | 34 +++++++++++++++++++-------------- net/sunrpc/xprtrdma/transport.c | 1 + net/sunrpc/xprtsock.c | 4 ++++ 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 77d278defa70..005b507d6d74 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -114,6 +114,7 @@ struct rpc_xprt_ops { void (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize); int (*reserve_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); + void (*alloc_slot)(struct rpc_xprt *xprt, struct rpc_task *task); void (*rpcbind)(struct rpc_task *task); void (*set_port)(struct rpc_xprt *xprt, unsigned short port); void (*connect)(struct rpc_task *task); @@ -279,6 +280,8 @@ void xprt_connect(struct rpc_task *task); void xprt_reserve(struct rpc_task *task); int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task); int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); +void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); +void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); int xprt_prepare_transmit(struct rpc_task *task); void xprt_transmit(struct rpc_task *task); void xprt_end_transmit(struct rpc_task *task); diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index da72492360b8..176a24f0153b 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -969,11 +969,11 @@ static bool xprt_dynamic_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) return false; } -static void xprt_alloc_slot(struct rpc_task *task) +void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) { - struct rpc_xprt *xprt = task->tk_xprt; struct rpc_rqst *req; + spin_lock(&xprt->reserve_lock); if (!list_empty(&xprt->free)) { req = list_entry(xprt->free.next, struct rpc_rqst, rq_list); list_del(&req->rq_list); @@ -994,12 +994,29 @@ static void xprt_alloc_slot(struct rpc_task *task) default: task->tk_status = -EAGAIN; } + spin_unlock(&xprt->reserve_lock); return; out_init_req: task->tk_status = 0; task->tk_rqstp = req; xprt_request_init(task, xprt); + spin_unlock(&xprt->reserve_lock); +} +EXPORT_SYMBOL_GPL(xprt_alloc_slot); + +void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) +{ + /* Note: grabbing the xprt_lock_write() ensures that we throttle + * new slot allocation if the transport is congested (i.e. when + * reconnecting a stream transport or when out of socket write + * buffer space). + */ + if (xprt_lock_write(xprt, task)) { + xprt_alloc_slot(xprt, task); + xprt_release_write(xprt, task); + } } +EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot); static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) { @@ -1083,20 +1100,9 @@ void xprt_reserve(struct rpc_task *task) if (task->tk_rqstp != NULL) return; - /* Note: grabbing the xprt_lock_write() here is not strictly needed, - * but ensures that we throttle new slot allocation if the transport - * is congested (e.g. if reconnecting or if we're out of socket - * write buffer space). - */ task->tk_timeout = 0; task->tk_status = -EAGAIN; - if (!xprt_lock_write(xprt, task)) - return; - - spin_lock(&xprt->reserve_lock); - xprt_alloc_slot(task); - spin_unlock(&xprt->reserve_lock); - xprt_release_write(xprt, task); + xprt->ops->alloc_slot(xprt, task); } static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 06cdbff79e4a..5d9202dc7cb1 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -713,6 +713,7 @@ static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) static struct rpc_xprt_ops xprt_rdma_procs = { .reserve_xprt = xprt_rdma_reserve_xprt, .release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */ + .alloc_slot = xprt_alloc_slot, .release_request = xprt_release_rqst_cong, /* ditto */ .set_retrans_timeout = xprt_set_retrans_timeout_def, /* ditto */ .rpcbind = rpcb_getport_async, /* sunrpc/rpcb_clnt.c */ diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 00ff34343bae..a4a6586f4032 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2444,6 +2444,7 @@ static void bc_destroy(struct rpc_xprt *xprt) static struct rpc_xprt_ops xs_local_ops = { .reserve_xprt = xprt_reserve_xprt, .release_xprt = xs_tcp_release_xprt, + .alloc_slot = xprt_alloc_slot, .rpcbind = xs_local_rpcbind, .set_port = xs_local_set_port, .connect = xs_connect, @@ -2460,6 +2461,7 @@ static struct rpc_xprt_ops xs_udp_ops = { .set_buffer_size = xs_udp_set_buffer_size, .reserve_xprt = xprt_reserve_xprt_cong, .release_xprt = xprt_release_xprt_cong, + .alloc_slot = xprt_alloc_slot, .rpcbind = rpcb_getport_async, .set_port = xs_set_port, .connect = xs_connect, @@ -2477,6 +2479,7 @@ static struct rpc_xprt_ops xs_udp_ops = { static struct rpc_xprt_ops xs_tcp_ops = { .reserve_xprt = xprt_reserve_xprt, .release_xprt = xs_tcp_release_xprt, + .alloc_slot = xprt_lock_and_alloc_slot, .rpcbind = rpcb_getport_async, .set_port = xs_set_port, .connect = xs_connect, @@ -2496,6 +2499,7 @@ static struct rpc_xprt_ops xs_tcp_ops = { static struct rpc_xprt_ops bc_tcp_ops = { .reserve_xprt = xprt_reserve_xprt, .release_xprt = xprt_release_xprt, + .alloc_slot = xprt_alloc_slot, .rpcbind = xs_local_rpcbind, .buf_alloc = bc_malloc, .buf_free = bc_free, -- GitLab From 6eca486b8d28b1fe1d147cf55dfb8832099bb0a2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 30 Apr 2012 13:50:56 +0000 Subject: [PATCH 0819/1799] pcmcia: sharpsl: don't discard sharpsl_pcmcia_ops commit fdc858a466b738d35d3492bc7cf77b1dac98bf7c upstream. The sharpsl_pcmcia_ops structure gets passed into sa11xx_drv_pcmcia_probe, where it gets accessed at run-time, unlike all other pcmcia drivers that pass their structures into platform_device_add_data, which makes a copy. This means the gcc warning is valid and the structure must not be marked as __initdata. Without this patch, building collie_defconfig results in: drivers/pcmcia/pxa2xx_sharpsl.c:22:31: fatal error: mach-pxa/hardware.h: No such file or directory compilation terminated. make[3]: *** [drivers/pcmcia/pxa2xx_sharpsl.o] Error 1 make[2]: *** [drivers/pcmcia] Error 2 make[1]: *** [drivers] Error 2 make: *** [sub-make] Error 2 Signed-off-by: Arnd Bergmann Cc: Dominik Brodowski Cc: Russell King Cc: Pavel Machek Cc: linux-pcmcia@lists.infradead.org Cc: Jochen Friedrich Signed-off-by: Greg Kroah-Hartman --- drivers/pcmcia/pxa2xx_sharpsl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index b066273b6b4f..7dd879ce514d 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c @@ -194,7 +194,7 @@ static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) sharpsl_pcmcia_init_reset(skt); } -static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = { +static struct pcmcia_low_level sharpsl_pcmcia_ops = { .owner = THIS_MODULE, .hw_init = sharpsl_pcmcia_hw_init, .socket_state = sharpsl_pcmcia_socket_state, -- GitLab From 643fde8ed4ea75f5d113803084806eff14d97454 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 19 Oct 2012 13:56:51 -0700 Subject: [PATCH 0820/1799] kernel/sys.c: fix stack memory content leak via UNAME26 commit 2702b1526c7278c4d65d78de209a465d4de2885e upstream. Calling uname() with the UNAME26 personality set allows a leak of kernel stack contents. This fixes it by defensively calculating the length of copy_to_user() call, making the len argument unsigned, and initializing the stack buffer to zero (now technically unneeded, but hey, overkill). CVE-2012-0957 Reported-by: PaX Team Signed-off-by: Kees Cook Cc: Andi Kleen Cc: PaX Team Cc: Brad Spengler Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/sys.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/kernel/sys.c b/kernel/sys.c index 898a84c9df5b..d041cc720c63 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1180,15 +1180,16 @@ DECLARE_RWSEM(uts_sem); * Work around broken programs that cannot handle "Linux 3.0". * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40 */ -static int override_release(char __user *release, int len) +static int override_release(char __user *release, size_t len) { int ret = 0; - char buf[65]; if (current->personality & UNAME26) { - char *rest = UTS_RELEASE; + const char *rest = UTS_RELEASE; + char buf[65] = { 0 }; int ndots = 0; unsigned v; + size_t copy; while (*rest) { if (*rest == '.' && ++ndots >= 3) @@ -1198,8 +1199,9 @@ static int override_release(char __user *release, int len) rest++; } v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40; - snprintf(buf, len, "2.6.%u%s", v, rest); - ret = copy_to_user(release, buf, len); + copy = min(sizeof(buf), max_t(size_t, 1, len)); + copy = scnprintf(buf, copy, "2.6.%u%s", v, rest); + ret = copy_to_user(release, buf, copy + 1); } return ret; } -- GitLab From 3680030e9747dfa51fe9c1850361c29ae0ad20fe Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 19 Oct 2012 18:45:53 -0700 Subject: [PATCH 0821/1799] use clamp_t in UNAME26 fix commit 31fd84b95eb211d5db460a1dda85e004800a7b52 upstream. The min/max call needed to have explicit types on some architectures (e.g. mn10300). Use clamp_t instead to avoid the warning: kernel/sys.c: In function 'override_release': kernel/sys.c:1287:10: warning: comparison of distinct pointer types lacks a cast [enabled by default] Reported-by: Fengguang Wu Signed-off-by: Kees Cook Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sys.c b/kernel/sys.c index d041cc720c63..b0003db7fea0 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1199,7 +1199,7 @@ static int override_release(char __user *release, size_t len) rest++; } v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40; - copy = min(sizeof(buf), max_t(size_t, 1, len)); + copy = clamp_t(size_t, len, 1, sizeof(buf)); copy = scnprintf(buf, copy, "2.6.%u%s", v, rest); ret = copy_to_user(release, buf, copy + 1); } -- GitLab From efd5fa0c1a1d1b46846ea6e8d1a783d0d8a6a721 Mon Sep 17 00:00:00 2001 From: Jacob Shin Date: Thu, 20 Oct 2011 16:15:26 -0500 Subject: [PATCH 0822/1799] x86: Exclude E820_RESERVED regions and memory holes above 4 GB from direct mapping. commit 1bbbbe779aabe1f0768c2bf8f8c0a5583679b54a upstream. On systems with very large memory (1 TB in our case), BIOS may report a reserved region or a hole in the E820 map, even above the 4 GB range. Exclude these from the direct mapping. [ hpa: this should be done not just for > 4 GB but for everything above the legacy region (1 MB), at the very least. That, however, turns out to require significant restructuring. That work is well underway, but is not suitable for rc/stable. ] Signed-off-by: Jacob Shin Link: http://lkml.kernel.org/r/1319145326-13902-1-git-send-email-jacob.shin@amd.com Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/setup.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 1a2901562059..fbbd1eb6c68e 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -927,8 +927,21 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_X86_64 if (max_pfn > max_low_pfn) { - max_pfn_mapped = init_memory_mapping(1UL<<32, - max_pfn<addr + ei->size <= 1UL << 32) + continue; + + if (ei->type == E820_RESERVED) + continue; + + max_pfn_mapped = init_memory_mapping( + ei->addr < 1UL << 32 ? 1UL << 32 : ei->addr, + ei->addr + ei->size); + } + /* can we preseve max_low_pfn ?*/ max_low_pfn = max_pfn; } -- GitLab From cf32a3a3e7b9a449e3b51bc8114d623d52fa9c5f Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Fri, 19 Oct 2012 17:29:07 +0100 Subject: [PATCH 0823/1799] xen/x86: don't corrupt %eip when returning from a signal handler commit a349e23d1cf746f8bdc603dcc61fae9ee4a695f6 upstream. In 32 bit guests, if a userspace process has %eax == -ERESTARTSYS (-512) or -ERESTARTNOINTR (-513) when it is interrupted by an event /and/ the process has a pending signal then %eip (and %eax) are corrupted when returning to the main process after handling the signal. The application may then crash with SIGSEGV or a SIGILL or it may have subtly incorrect behaviour (depending on what instruction it returned to). The occurs because handle_signal() is incorrectly thinking that there is a system call that needs to restarted so it adjusts %eip and %eax to re-execute the system call instruction (even though user space had not done a system call). If %eax == -514 (-ERESTARTNOHAND (-514) or -ERESTART_RESTARTBLOCK (-516) then handle_signal() only corrupted %eax (by setting it to -EINTR). This may cause the application to crash or have incorrect behaviour. handle_signal() assumes that regs->orig_ax >= 0 means a system call so any kernel entry point that is not for a system call must push a negative value for orig_ax. For example, for physical interrupts on bare metal the inverse of the vector is pushed and page_fault() sets regs->orig_ax to -1, overwriting the hardware provided error code. xen_hypervisor_callback() was incorrectly pushing 0 for orig_ax instead of -1. Classic Xen kernels pushed %eax which works as %eax cannot be both non-negative and -RESTARTSYS (etc.), but using -1 is consistent with other non-system call entry points and avoids some of the tests in handle_signal(). There were similar bugs in xen_failsafe_callback() of both 32 and 64-bit guests. If the fault was corrected and the normal return path was used then 0 was incorrectly pushed as the value for orig_ax. Signed-off-by: David Vrabel Acked-by: Jan Beulich Acked-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/entry_32.S | 8 +++++--- arch/x86/kernel/entry_64.S | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 7b784f4ef1e4..6d4f7ba227f6 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -1025,7 +1025,7 @@ ENTRY(xen_sysenter_target) ENTRY(xen_hypervisor_callback) CFI_STARTPROC - pushl_cfi $0 + pushl_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL TRACE_IRQS_OFF @@ -1067,14 +1067,16 @@ ENTRY(xen_failsafe_callback) 2: mov 8(%esp),%es 3: mov 12(%esp),%fs 4: mov 16(%esp),%gs + /* EAX == 0 => Category 1 (Bad segment) + EAX != 0 => Category 2 (Bad IRET) */ testl %eax,%eax popl_cfi %eax lea 16(%esp),%esp CFI_ADJUST_CFA_OFFSET -16 jz 5f addl $16,%esp - jmp iret_exc # EAX != 0 => Category 2 (Bad IRET) -5: pushl_cfi $0 # EAX == 0 => Category 1 (Bad segment) + jmp iret_exc +5: pushl_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL jmp ret_from_exception CFI_ENDPROC diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index cdc79b5cfcd9..bd6f59203b5f 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1351,7 +1351,7 @@ ENTRY(xen_failsafe_callback) CFI_RESTORE r11 addq $0x30,%rsp CFI_ADJUST_CFA_OFFSET -0x30 - pushq_cfi $0 + pushq_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL jmp error_exit CFI_ENDPROC -- GitLab From e83863d3e7ead8c66c1cabb53d95ebd3c7f1805e Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 16 Oct 2012 21:21:21 +0800 Subject: [PATCH 0824/1799] USB: cdc-acm: fix pipe type of write endpoint commit c5211187f7ff8e8dbff4ebf7c011ac4c0ffe319c upstream. If the write endpoint is interrupt type, usb_sndintpipe() should be passed to usb_fill_int_urb() instead of usb_sndbulkpipe(). Signed-off-by: Ming Lei Cc: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 7f2fac162a7e..3b70aade0569 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1234,7 +1234,7 @@ static int acm_probe(struct usb_interface *intf, if (usb_endpoint_xfer_int(epwrite)) usb_fill_int_urb(snd->urb, usb_dev, - usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), + usb_sndintpipe(usb_dev, epwrite->bEndpointAddress), NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval); else usb_fill_bulk_urb(snd->urb, usb_dev, -- GitLab From a5204466fa5da21c4431d391101439d7f5f2b828 Mon Sep 17 00:00:00 2001 From: Nicolas Boullis Date: Tue, 16 Oct 2012 00:06:23 +0200 Subject: [PATCH 0825/1799] usb: acm: fix the computation of the number of data bits commit 301a29da6e891e7eb95c843af0ecdbe86d01f723 upstream. The current code assumes that CSIZE is 0000060, which appears to be wrong on some arches (such as powerpc). Signed-off-by: Nicolas Boullis Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 3b70aade0569..c5f7eae429e8 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -818,10 +818,6 @@ static const __u32 acm_tty_speed[] = { 2500000, 3000000, 3500000, 4000000 }; -static const __u8 acm_tty_size[] = { - 5, 6, 7, 8 -}; - static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) { @@ -835,7 +831,21 @@ static void acm_tty_set_termios(struct tty_struct *tty, newline.bParityType = termios->c_cflag & PARENB ? (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; - newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4]; + switch (termios->c_cflag & CSIZE) { + case CS5: + newline.bDataBits = 5; + break; + case CS6: + newline.bDataBits = 6; + break; + case CS7: + newline.bDataBits = 7; + break; + case CS8: + default: + newline.bDataBits = 8; + break; + } /* FIXME: Needs to clear unsupported bits in the termios */ acm->clocal = ((termios->c_cflag & CLOCAL) != 0); -- GitLab From 045b361901efac992f4ffd773db7c32319ffe177 Mon Sep 17 00:00:00 2001 From: "Alexis R. Cortes" Date: Wed, 17 Oct 2012 14:09:12 -0500 Subject: [PATCH 0826/1799] usb: host: xhci: New system added for Compliance Mode Patch on SN65LVPE502CP commit 470809741a28c3092279f4e1f3f432e534d46068 upstream. This minor change adds a new system to which the "Fix Compliance Mode on SN65LVPE502CP Hardware" patch has to be applied also. System added: Vendor: Hewlett-Packard. System Model: Z1 Signed-off-by: Alexis R. Cortes Acked-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index f75623155308..e52ddfe05486 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -479,7 +479,8 @@ static bool compliance_mode_recovery_timer_quirk_check(void) if (strstr(dmi_product_name, "Z420") || strstr(dmi_product_name, "Z620") || - strstr(dmi_product_name, "Z820")) + strstr(dmi_product_name, "Z820") || + strstr(dmi_product_name, "Z1")) return true; return false; -- GitLab From f9353fb64e1cfb7a1218fbd610df1980a40b1c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 18 Oct 2012 17:19:53 +0200 Subject: [PATCH 0827/1799] USB: option: blacklist net interface on ZTE devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1452df6f1b7e396d89c2a1fdbdc0e0e839f97671 upstream. Based on information from the ZTE Windows drivers. Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 68 ++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 57de73462f0d..2a90a0e283a1 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -503,11 +503,19 @@ static const struct option_blacklist_info net_intf5_blacklist = { .reserved = BIT(5), }; +static const struct option_blacklist_info net_intf6_blacklist = { + .reserved = BIT(6), +}; + static const struct option_blacklist_info zte_mf626_blacklist = { .sendsetup = BIT(0) | BIT(1), .reserved = BIT(4), }; +static const struct option_blacklist_info zte_1255_blacklist = { + .reserved = BIT(3) | BIT(4), +}; + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -853,13 +861,19 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) }, @@ -872,7 +886,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) }, @@ -886,7 +901,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, @@ -1002,18 +1018,24 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&zte_1255_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) }, @@ -1071,15 +1093,21 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { 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) }, -- GitLab From 9b1ca55bf3ff5fa1c3ff87bac9c7183bc421dc82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 18 Oct 2012 17:14:17 +0200 Subject: [PATCH 0828/1799] USB: option: add more ZTE devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4b35f1c52943851b310afb09047bfe991ac8f5ae upstream. Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 2a90a0e283a1..17ec21ee7d07 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -895,6 +895,12 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */ + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), @@ -903,6 +909,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, @@ -1080,8 +1088,16 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff), /* ZTE MF91 */ + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, -- GitLab From 9a55fef20afb3d7362b0c9d19ba1e78dfe482d3d Mon Sep 17 00:00:00 2001 From: Daisuke Nishimura Date: Thu, 4 Oct 2012 16:37:16 +0900 Subject: [PATCH 0829/1799] cgroup: notify_on_release may not be triggered in some cases commit 1f5320d5972aa50d3e8d2b227b636b370e608359 upstream. notify_on_release must be triggered when the last process in a cgroup is move to another. But if the first(and only) process in a cgroup is moved to another, notify_on_release is not triggered. # mkdir /cgroup/cpu/SRC # mkdir /cgroup/cpu/DST # # echo 1 >/cgroup/cpu/SRC/notify_on_release # echo 1 >/cgroup/cpu/DST/notify_on_release # # sleep 300 & [1] 8629 # # echo 8629 >/cgroup/cpu/SRC/tasks # echo 8629 >/cgroup/cpu/DST/tasks -> notify_on_release for /SRC must be triggered at this point, but it isn't. This is because put_css_set() is called before setting CGRP_RELEASABLE in cgroup_task_migrate(), and is a regression introduce by the commit:74a1166d(cgroups: make procs file writable), which was merged into v3.0. Acked-by: Li Zefan Cc: Ben Blum Signed-off-by: Daisuke Nishimura Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- kernel/cgroup.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index ed64ccac67c9..b76dd5862a8c 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1868,9 +1868,8 @@ static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp, * trading it for newcg is protected by cgroup_mutex, we're safe to drop * it here; it will be freed under RCU. */ - put_css_set(oldcg); - set_bit(CGRP_RELEASABLE, &oldcgrp->flags); + put_css_set(oldcg); } /** -- GitLab From 5993bba302a1a6df9c73690a08346411ff7cd56e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 18 Oct 2012 17:40:30 -0700 Subject: [PATCH 0830/1799] Revert "cgroup: Remove task_lock() from cgroup_post_fork()" commit d87838321124061f6c935069d97f37010fa417e6 upstream. This reverts commit 7e3aa30ac8c904a706518b725c451bb486daaae9. The commit incorrectly assumed that fork path always performed threadgroup_change_begin/end() and depended on that for synchronization against task exit and cgroup migration paths instead of explicitly grabbing task_lock(). threadgroup_change is not locked when forking a new process (as opposed to a new thread in the same process) and even if it were it wouldn't be effective as different processes use different threadgroup locks. Revert the incorrect optimization. Signed-off-by: Tejun Heo LKML-Reference: <20121008020000.GB2575@localhost> Acked-by: Li Zefan Cc: Frederic Weisbecker Signed-off-by: Greg Kroah-Hartman --- kernel/cgroup.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index b76dd5862a8c..5cb488065dca 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4539,19 +4539,10 @@ void cgroup_post_fork(struct task_struct *child) */ if (use_task_css_set_links) { write_lock(&css_set_lock); - if (list_empty(&child->cg_list)) { - /* - * It's safe to use child->cgroups without task_lock() - * here because we are protected through - * threadgroup_change_begin() against concurrent - * css_set change in cgroup_task_migrate(). Also - * the task can't exit at that point until - * wake_up_new_task() is called, so we are protected - * against cgroup_exit() setting child->cgroup to - * init_css_set. - */ + task_lock(child); + if (list_empty(&child->cg_list)) list_add(&child->cg_list, &child->cgroups->tasks); - } + task_unlock(child); write_unlock(&css_set_lock); } } -- GitLab From 727fa37e405a71dc1c7208ea7352be55e0310eca Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 18 Oct 2012 17:52:07 -0700 Subject: [PATCH 0831/1799] Revert "cgroup: Drop task_lock(parent) on cgroup_fork()" commit 9bb71308b8133d643648776243e4d5599b1c193d upstream. This reverts commit 7e381b0eb1e1a9805c37335562e8dc02e7d7848c. The commit incorrectly assumed that fork path always performed threadgroup_change_begin/end() and depended on that for synchronization against task exit and cgroup migration paths instead of explicitly grabbing task_lock(). threadgroup_change is not locked when forking a new process (as opposed to a new thread in the same process) and even if it were it wouldn't be effective as different processes use different threadgroup locks. Revert the incorrect optimization. Signed-off-by: Tejun Heo LKML-Reference: <20121008020000.GB2575@localhost> Acked-by: Li Zefan Bitterly-Acked-by: Frederic Weisbecker Signed-off-by: Greg Kroah-Hartman --- kernel/cgroup.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 5cb488065dca..762f7cc753ac 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4462,31 +4462,20 @@ static const struct file_operations proc_cgroupstats_operations = { * * A pointer to the shared css_set was automatically copied in * fork.c by dup_task_struct(). However, we ignore that copy, since - * it was not made under the protection of RCU, cgroup_mutex or - * threadgroup_change_begin(), so it might no longer be a valid - * cgroup pointer. cgroup_attach_task() might have already changed - * current->cgroups, allowing the previously referenced cgroup - * group to be removed and freed. - * - * Outside the pointer validity we also need to process the css_set - * inheritance between threadgoup_change_begin() and - * threadgoup_change_end(), this way there is no leak in any process - * wide migration performed by cgroup_attach_proc() that could otherwise - * miss a thread because it is too early or too late in the fork stage. + * it was not made under the protection of RCU or cgroup_mutex, so + * might no longer be a valid cgroup pointer. cgroup_attach_task() might + * have already changed current->cgroups, allowing the previously + * referenced cgroup group to be removed and freed. * * At the point that cgroup_fork() is called, 'current' is the parent * task, and the passed argument 'child' points to the child task. */ void cgroup_fork(struct task_struct *child) { - /* - * We don't need to task_lock() current because current->cgroups - * can't be changed concurrently here. The parent obviously hasn't - * exited and called cgroup_exit(), and we are synchronized against - * cgroup migration through threadgroup_change_begin(). - */ + task_lock(current); child->cgroups = current->cgroups; get_css_set(child->cgroups); + task_unlock(current); INIT_LIST_HEAD(&child->cg_list); } -- GitLab From 409dcaefb5c287d68c36e2598154b979a67a9447 Mon Sep 17 00:00:00 2001 From: Pritesh Raithatha Date: Wed, 17 Oct 2012 11:51:37 +0530 Subject: [PATCH 0832/1799] pinctrl: tegra: correct bank for pingroup and drv pingroup commit a03690e44468dcd3088f6600ab036d17bd2130ff upstream. Signed-off-by: Pritesh Raithatha Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/pinctrl/pinctrl-tegra30.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c index 4d7571d4a431..636d96c4b3ee 100644 --- a/drivers/pinctrl/pinctrl-tegra30.c +++ b/drivers/pinctrl/pinctrl-tegra30.c @@ -3343,10 +3343,10 @@ static const struct tegra_function tegra30_functions[] = { FUNCTION(vi_alt3), }; -#define MUXCTL_REG_A 0x3000 -#define PINGROUP_REG_A 0x868 +#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ -#define PINGROUP_REG_Y(r) ((r) - MUXCTL_REG_A) +#define PINGROUP_REG_Y(r) ((r) - PINGROUP_REG_A) #define PINGROUP_REG_N(r) -1 #define PINGROUP(pg_name, f0, f1, f2, f3, f_safe, r, od, ior) \ @@ -3362,25 +3362,25 @@ static const struct tegra_function tegra30_functions[] = { }, \ .func_safe = TEGRA_MUX_ ## f_safe, \ .mux_reg = PINGROUP_REG_Y(r), \ - .mux_bank = 0, \ + .mux_bank = 1, \ .mux_bit = 0, \ .pupd_reg = PINGROUP_REG_Y(r), \ - .pupd_bank = 0, \ + .pupd_bank = 1, \ .pupd_bit = 2, \ .tri_reg = PINGROUP_REG_Y(r), \ - .tri_bank = 0, \ + .tri_bank = 1, \ .tri_bit = 4, \ .einput_reg = PINGROUP_REG_Y(r), \ - .einput_bank = 0, \ + .einput_bank = 1, \ .einput_bit = 5, \ .odrain_reg = PINGROUP_REG_##od(r), \ - .odrain_bank = 0, \ + .odrain_bank = 1, \ .odrain_bit = 6, \ .lock_reg = PINGROUP_REG_Y(r), \ - .lock_bank = 0, \ + .lock_bank = 1, \ .lock_bit = 7, \ .ioreset_reg = PINGROUP_REG_##ior(r), \ - .ioreset_bank = 0, \ + .ioreset_bank = 1, \ .ioreset_bit = 8, \ .drv_reg = -1, \ } @@ -3399,8 +3399,8 @@ static const struct tegra_function tegra30_functions[] = { .odrain_reg = -1, \ .lock_reg = -1, \ .ioreset_reg = -1, \ - .drv_reg = ((r) - PINGROUP_REG_A), \ - .drv_bank = 1, \ + .drv_reg = ((r) - DRV_PINGROUP_REG_A), \ + .drv_bank = 0, \ .hsm_bit = hsm_b, \ .schmitt_bit = schmitt_b, \ .lpmd_bit = lpmd_b, \ -- GitLab From 248ada294174583d918564de33bc5504311c69bb Mon Sep 17 00:00:00 2001 From: Pritesh Raithatha Date: Wed, 17 Oct 2012 17:09:36 +0530 Subject: [PATCH 0833/1799] pinctrl: tegra: set low power mode bank width to 2 commit 154f3ebf53edcfbe28728452b4ab37a118581125 upstream. Signed-off-by: Pritesh Raithatha Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/pinctrl/pinctrl-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c index 9b329688120c..2a32a2ff7323 100644 --- a/drivers/pinctrl/pinctrl-tegra.c +++ b/drivers/pinctrl/pinctrl-tegra.c @@ -259,7 +259,7 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx, *bank = g->drv_bank; *reg = g->drv_reg; *bit = g->lpmd_bit; - *width = 1; + *width = 2; break; case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH: *bank = g->drv_bank; -- GitLab From 5a58f4890e681eadbb617cace87cfdac948c7edd Mon Sep 17 00:00:00 2001 From: Hiro Sugawara Date: Thu, 18 Oct 2012 08:35:10 +0300 Subject: [PATCH 0834/1799] iommu/tegra: smmu: Fix deadly typo commit d0078e72314df2e5ede03f2102cddde06767c374 upstream. Fix a deadly typo in macro definition. Signed-off-by: Hiro Sugawara Signed-off-by: Hiroshi Doyu Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/tegra-smmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 17ef6c493662..035f28edf8fa 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -148,7 +148,7 @@ #define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12) #define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22) -#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22) +#define SMMU_PDN_TO_ADDR(pdn) ((pdn) << 22) #define _READABLE (1 << SMMU_PTB_DATA_ASID_READABLE_SHIFT) #define _WRITABLE (1 << SMMU_PTB_DATA_ASID_WRITABLE_SHIFT) -- GitLab From 8538f9c30a098c87bb806e80f43b2203a997a4d9 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 23 Oct 2012 14:09:39 -0700 Subject: [PATCH 0835/1799] amd64_edac:__amd64_set_scrub_rate(): avoid overindexing scrubrates[] commit 168bfeef7bba3f9784f7540b053e4ac72b769ce9 upstream. If none of the elements in scrubrates[] matches, this loop will cause __amd64_set_scrub_rate() to incorrectly use the n+1th element. As the function is designed to use the final scrubrates[] element in the case of no match, we can fix this bug by simply terminating the array search at the n-1th element. Boris: this code is fragile anyway, see here why: http://marc.info/?l=linux-kernel&m=135102834131236&w=2 It will be rewritten more robustly soonish. Reported-by: Denis Kirjanov Cc: Doug Thompson Signed-off-by: Andrew Morton Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman --- drivers/edac/amd64_edac.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 7ef73c919c5d..a8bfe1c5378c 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -170,8 +170,11 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) * memory controller and apply to register. Search for the first * bandwidth entry that is greater or equal than the setting requested * and program that. If at last entry, turn off DRAM scrubbing. + * + * If no suitable bandwidth is found, turn off DRAM scrubbing entirely + * by falling back to the last element in scrubrates[]. */ - for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { + for (i = 0; i < ARRAY_SIZE(scrubrates) - 1; i++) { /* * skip scrub rates which aren't recommended * (see F10 BKDG, F3x58) @@ -181,12 +184,6 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) if (scrubrates[i].bandwidth <= new_bw) break; - - /* - * if no suitable bandwidth found, turn off DRAM scrubbing - * entirely by falling back to the last element in the - * scrubrates array. - */ } scrubval = scrubrates[i].scrubval; -- GitLab From bfbd61ec59fae6f633db1d139015c3dd81e453be Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 4 Oct 2012 11:58:00 +0300 Subject: [PATCH 0836/1799] usb: dwc3: gadget: fix 'endpoint always busy' bug commit 041d81f493d90c940ec41f0ec98bc7c4f2fba431 upstream. If a USB transfer has already been started, meaning we have already issued StartTransfer command to that particular endpoint, DWC3_EP_BUSY flag has also already been set. When we try to cancel this transfer which is already in controller's cache, we will not receive XferComplete event and we must clear DWC3_EP_BUSY in order to allow subsequent requests to be properly started. The best place to clear that flag is right after issuing DWC3_DEPCMD_ENDTRANSFER. Reported-by: Moiz Sonasath Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index b8d46978fc58..cee0c3e8ab3a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1777,6 +1777,7 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum) ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); WARN_ON_ONCE(ret); dep->res_trans_idx = 0; + dep->flags &= ~DWC3_EP_BUSY; } } -- GitLab From f0dc514c8a0fd7ee7b1f6a3ccdae3b38e6ee1578 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 6 Aug 2012 22:47:03 -0300 Subject: [PATCH 0837/1799] media: au0828: fix case where STREAMOFF being called on stopped stream causes BUG() commit a595c1ce4c9d572cf53513570b9f1a263d7867f2 upstream. We weren't checking whether the resource was in use before calling res_free(), so applications which called STREAMOFF on a v4l2 device that wasn't already streaming would cause a BUG() to be hit (MythTV). Reported-by: Larry Finger Reported-by: Jay Harbeston Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 0b3e481ffe8c..eab06419473e 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1692,14 +1692,18 @@ static int vidioc_streamoff(struct file *file, void *priv, (AUVI_INPUT(i).audio_setup)(dev, 0); } - videobuf_streamoff(&fh->vb_vidq); - res_free(fh, AU0828_RESOURCE_VIDEO); + if (res_check(fh, AU0828_RESOURCE_VIDEO)) { + videobuf_streamoff(&fh->vb_vidq); + res_free(fh, AU0828_RESOURCE_VIDEO); + } } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { dev->vbi_timeout_running = 0; del_timer_sync(&dev->vbi_timeout); - videobuf_streamoff(&fh->vb_vbiq); - res_free(fh, AU0828_RESOURCE_VBI); + if (res_check(fh, AU0828_RESOURCE_VBI)) { + videobuf_streamoff(&fh->vb_vbiq); + res_free(fh, AU0828_RESOURCE_VBI); + } } return 0; -- GitLab From 70f7f1c70af637a23ca09ba1d2d7c966d1bd5990 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Thu, 4 Oct 2012 20:15:48 +0000 Subject: [PATCH 0838/1799] netlink: add reference of module in netlink_dump_start [ Upstream commit 6dc878a8ca39e93f70c42f3dd7260bde10c1e0f1 ] I get a panic when I use ss -a and rmmod inet_diag at the same time. It's because netlink_dump uses inet_diag_dump which belongs to module inet_diag. I search the codes and find many modules have the same problem. We need to add a reference to the module which the cb->dump belongs to. Thanks for all help from Stephen,Jan,Eric,Steffen and Pablo. Change From v3: change netlink_dump_start to inline,suggestion from Pablo and Eric. Change From v2: delete netlink_dump_done,and call module_put in netlink_dump and netlink_sock_destruct. Signed-off-by: Gao feng Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/netlink.h | 21 +++++++++++++++++---- net/netlink/af_netlink.c | 29 +++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index a2092f582a78..b23e9cd6a888 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -153,6 +153,7 @@ struct nlattr { #include #include +#include struct net; @@ -226,6 +227,8 @@ struct netlink_callback { struct netlink_callback *cb); int (*done)(struct netlink_callback *cb); void *data; + /* the module that dump function belong to */ + struct module *module; u16 family; u16 min_dump_alloc; unsigned int prev_seq, seq; @@ -251,14 +254,24 @@ __nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, int type, int len, int flags) struct netlink_dump_control { int (*dump)(struct sk_buff *skb, struct netlink_callback *); - int (*done)(struct netlink_callback*); + int (*done)(struct netlink_callback *); void *data; + struct module *module; u16 min_dump_alloc; }; -extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, - const struct nlmsghdr *nlh, - struct netlink_dump_control *control); +extern int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, + const struct nlmsghdr *nlh, + struct netlink_dump_control *control); +static inline int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, + const struct nlmsghdr *nlh, + struct netlink_dump_control *control) +{ + if (!control->module) + control->module = THIS_MODULE; + + return __netlink_dump_start(ssk, skb, nlh, control); +} #define NL_NONROOT_RECV 0x1 diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index bba6ba176abd..edce424048d8 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -156,6 +156,8 @@ static void netlink_sock_destruct(struct sock *sk) if (nlk->cb) { if (nlk->cb->done) nlk->cb->done(nlk->cb); + + module_put(nlk->cb->module); netlink_destroy_callback(nlk->cb); } @@ -1728,6 +1730,7 @@ static int netlink_dump(struct sock *sk) nlk->cb = NULL; mutex_unlock(nlk->cb_mutex); + module_put(cb->module); netlink_destroy_callback(cb); return 0; @@ -1737,9 +1740,9 @@ static int netlink_dump(struct sock *sk) return err; } -int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, - const struct nlmsghdr *nlh, - struct netlink_dump_control *control) +int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, + const struct nlmsghdr *nlh, + struct netlink_dump_control *control) { struct netlink_callback *cb; struct sock *sk; @@ -1754,6 +1757,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, cb->done = control->done; cb->nlh = nlh; cb->data = control->data; + cb->module = control->module; cb->min_dump_alloc = control->min_dump_alloc; atomic_inc(&skb->users); cb->skb = skb; @@ -1764,19 +1768,28 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, return -ECONNREFUSED; } nlk = nlk_sk(sk); - /* A dump is in progress... */ + mutex_lock(nlk->cb_mutex); + /* A dump is in progress... */ if (nlk->cb) { mutex_unlock(nlk->cb_mutex); netlink_destroy_callback(cb); - sock_put(sk); - return -EBUSY; + ret = -EBUSY; + goto out; } + /* add reference of module which cb->dump belongs to */ + if (!try_module_get(cb->module)) { + mutex_unlock(nlk->cb_mutex); + netlink_destroy_callback(cb); + ret = -EPROTONOSUPPORT; + goto out; + } + nlk->cb = cb; mutex_unlock(nlk->cb_mutex); ret = netlink_dump(sk); - +out: sock_put(sk); if (ret) @@ -1787,7 +1800,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, */ return -EINTR; } -EXPORT_SYMBOL(netlink_dump_start); +EXPORT_SYMBOL(__netlink_dump_start); void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) { -- GitLab From 6114941a295ff186d29ab7462cce6a41a089c354 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Thu, 4 Oct 2012 20:15:49 +0000 Subject: [PATCH 0839/1799] infiniband: pass rdma_cm module to netlink_dump_start [ Upstream commit 809d5fc9bf6589276a12bd4fd611e4c7ff9940c3 ] set netlink_dump_control.module to avoid panic. Signed-off-by: Gao feng Cc: Roland Dreier Cc: Sean Hefty Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/cma.c | 3 ++- drivers/infiniband/core/netlink.c | 1 + include/rdma/rdma_netlink.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index e3e470fecaa9..67432e200c63 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -3451,7 +3451,8 @@ static int cma_get_id_stats(struct sk_buff *skb, struct netlink_callback *cb) } static const struct ibnl_client_cbs cma_cb_table[] = { - [RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats }, + [RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats, + .module = THIS_MODULE }, }; static int __init cma_init(void) diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c index 396e29370304..8c3b08ac496d 100644 --- a/drivers/infiniband/core/netlink.c +++ b/drivers/infiniband/core/netlink.c @@ -151,6 +151,7 @@ static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { struct netlink_dump_control c = { .dump = client->cb_table[op].dump, + .module = client->cb_table[op].module, }; return netlink_dump_start(nls, skb, nlh, &c); } diff --git a/include/rdma/rdma_netlink.h b/include/rdma/rdma_netlink.h index 3c5363ab867b..bd3d8b24b420 100644 --- a/include/rdma/rdma_netlink.h +++ b/include/rdma/rdma_netlink.h @@ -39,6 +39,7 @@ struct rdma_cm_id_stats { struct ibnl_client_cbs { int (*dump)(struct sk_buff *skb, struct netlink_callback *nlcb); + struct module *module; }; int ibnl_init(void); -- GitLab From 742bd2b3cef97a6eea8168b8e356ca2f16b7f3eb Mon Sep 17 00:00:00 2001 From: "ramesh.nagappa@gmail.com" Date: Fri, 5 Oct 2012 19:10:15 +0000 Subject: [PATCH 0840/1799] net: Fix skb_under_panic oops in neigh_resolve_output [ Upstream commit e1f165032c8bade3a6bdf546f8faf61fda4dd01c ] The retry loop in neigh_resolve_output() and neigh_connected_output() call dev_hard_header() with out reseting the skb to network_header. This causes the retry to fail with skb_under_panic. The fix is to reset the network_header within the retry loop. Signed-off-by: Ramesh Nagappa Reviewed-by: Shawn Lu Reviewed-by: Robert Coulson Reviewed-by: Billie Alsup Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/neighbour.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 73b90351df5c..ac88107d1bc9 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1285,8 +1285,6 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) if (!dst) goto discard; - __skb_pull(skb, skb_network_offset(skb)); - if (!neigh_event_send(neigh, skb)) { int err; struct net_device *dev = neigh->dev; @@ -1296,6 +1294,7 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) neigh_hh_init(neigh, dst); do { + __skb_pull(skb, skb_network_offset(skb)); seq = read_seqbegin(&neigh->ha_lock); err = dev_hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len); @@ -1326,9 +1325,8 @@ int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb) unsigned int seq; int err; - __skb_pull(skb, skb_network_offset(skb)); - do { + __skb_pull(skb, skb_network_offset(skb)); seq = read_seqbegin(&neigh->ha_lock); err = dev_hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len); -- GitLab From 14a547a85a7fa2b6473eaa73b83e2055b476a5dc Mon Sep 17 00:00:00 2001 From: Graham Gower Date: Mon, 8 Oct 2012 08:34:50 +0000 Subject: [PATCH 0841/1799] skge: Add DMA mask quirk for Marvell 88E8001 on ASUS P5NSLI motherboard [ Upstream commit a2af139ff1cd85df586690ff626619ab1ee88b0a ] Marvell 88E8001 on an ASUS P5NSLI motherboard is unable to send/receive packets on a system with >4gb ram unless a 32bit DMA mask is used. This issue has been around for years and a fix was sent 3.5 years ago, but there was some debate as to whether it should instead be fixed as a PCI quirk. http://www.spinics.net/lists/netdev/msg88670.html However, 18 months later a similar workaround was introduced for another chipset exhibiting the same problem. http://www.spinics.net/lists/netdev/msg142287.html Signed-off-by: Graham Gower Signed-off-by: Jan Ceuleers Acked-by: Stephen Hemminger Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/marvell/skge.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 5a30bf823099..f4be8f7c2866 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -4153,6 +4153,13 @@ static struct dmi_system_id skge_32bit_dma_boards[] = { DMI_MATCH(DMI_BOARD_NAME, "nForce"), }, }, + { + .ident = "ASUS P5NSLI", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "P5NSLI") + }, + }, {} }; -- GitLab From 2d2f242f248f19c4618bde9091d20416e2c9a1f6 Mon Sep 17 00:00:00 2001 From: Florian Zumbiehl Date: Sun, 7 Oct 2012 15:51:58 +0000 Subject: [PATCH 0842/1799] vlan: don't deliver frames for unknown vlans to protocols [ Upstream commit 48cc32d38a52d0b68f91a171a8d00531edc6a46e ] 6a32e4f9dd9219261f8856f817e6655114cfec2f made the vlan code skip marking vlan-tagged frames for not locally configured vlans as PACKET_OTHERHOST if there was an rx_handler, as the rx_handler could cause the frame to be received on a different (virtual) vlan-capable interface where that vlan might be configured. As rx_handlers do not necessarily return RX_HANDLER_ANOTHER, this could cause frames for unknown vlans to be delivered to the protocol stack as if they had been received untagged. For example, if an ipv6 router advertisement that's tagged for a locally not configured vlan is received on an interface with macvlan interfaces attached, macvlan's rx_handler returns RX_HANDLER_PASS after delivering the frame to the macvlan interfaces, which caused it to be passed to the protocol stack, leading to ipv6 addresses for the announced prefix being configured even though those are completely unusable on the underlying interface. The fix moves marking as PACKET_OTHERHOST after the rx_handler so the rx_handler, if there is one, sees the frame unchanged, but afterwards, before the frame is delivered to the protocol stack, it gets marked whether there is an rx_handler or not. Signed-off-by: Florian Zumbiehl Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/if_vlan.h | 8 ++++---- net/8021q/vlan_core.c | 10 ++-------- net/core/dev.c | 7 +++++-- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index a810987cb80e..561e130df0b2 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -82,6 +82,8 @@ static inline int is_vlan_dev(struct net_device *dev) } #define vlan_tx_tag_present(__skb) ((__skb)->vlan_tci & VLAN_TAG_PRESENT) +#define vlan_tx_nonzero_tag_present(__skb) \ + (vlan_tx_tag_present(__skb) && ((__skb)->vlan_tci & VLAN_VID_MASK)) #define vlan_tx_tag_get(__skb) ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT) #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) @@ -91,7 +93,7 @@ extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, extern struct net_device *vlan_dev_real_dev(const struct net_device *dev); extern u16 vlan_dev_vlan_id(const struct net_device *dev); -extern bool vlan_do_receive(struct sk_buff **skb, bool last_handler); +extern bool vlan_do_receive(struct sk_buff **skb); extern struct sk_buff *vlan_untag(struct sk_buff *skb); extern int vlan_vid_add(struct net_device *dev, unsigned short vid); @@ -120,10 +122,8 @@ static inline u16 vlan_dev_vlan_id(const struct net_device *dev) return 0; } -static inline bool vlan_do_receive(struct sk_buff **skb, bool last_handler) +static inline bool vlan_do_receive(struct sk_buff **skb) { - if (((*skb)->vlan_tci & VLAN_VID_MASK) && last_handler) - (*skb)->pkt_type = PACKET_OTHERHOST; return false; } diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index f36463087ba8..912613c566cb 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -5,7 +5,7 @@ #include #include "vlan.h" -bool vlan_do_receive(struct sk_buff **skbp, bool last_handler) +bool vlan_do_receive(struct sk_buff **skbp) { struct sk_buff *skb = *skbp; u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK; @@ -13,14 +13,8 @@ bool vlan_do_receive(struct sk_buff **skbp, bool last_handler) struct vlan_pcpu_stats *rx_stats; vlan_dev = vlan_find_dev(skb->dev, vlan_id); - if (!vlan_dev) { - /* Only the last call to vlan_do_receive() should change - * pkt_type to PACKET_OTHERHOST - */ - if (vlan_id && last_handler) - skb->pkt_type = PACKET_OTHERHOST; + if (!vlan_dev) return false; - } skb = *skbp = skb_share_check(skb, GFP_ATOMIC); if (unlikely(!skb)) diff --git a/net/core/dev.c b/net/core/dev.c index 086bc2e578cc..82ca51bc29ed 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3209,18 +3209,18 @@ static int __netif_receive_skb(struct sk_buff *skb) ncls: #endif - rx_handler = rcu_dereference(skb->dev->rx_handler); if (vlan_tx_tag_present(skb)) { if (pt_prev) { ret = deliver_skb(skb, pt_prev, orig_dev); pt_prev = NULL; } - if (vlan_do_receive(&skb, !rx_handler)) + if (vlan_do_receive(&skb)) goto another_round; else if (unlikely(!skb)) goto out; } + rx_handler = rcu_dereference(skb->dev->rx_handler); if (rx_handler) { if (pt_prev) { ret = deliver_skb(skb, pt_prev, orig_dev); @@ -3240,6 +3240,9 @@ static int __netif_receive_skb(struct sk_buff *skb) } } + if (vlan_tx_nonzero_tag_present(skb)) + skb->pkt_type = PACKET_OTHERHOST; + /* deliver only exact match when indicated */ null_or_dev = deliver_exact ? skb->dev : NULL; -- GitLab From 04c592343f478826bf1e5d0d178bb295d848c428 Mon Sep 17 00:00:00 2001 From: "jeff.liu" Date: Mon, 8 Oct 2012 18:57:27 +0000 Subject: [PATCH 0843/1799] RDS: fix rds-ping spinlock recursion [ Upstream commit 5175a5e76bbdf20a614fb47ce7a38f0f39e70226 ] This is the revised patch for fixing rds-ping spinlock recursion according to Venkat's suggestions. RDS ping/pong over TCP feature has been broken for years(2.6.39 to 3.6.0) since we have to set TCP cork and call kernel_sendmsg() between ping/pong which both need to lock "struct sock *sk". However, this lock has already been hold before rds_tcp_data_ready() callback is triggerred. As a result, we always facing spinlock resursion which would resulting in system panic. Given that RDS ping is only used to test the connectivity and not for serious performance measurements, we can queue the pong transmit to rds_wq as a delayed response. Reported-by: Dan Carpenter CC: Venkat Venkatsubra CC: David S. Miller CC: James Morris Signed-off-by: Jie Liu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/rds/send.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/rds/send.c b/net/rds/send.c index 96531d4033a2..88eace57dd6b 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -1122,7 +1122,7 @@ rds_send_pong(struct rds_connection *conn, __be16 dport) rds_stats_inc(s_send_pong); if (!test_bit(RDS_LL_SEND_FULL, &conn->c_flags)) - rds_send_xmit(conn); + queue_delayed_work(rds_wq, &conn->c_send_w, 0); rds_message_put(rm); return 0; -- GitLab From 259c5a7fd824ebca122f04fc4202b88896f31d26 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 12 Oct 2012 04:34:17 +0000 Subject: [PATCH 0844/1799] tcp: resets are misrouted [ Upstream commit 4c67525849e0b7f4bd4fab2487ec9e43ea52ef29 ] After commit e2446eaa ("tcp_v4_send_reset: binding oif to iif in no sock case").. tcp resets are always lost, when routing is asymmetric. Yes, backing out that patch will result in misrouting of resets for dead connections which used interface binding when were alive, but we actually cannot do anything here. What's died that's died and correct handling normal unbound connections is obviously a priority. Comment to comment: > This has few benefits: > 1. tcp_v6_send_reset already did that. It was done to route resets for IPv6 link local addresses. It was a mistake to do so for global addresses. The patch fixes this as well. Actually, the problem appears to be even more serious than guaranteed loss of resets. As reported by Sergey Soloviev , those misrouted resets create a lot of arp traffic and huge amount of unresolved arp entires putting down to knees NAT firewalls which use asymmetric routing. Signed-off-by: Alexey Kuznetsov Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_ipv4.c | 7 ++++--- net/ipv6/tcp_ipv6.c | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 0cb86ceb652f..8f2458df19f0 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -678,10 +678,11 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) arg.csumoffset = offsetof(struct tcphdr, check) / 2; arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; /* When socket is gone, all binding information is lost. - * routing might fail in this case. using iif for oif to - * make sure we can deliver it + * routing might fail in this case. No choice here, if we choose to force + * input interface, we will misroute in case of asymmetric route. */ - arg.bound_dev_if = sk ? sk->sk_bound_dev_if : inet_iif(skb); + if (sk) + arg.bound_dev_if = sk->sk_bound_dev_if; net = dev_net(skb_dst(skb)->dev); arg.tos = ip_hdr(skb)->tos; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 98256cf72f9d..8a8fa2dd149f 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -896,7 +896,8 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr); fl6.flowi6_proto = IPPROTO_TCP; - fl6.flowi6_oif = inet6_iif(skb); + if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL) + fl6.flowi6_oif = inet6_iif(skb); fl6.fl6_dport = t1->dest; fl6.fl6_sport = t1->source; security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); -- GitLab From dd2c50efa9941fe7393b5f490eeef68f18916211 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 16 Oct 2012 07:37:27 +0000 Subject: [PATCH 0845/1799] ipv6: addrconf: fix /proc/net/if_inet6 [ Upstream commit 9f0d3c2781baa1102108e16efbe640dd74564a7c ] Commit 1d5783030a1 (ipv6/addrconf: speedup /proc/net/if_inet6 filling) added bugs hiding some devices from if_inet6 and breaking applications. "ip -6 addr" could still display all IPv6 addresses, while "ifconfig -a" couldnt. One way to reproduce the bug is by starting in a shell : unshare -n /bin/bash ifconfig lo up And in original net namespace, lo device disappeared from if_inet6 Reported-by: Jan Hinnerk Stosch Tested-by: Jan Hinnerk Stosch Signed-off-by: Eric Dumazet Cc: Mihai Maruseac Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/addrconf.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 5ec60699c671..468a5ce6e9d2 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3095,14 +3095,15 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq, loff_t pos) struct hlist_node *n; hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; /* sync with offset */ if (p < state->offset) { p++; continue; } state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } /* prepare for next bucket */ @@ -3120,18 +3121,20 @@ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct hlist_node *n = &ifa->addr_lst; hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } while (++state->bucket < IN6_ADDR_HSIZE) { state->offset = 0; hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } } -- GitLab From 01afdbe150a888b20b24a427e010214530176cf5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 10 Oct 2012 17:25:00 -0700 Subject: [PATCH 0846/1799] sparc64: fix ptrace interaction with force_successful_syscall_return() [ Upstream commit 55c2770e413e96871147b9406a9c41fe9bc5209c ] we want syscall_trace_leave() called on exit from any syscall; skipping its call in case we'd done force_successful_syscall_return() is broken... Signed-off-by: Al Viro Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/syscalls.S | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index 1d7e274f3f2b..7f5f65d0b3fd 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S @@ -212,24 +212,20 @@ linux_sparc_syscall: 3: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] ret_sys_call: ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3 - ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc sra %o0, 0, %o0 mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 sllx %g2, 32, %g2 - /* Check if force_successful_syscall_return() - * was invoked. - */ - ldub [%g6 + TI_SYS_NOERROR], %l2 - brnz,a,pn %l2, 80f - stb %g0, [%g6 + TI_SYS_NOERROR] - cmp %o0, -ERESTART_RESTARTBLOCK bgeu,pn %xcc, 1f - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6 -80: + andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 + ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc + +2: + stb %g0, [%g6 + TI_SYS_NOERROR] /* System call success, clear Carry condition code. */ andn %g3, %g2, %g3 +3: stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] bne,pn %icc, linux_syscall_trace2 add %l1, 0x4, %l2 ! npc = npc+4 @@ -238,20 +234,20 @@ ret_sys_call: stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] 1: + /* Check if force_successful_syscall_return() + * was invoked. + */ + ldub [%g6 + TI_SYS_NOERROR], %l2 + brnz,pn %l2, 2b + ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc /* System call failure, set Carry condition code. * Also, get abs(errno) to return to the process. */ - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6 sub %g0, %o0, %o0 - or %g3, %g2, %g3 stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] - bne,pn %icc, linux_syscall_trace2 - add %l1, 0x4, %l2 ! npc = npc+4 - stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] + ba,pt %xcc, 3b + or %g3, %g2, %g3 - b,pt %xcc, rtrap - stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] linux_syscall_trace2: call syscall_trace_leave add %sp, PTREGS_OFF, %o0 -- GitLab From 846514fcb8f4518aa88636542bb7aa8453faacb2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 14 Oct 2012 17:59:40 -0700 Subject: [PATCH 0847/1799] sparc64: Like x86 we should check current->mm during perf backtrace generation. [ Upstream commit 08280e6c4c2e8049ac61d9e8e3536ec1df629c0d ] If the MM is not active, only report the top-level PC. Do not try to access the address space. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/perf_event.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index 28559ce5eeb5..db344c4bc519 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -1428,8 +1428,6 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry, { unsigned long ufp; - perf_callchain_store(entry, regs->tpc); - ufp = regs->u_regs[UREG_I6] + STACK_BIAS; do { struct sparc_stackf *usf, sf; @@ -1450,8 +1448,6 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, { unsigned long ufp; - perf_callchain_store(entry, regs->tpc); - ufp = regs->u_regs[UREG_I6] & 0xffffffffUL; do { struct sparc_stackf32 *usf, sf; @@ -1470,6 +1466,11 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, void perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) { + perf_callchain_store(entry, regs->tpc); + + if (!current->mm) + return; + flushw_user(); if (test_thread_flag(TIF_32BIT)) perf_callchain_user_32(entry, regs); -- GitLab From f603fa368be8342b2bee401ac6c815e6e34b3373 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 16 Oct 2012 13:05:25 -0700 Subject: [PATCH 0848/1799] sparc64: Fix bit twiddling in sparc_pmu_enable_event(). [ Upstream commit e793d8c6740f8fe704fa216e95685f4d92c4c4b9 ] There was a serious disconnect in the logic happening in sparc_pmu_disable_event() vs. sparc_pmu_enable_event(). Event disable is implemented by programming a NOP event into the PCR. However, event enable was not reversing this operation. Instead, it was setting the User/Priv/Hypervisor trace enable bits. That's not sparc_pmu_enable_event()'s job, that's what sparc_pmu_enable() and sparc_pmu_disable() do . The intent of sparc_pmu_enable_event() is clear, since it first clear out the event type encoding field. So fix this by OR'ing in the event encoding rather than the trace enable bits. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/perf_event.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index db344c4bc519..602eca8ef8c4 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -557,11 +557,13 @@ static u64 nop_for_index(int idx) static inline void sparc_pmu_enable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx) { - u64 val, mask = mask_for_index(idx); + u64 enc, val, mask = mask_for_index(idx); + + enc = perf_event_get_enc(cpuc->events[idx]); val = cpuc->pcr; val &= ~mask; - val |= hwc->config; + val |= event_encoding(enc, idx); cpuc->pcr = val; pcr_ops->write(cpuc->pcr); -- GitLab From d37bcccee1b807af77b5c6767cb0df295f9dfbdb Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Wed, 1 Aug 2012 21:10:51 +0200 Subject: [PATCH 0849/1799] sparc64: do not clobber personality flags in sys_sparc64_personality() [ Upstream commit a27032eee8cb6e16516f13c8a9752e9d5d4cc430 ] There are multiple errors in how sys_sparc64_personality() handles personality flags stored in top three bytes. - directly comparing current->personality against PER_LINUX32 doesn't work in cases when any of the personality flags stored in the top three bytes are used. - directly forcefully setting personality to PER_LINUX32 or PER_LINUX discards any flags stored in the top three bytes Fix the first one by properly using personality() macro to compare only PER_MASK bytes. Fix the second one by setting only the bits that should be set, instead of overwriting the whole value. Signed-off-by: Jiri Kosina Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/sys_sparc_64.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 3ee51f189a55..57b7cab1e26a 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -519,12 +519,12 @@ SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality) { int ret; - if (current->personality == PER_LINUX32 && - personality == PER_LINUX) - personality = PER_LINUX32; + if (personality(current->personality) == PER_LINUX32 && + personality(personality) == PER_LINUX) + personality |= PER_LINUX32; ret = sys_personality(personality); - if (ret == PER_LINUX32) - ret = PER_LINUX; + if (personality(ret) == PER_LINUX32) + ret &= ~PER_LINUX32; return ret; } -- GitLab From 3ba595416b15151d2eaa12578c17cbfd64c06aec Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 15 Aug 2012 00:37:29 -0700 Subject: [PATCH 0850/1799] sparc64: Be less verbose during vmemmap population. [ Upstream commit 2856cc2e4d0852c3ddaae9dcb19cb9396512eb08 ] On a 2-node machine with 256GB of ram we get 512 lines of console output, which is just too much. This mimicks Yinghai Lu's x86 commit c2b91e2eec9678dbda274e906cc32ea8f711da3b (x86_64/mm: check and print vmemmap allocation continuous) except that we aren't ever going to get contiguous block pointers in between calls so just print when the virtual address or node changes. This decreases the output by an order of 16. Also demote this to KERN_DEBUG. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/mm/init_64.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 21faaeea85de..07916182387e 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -2099,6 +2099,9 @@ EXPORT_SYMBOL(_PAGE_CACHE); #ifdef CONFIG_SPARSEMEM_VMEMMAP unsigned long vmemmap_table[VMEMMAP_SIZE]; +static long __meminitdata addr_start, addr_end; +static int __meminitdata node_start; + int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) { unsigned long vstart = (unsigned long) start; @@ -2129,15 +2132,30 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) *vmem_pp = pte_base | __pa(block); - printk(KERN_INFO "[%p-%p] page_structs=%lu " - "node=%d entry=%lu/%lu\n", start, block, nr, - node, - addr >> VMEMMAP_CHUNK_SHIFT, - VMEMMAP_SIZE); + /* check to see if we have contiguous blocks */ + if (addr_end != addr || node_start != node) { + if (addr_start) + printk(KERN_DEBUG " [%lx-%lx] on node %d\n", + addr_start, addr_end-1, node_start); + addr_start = addr; + node_start = node; + } + addr_end = addr + VMEMMAP_CHUNK; } } return 0; } + +void __meminit vmemmap_populate_print_last(void) +{ + if (addr_start) { + printk(KERN_DEBUG " [%lx-%lx] on node %d\n", + addr_start, addr_end-1, node_start); + addr_start = 0; + addr_end = 0; + node_start = 0; + } +} #endif /* CONFIG_SPARSEMEM_VMEMMAP */ static void prot_init_common(unsigned long page_none, -- GitLab From f2a713d25e8b95e065c90af72f461e99427e20f8 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 13 Jul 2012 09:28:24 -0700 Subject: [PATCH 0851/1799] mtd: nand: allow NAND_NO_SUBPAGE_WRITE to be set from driver commit bf7a01bf7987b63b121d572b240c132ec44129c4 upstream. The NAND_CHIPOPTIONS_MSK has limited utility and is causing real bugs. It silently masks off at least one flag that might be set by the driver (NAND_NO_SUBPAGE_WRITE). This breaks the GPMI NAND driver and possibly others. Really, as long as driver writers exercise a small amount of care with NAND_* options, this mask is not necessary at all; it was only here to prevent certain options from accidentally being set by the driver. But the original thought turns out to be a bad idea occasionally. Thus, kill it. Note, this patch fixes some major gpmi-nand breakage. Signed-off-by: Brian Norris Tested-by: Huang Shijie Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/nand_base.c | 9 +++------ include/linux/mtd/nand.h | 3 --- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 47b19c0bb070..eb9f5fb02eef 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2897,9 +2897,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, if (le16_to_cpu(p->features) & 1) *busw = NAND_BUSWIDTH_16; - chip->options &= ~NAND_CHIPOPTIONS_MSK; - chip->options |= (NAND_NO_READRDY | - NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK; + chip->options |= NAND_NO_READRDY | NAND_NO_AUTOINCR; pr_info("ONFI flash detected\n"); return 1; @@ -3064,9 +3062,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, mtd->erasesize <<= ((id_data[3] & 0x03) << 1); } } - /* Get chip options, preserve non chip based options */ - chip->options &= ~NAND_CHIPOPTIONS_MSK; - chip->options |= type->options & NAND_CHIPOPTIONS_MSK; + /* Get chip options */ + chip->options |= type->options; /* * Check if chip is not a Samsung device. Do not clear the diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 1482340d3d9f..248351344718 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -215,9 +215,6 @@ typedef enum { #define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT) \ && (chip->page_shift > 9)) -/* Mask to zero out the chip options, which come from the id table */ -#define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR) - /* Non chip related options */ /* This option skips the bbt scan during initialization. */ #define NAND_SKIP_BBTSCAN 0x00010000 -- GitLab From f88df5ff96f5ea632aa2d193d2c9019aa4c728d9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 28 Oct 2012 10:36:33 -0700 Subject: [PATCH 0852/1799] Linux 3.4.16 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fe9ea67db868..470d96b8ba6d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 15 +SUBLEVEL = 16 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 8357dde8b780b426d398f9e3701fdc16f0856766 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 16 Oct 2012 12:51:45 -0400 Subject: [PATCH 0853/1799] drm/radeon: add some new SI PCI ids commit b6aa22db7857ab7ed042d6c56b800bfc727cfdff upstream. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- include/drm/drm_pciids.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 53392e8f9564..efc66f2d096c 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -209,6 +209,8 @@ {0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x678A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6790, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6791, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6792, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ @@ -221,6 +223,7 @@ {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ -- GitLab From 1c1e11543381f3ff0cee52b69903928ff881c0cb Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 19 Oct 2012 13:27:04 -0400 Subject: [PATCH 0854/1799] drm/radeon: add error output if VM CS fails on cayman commit c71721324c612f7f040657ce9917d87f530f9784 upstream. So we know why the CS was rejected. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen_cs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index ea69daeffac1..977b22d4f478 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -2775,6 +2775,7 @@ static bool evergreen_vm_reg_valid(u32 reg) case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS: return true; default: + DRM_ERROR("Invalid register 0x%x in CS\n", reg); return false; } } -- GitLab From 218246de04389b7aa0d1e799ed8b0115f342ee37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stef=C3=A1n=20Freyr?= Date: Fri, 19 Oct 2012 22:46:00 +0200 Subject: [PATCH 0855/1799] ALSA: hda - add dock support for Thinkpad T430 commit 84f98fdf7865fbd35b312eb39ea91e5618c514c7 upstream. I have a Lenovo ThinkPad T430 and an UltraBase Series 3 docking station. Without this patch, if I plug my headphones into the jack on the computer, everything works fine. The computer speakers mute and the audio is played in the headphones. However, if I plug into the docking station headphone jack the computer speakers are muted but there is no audio in the headphones. Addresses https://bugs.launchpad.net/bugs/1060372 Signed-off-by: Joseph Salisbury 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 94b765b31ea4..6ecf1d4fa8a3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6184,6 +6184,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK), + SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), -- GitLab From 419cbf261a717df51878cadd00488ec2a9d9b3a4 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 25 Oct 2012 13:38:14 -0700 Subject: [PATCH 0856/1799] gen_init_cpio: avoid stack overflow when expanding commit 20f1de659b77364d55d4e7fad2ef657e7730323f upstream. Fix possible overflow of the buffer used for expanding environment variables when building file list. In the extremely unlikely case of an attacker having control over the environment variables visible to gen_init_cpio, control over the contents of the file gen_init_cpio parses, and gen_init_cpio was built without compiler hardening, the attacker can gain arbitrary execution control via a stack buffer overflow. $ cat usr/crash.list file foo ${BIG}${BIG}${BIG}${BIG}${BIG}${BIG} 0755 0 0 $ BIG=$(perl -e 'print "A" x 4096;') ./usr/gen_init_cpio usr/crash.list *** buffer overflow detected ***: ./usr/gen_init_cpio terminated This also replaces the space-indenting with tabs. Patch based on existing fix extracted from grsecurity. Signed-off-by: Kees Cook Cc: Michal Marek Cc: Brad Spengler Cc: PaX Team Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- usr/gen_init_cpio.c | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c index af0f22fb1ef7..aca6edcbbc6f 100644 --- a/usr/gen_init_cpio.c +++ b/usr/gen_init_cpio.c @@ -303,7 +303,7 @@ static int cpio_mkfile(const char *name, const char *location, int retval; int rc = -1; int namesize; - int i; + unsigned int i; mode |= S_IFREG; @@ -381,25 +381,28 @@ static int cpio_mkfile(const char *name, const char *location, static char *cpio_replace_env(char *new_location) { - char expanded[PATH_MAX + 1]; - char env_var[PATH_MAX + 1]; - char *start; - char *end; - - for (start = NULL; (start = strstr(new_location, "${")); ) { - end = strchr(start, '}'); - if (start < end) { - *env_var = *expanded = '\0'; - strncat(env_var, start + 2, end - start - 2); - strncat(expanded, new_location, start - new_location); - strncat(expanded, getenv(env_var), PATH_MAX); - strncat(expanded, end + 1, PATH_MAX); - strncpy(new_location, expanded, PATH_MAX); - } else - break; - } - - return new_location; + char expanded[PATH_MAX + 1]; + char env_var[PATH_MAX + 1]; + char *start; + char *end; + + for (start = NULL; (start = strstr(new_location, "${")); ) { + end = strchr(start, '}'); + if (start < end) { + *env_var = *expanded = '\0'; + strncat(env_var, start + 2, end - start - 2); + strncat(expanded, new_location, start - new_location); + strncat(expanded, getenv(env_var), + PATH_MAX - strlen(expanded)); + strncat(expanded, end + 1, + PATH_MAX - strlen(expanded)); + strncpy(new_location, expanded, PATH_MAX); + new_location[PATH_MAX] = 0; + } else + break; + } + + return new_location; } -- GitLab From 6fddae5c4eda4ebc63ae47f3d47e142ca08b31ff Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 25 Oct 2012 13:38:16 -0700 Subject: [PATCH 0857/1799] fs/compat_ioctl.c: VIDEO_SET_SPU_PALETTE missing error check commit 12176503366885edd542389eed3aaf94be163fdb upstream. The compat ioctl for VIDEO_SET_SPU_PALETTE was missing an error check while converting ioctl arguments. This could lead to leaking kernel stack contents into userspace. Patch extracted from existing fix in grsecurity. Signed-off-by: Kees Cook Cc: David Miller Cc: Brad Spengler Cc: PaX Team Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/compat_ioctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index debdfe0fc809..5d2069ff635c 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -210,6 +210,8 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, err = get_user(palp, &up->palette); err |= get_user(length, &up->length); + if (err) + return -EFAULT; up_native = compat_alloc_user_space(sizeof(struct video_spu_palette)); err = put_user(compat_ptr(palp), &up_native->palette); -- GitLab From 3146a25c513a1a3d5452db06d711a0a816e76584 Mon Sep 17 00:00:00 2001 From: Jan Luebbe Date: Thu, 25 Oct 2012 13:38:11 -0700 Subject: [PATCH 0858/1799] drivers/rtc/rtc-imxdi.c: add missing spin lock initialization commit fee0de7791f967c2c5f0d43eb7b7261761b45e64 upstream. Signed-off-by: Jan Luebbe Cc: Alessandro Zummo Cc: Roland Stigge Cc: Grant Likely Tested-by: Roland Stigge Cc: Sascha Hauer Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-imxdi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index d93a9608b1f0..bc744b490b02 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -392,6 +392,8 @@ static int dryice_rtc_probe(struct platform_device *pdev) if (imxdi->ioaddr == NULL) return -ENOMEM; + spin_lock_init(&imxdi->irq_lock); + imxdi->irq = platform_get_irq(pdev, 0); if (imxdi->irq < 0) return imxdi->irq; -- GitLab From 24d1745f4d77918e78ff0095ab233ff4f786287c Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Thu, 25 Oct 2012 13:37:51 -0700 Subject: [PATCH 0859/1799] genalloc: stop crashing the system when destroying a pool commit eedce141cd2dad8d0cefc5468ef41898949a7031 upstream. The genalloc code uses the bitmap API from include/linux/bitmap.h and lib/bitmap.c, which is based on long values. Both bitmap_set from lib/bitmap.c and bitmap_set_ll, which is the lockless version from genalloc.c, use BITMAP_LAST_WORD_MASK to set the first bits in a long in the bitmap. That one uses (1 << bits) - 1, 0b111, if you are setting the first three bits. This means that the API counts from the least significant bits (LSB from now on) to the MSB. The LSB in the first long is bit 0, then. The same works for the lookup functions. The genalloc code uses longs for the bitmap, as it should. In include/linux/genalloc.h, struct gen_pool_chunk has unsigned long bits[0] as its last member. When allocating the struct, genalloc should reserve enough space for the bitmap. This should be a proper number of longs that can fit the amount of bits in the bitmap. However, genalloc allocates an integer number of bytes that fit the amount of bits, but may not be an integer amount of longs. 9 bytes, for example, could be allocated for 70 bits. This is a problem in itself if the Least Significat Bit in a long is in the byte with the largest address, which happens in Big Endian machines. This means genalloc is not allocating the byte in which it will try to set or check for a bit. This may end up in memory corruption, where genalloc will try to set the bits it has not allocated. In fact, genalloc may not set these bits because it may find them already set, because they were not zeroed since they were not allocated. And that's what causes a BUG when gen_pool_destroy is called and check for any set bits. What really happens is that genalloc uses kmalloc_node with __GFP_ZERO on gen_pool_add_virt. With SLAB and SLUB, this means the whole slab will be cleared, not only the requested bytes. Since struct gen_pool_chunk has a size that is a multiple of 8, and slab sizes are multiples of 8, we get lucky and allocate and clear the right amount of bytes. Hower, this is not the case with SLOB or with older code that did memset after allocating instead of using __GFP_ZERO. So, a simple module as this (running 3.6.0), will cause a crash when rmmod'ed. [root@phantom-lp2 foo]# cat foo.c #include #include #include #include MODULE_LICENSE("GPL"); MODULE_VERSION("0.1"); static struct gen_pool *foo_pool; static __init int foo_init(void) { int ret; foo_pool = gen_pool_create(10, -1); if (!foo_pool) return -ENOMEM; ret = gen_pool_add(foo_pool, 0xa0000000, 32 << 10, -1); if (ret) { gen_pool_destroy(foo_pool); return ret; } return 0; } static __exit void foo_exit(void) { gen_pool_destroy(foo_pool); } module_init(foo_init); module_exit(foo_exit); [root@phantom-lp2 foo]# zcat /proc/config.gz | grep SLOB CONFIG_SLOB=y [root@phantom-lp2 foo]# insmod ./foo.ko [root@phantom-lp2 foo]# rmmod foo ------------[ cut here ]------------ kernel BUG at lib/genalloc.c:243! cpu 0x4: Vector: 700 (Program Check) at [c0000000bb0e7960] pc: c0000000003cb50c: .gen_pool_destroy+0xac/0x110 lr: c0000000003cb4fc: .gen_pool_destroy+0x9c/0x110 sp: c0000000bb0e7be0 msr: 8000000000029032 current = 0xc0000000bb0e0000 paca = 0xc000000006d30e00 softe: 0 irq_happened: 0x01 pid = 13044, comm = rmmod kernel BUG at lib/genalloc.c:243! [c0000000bb0e7ca0] d000000004b00020 .foo_exit+0x20/0x38 [foo] [c0000000bb0e7d20] c0000000000dff98 .SyS_delete_module+0x1a8/0x290 [c0000000bb0e7e30] c0000000000097d4 syscall_exit+0x0/0x94 --- Exception: c00 (System Call) at 000000800753d1a0 SP (fffd0b0e640) is in userspace Signed-off-by: Thadeu Lima de Souza Cascardo Cc: Paul Gortmaker Cc: Benjamin Gaignard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- lib/genalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/genalloc.c b/lib/genalloc.c index 6bc04aab6ec7..7cb7a5dac09b 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -176,7 +176,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy struct gen_pool_chunk *chunk; int nbits = size >> pool->min_alloc_order; int nbytes = sizeof(struct gen_pool_chunk) + - (nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE; + BITS_TO_LONGS(nbits) * sizeof(long); chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid); if (unlikely(chunk == NULL)) -- GitLab From c87ece5a158f3907193202d84f2a316a4c363768 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 19 Oct 2012 17:53:01 +0100 Subject: [PATCH 0860/1799] ARM: 7559/1: smp: switch away from the idmap before updating init_mm.mm_count commit 5f40b909728ad784eb43aa309d3c4e9bdf050781 upstream. When booting a secondary CPU, the primary CPU hands two sets of page tables via the secondary_data struct: (1) swapper_pg_dir: a normal, cacheable, shared (if SMP) mapping of the kernel image (i.e. the tables used by init_mm). (2) idmap_pgd: an uncached mapping of the .idmap.text ELF section. The idmap is generally used when enabling and disabling the MMU, which includes early CPU boot. In this case, the secondary CPU switches to swapper as soon as it enters C code: struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); /* * All kernel threads share the same mm context; grab a * reference and switch to it. */ atomic_inc(&mm->mm_count); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); cpu_switch_mm(mm->pgd, mm); This causes a problem on ARMv7, where the identity mapping is treated as strongly-ordered leading to architecturally UNPREDICTABLE behaviour of exclusive accesses, such as those used by atomic_inc. This patch re-orders the secondary_start_kernel function so that we switch to swapper before performing any exclusive accesses. Reported-by: Gilles Chanteperdrix Cc: David McKay Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/smp.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 7babc3f98a1a..8f14a1b8975a 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -249,18 +249,24 @@ static void percpu_timer_setup(void); asmlinkage void __cpuinit secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; - unsigned int cpu = smp_processor_id(); + unsigned int cpu; + + /* + * The identity mapping is uncached (strongly ordered), so + * switch away from it before attempting any exclusive accesses. + */ + cpu_switch_mm(mm->pgd, mm); + enter_lazy_tlb(mm, current); + local_flush_tlb_all(); /* * All kernel threads share the same mm context; grab a * reference and switch to it. */ + cpu = smp_processor_id(); atomic_inc(&mm->mm_count); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); - cpu_switch_mm(mm->pgd, mm); - enter_lazy_tlb(mm, current); - local_flush_tlb_all(); printk("CPU%u: Booted secondary processor\n", cpu); -- GitLab From 368845fde9e704288f370df57988767aab6042b4 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Oct 2012 16:35:18 -0700 Subject: [PATCH 0861/1799] x86, mm: Trim memory in memblock to be page aligned commit 6ede1fd3cb404c0016de6ac529df46d561bd558b upstream. We will not map partial pages, so need to make sure memblock allocation will not allocate those bytes out. Also we will use for_each_mem_pfn_range() to loop to map memory range to keep them consistent. Signed-off-by: Yinghai Lu Link: http://lkml.kernel.org/r/CAE9FiQVZirvaBMFYRfXMmWEcHbKSicQEHz4VAwUv0xFCk51ZNw@mail.gmail.com Acked-by: Jacob Shin Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/e820.c | 3 +++ include/linux/memblock.h | 1 + mm/memblock.c | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 62d61e9976eb..298dc000378a 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1076,6 +1076,9 @@ void __init memblock_x86_fill(void) memblock_add(ei->addr, ei->size); } + /* throw away partial pages */ + memblock_trim_memory(PAGE_SIZE); + memblock_dump_all(); } diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 19dc455b4f3d..c948c440ea2c 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -57,6 +57,7 @@ int memblock_add(phys_addr_t base, phys_addr_t size); int memblock_remove(phys_addr_t base, phys_addr_t size); int memblock_free(phys_addr_t base, phys_addr_t size); int memblock_reserve(phys_addr_t base, phys_addr_t size); +void memblock_trim_memory(phys_addr_t align); #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, diff --git a/mm/memblock.c b/mm/memblock.c index 280d3d7835d6..11e5bd174f3c 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -908,6 +908,30 @@ int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t si return memblock_overlaps_region(&memblock.reserved, base, size) >= 0; } +void __init_memblock memblock_trim_memory(phys_addr_t align) +{ + int i; + phys_addr_t start, end, orig_start, orig_end; + struct memblock_type *mem = &memblock.memory; + + for (i = 0; i < mem->cnt; i++) { + orig_start = mem->regions[i].base; + orig_end = mem->regions[i].base + mem->regions[i].size; + start = round_up(orig_start, align); + end = round_down(orig_end, align); + + if (start == orig_start && end == orig_end) + continue; + + if (start < end) { + mem->regions[i].base = start; + mem->regions[i].size = end - start; + } else { + memblock_remove_region(mem, i); + i--; + } + } +} void __init_memblock memblock_set_current_limit(phys_addr_t limit) { -- GitLab From 71a36b53c81c3ecd1359af68ca4373e7d941a4c5 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 25 Oct 2012 13:37:31 -0700 Subject: [PATCH 0862/1799] mm: fix XFS oops due to dirty pages without buffers on s390 commit ef5d437f71afdf4afdbab99213add99f4b1318fd upstream. On s390 any write to a page (even from kernel itself) sets architecture specific page dirty bit. Thus when a page is written to via buffered write, HW dirty bit gets set and when we later map and unmap the page, page_remove_rmap() finds the dirty bit and calls set_page_dirty(). Dirtying of a page which shouldn't be dirty can cause all sorts of problems to filesystems. The bug we observed in practice is that buffers from the page get freed, so when the page gets later marked as dirty and writeback writes it, XFS crashes due to an assertion BUG_ON(!PagePrivate(page)) in page_buffers() called from xfs_count_page_state(). Similar problem can also happen when zero_user_segment() call from xfs_vm_writepage() (or block_write_full_page() for that matter) set the hardware dirty bit during writeback, later buffers get freed, and then page unmapped. Fix the issue by ignoring s390 HW dirty bit for page cache pages of mappings with mapping_cap_account_dirty(). This is safe because for such mappings when a page gets marked as writeable in PTE it is also marked dirty in do_wp_page() or do_page_fault(). When the dirty bit is cleared by clear_page_dirty_for_io(), the page gets writeprotected in page_mkclean(). So pagecache page is writeable if and only if it is dirty. Thanks to Hugh Dickins for pointing out mapping has to have mapping_cap_account_dirty() for things to work and proposing a cleaned up variant of the patch. The patch has survived about two hours of running fsx-linux on tmpfs while heavily swapping and several days of running on out build machines where the original problem was triggered. Signed-off-by: Jan Kara Cc: Martin Schwidefsky Cc: Mel Gorman Cc: Hugh Dickins Cc: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/rmap.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/mm/rmap.c b/mm/rmap.c index 5b5ad584ffb7..bfca52c96999 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -56,6 +56,7 @@ #include #include #include +#include #include @@ -977,11 +978,8 @@ int page_mkclean(struct page *page) if (page_mapped(page)) { struct address_space *mapping = page_mapping(page); - if (mapping) { + if (mapping) ret = page_mkclean_file(mapping, page); - if (page_test_and_clear_dirty(page_to_pfn(page), 1)) - ret = 1; - } } return ret; @@ -1167,6 +1165,7 @@ void page_add_file_rmap(struct page *page) */ void page_remove_rmap(struct page *page) { + struct address_space *mapping = page_mapping(page); bool anon = PageAnon(page); bool locked; unsigned long flags; @@ -1189,8 +1188,19 @@ void page_remove_rmap(struct page *page) * this if the page is anon, so about to be freed; but perhaps * not if it's in swapcache - there might be another pte slot * containing the swap entry, but page not yet written to swap. + * + * And we can skip it on file pages, so long as the filesystem + * participates in dirty tracking; but need to catch shm and tmpfs + * and ramfs pages which have been modified since creation by read + * fault. + * + * Note that mapping must be decided above, before decrementing + * mapcount (which luckily provides a barrier): once page is unmapped, + * it could be truncated and page->mapping reset to NULL at any moment. + * Note also that we are relying on page_mapping(page) to set mapping + * to &swapper_space when PageSwapCache(page). */ - if ((!anon || PageSwapCache(page)) && + if (mapping && !mapping_cap_account_dirty(mapping) && page_test_and_clear_dirty(page_to_pfn(page), 1)) set_page_dirty(page); /* -- GitLab From 9f659caf90048296ca120143964222c3f8b6dae7 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 22 Oct 2012 17:14:36 -0400 Subject: [PATCH 0863/1799] SUNRPC: Get rid of the xs_error_report socket callback commit f878b657ce8e7d3673afe48110ec208a29e38c4a upstream. Chris Perl reports that we're seeing races between the wakeup call in xs_error_report and the connect attempts. Basically, Chris has shown that in certain circumstances, the call to xs_error_report causes the rpc_task that is responsible for reconnecting to wake up early, thus triggering a disconnect and retry. Since the sk->sk_error_report() calls in the socket layer are always followed by a tcp_done() in the cases where we care about waking up the rpc_tasks, just let the state_change callbacks take responsibility for those wake ups. Reported-by: Chris Perl Signed-off-by: Trond Myklebust Tested-by: Chris Perl Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index a4a6586f4032..6581a9de5799 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -254,7 +254,6 @@ struct sock_xprt { void (*old_data_ready)(struct sock *, int); void (*old_state_change)(struct sock *); void (*old_write_space)(struct sock *); - void (*old_error_report)(struct sock *); }; /* @@ -781,7 +780,6 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk) transport->old_data_ready = sk->sk_data_ready; transport->old_state_change = sk->sk_state_change; transport->old_write_space = sk->sk_write_space; - transport->old_error_report = sk->sk_error_report; } static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) @@ -789,7 +787,6 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s sk->sk_data_ready = transport->old_data_ready; sk->sk_state_change = transport->old_state_change; sk->sk_write_space = transport->old_write_space; - sk->sk_error_report = transport->old_error_report; } static void xs_reset_transport(struct sock_xprt *transport) @@ -1552,25 +1549,6 @@ static void xs_tcp_state_change(struct sock *sk) read_unlock_bh(&sk->sk_callback_lock); } -/** - * xs_error_report - callback mainly for catching socket errors - * @sk: socket - */ -static void xs_error_report(struct sock *sk) -{ - struct rpc_xprt *xprt; - - read_lock_bh(&sk->sk_callback_lock); - if (!(xprt = xprt_from_sock(sk))) - goto out; - dprintk("RPC: %s client %p...\n" - "RPC: error %d\n", - __func__, xprt, sk->sk_err); - xprt_wake_pending_tasks(xprt, -EAGAIN); -out: - read_unlock_bh(&sk->sk_callback_lock); -} - static void xs_write_space(struct sock *sk) { struct socket *sock; @@ -1870,7 +1848,6 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt, sk->sk_user_data = xprt; sk->sk_data_ready = xs_local_data_ready; sk->sk_write_space = xs_udp_write_space; - sk->sk_error_report = xs_error_report; sk->sk_allocation = GFP_ATOMIC; xprt_clear_connected(xprt); @@ -1959,7 +1936,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) sk->sk_user_data = xprt; sk->sk_data_ready = xs_udp_data_ready; sk->sk_write_space = xs_udp_write_space; - sk->sk_error_report = xs_error_report; sk->sk_no_check = UDP_CSUM_NORCV; sk->sk_allocation = GFP_ATOMIC; @@ -2075,7 +2051,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) sk->sk_data_ready = xs_tcp_data_ready; sk->sk_state_change = xs_tcp_state_change; sk->sk_write_space = xs_tcp_write_space; - sk->sk_error_report = xs_error_report; sk->sk_allocation = GFP_ATOMIC; /* socket options */ -- GitLab From ea2887242aafd45727ca22564105fd244f4c6584 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 23 Oct 2012 11:35:47 -0400 Subject: [PATCH 0864/1799] SUNRPC: Clear the connect flag when socket state is TCP_CLOSE_WAIT commit d0bea455dd48da1ecbd04fedf00eb89437455fdc upstream. This is needed to ensure that we call xprt_connect() upon the next call to call_connect(). Signed-off-by: Trond Myklebust Tested-by: Chris Perl Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 6581a9de5799..b34cf303d916 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1525,6 +1525,7 @@ static void xs_tcp_state_change(struct sock *sk) case TCP_CLOSE_WAIT: /* The server initiated a shutdown of the socket */ xprt->connect_cookie++; + clear_bit(XPRT_CONNECTED, &xprt->state); xs_tcp_force_close(xprt); case TCP_CLOSING: /* -- GitLab From dedf1c2d17cd81796fc25190fd194e8dd0269817 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 23 Oct 2012 11:40:02 -0400 Subject: [PATCH 0865/1799] Revert "SUNRPC: Ensure we close the socket on EPIPE errors too..." commit b9d2bb2ee537424a7f855e1f93eed44eb9ee0854 upstream. This reverts commit 55420c24a0d4d1fce70ca713f84aa00b6b74a70e. Now that we clear the connected flag when entering TCP_CLOSE_WAIT, the deadlock described in this commit is no longer possible. Instead, the resulting call to xs_tcp_shutdown() can interfere with pending reconnection attempts. Reported-by: Chris Perl Signed-off-by: Trond Myklebust Tested-by: Chris Perl Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index b34cf303d916..fc197c275e1a 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -736,10 +736,10 @@ static int xs_tcp_send_request(struct rpc_task *task) dprintk("RPC: sendmsg returned unrecognized error %d\n", -status); case -ECONNRESET: - case -EPIPE: xs_tcp_shutdown(xprt); case -ECONNREFUSED: case -ENOTCONN: + case -EPIPE: clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); } -- GitLab From 6c6dff65535906e5a7a27010447fad0cb316a1fb Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 23 Oct 2012 17:50:07 -0400 Subject: [PATCH 0866/1799] SUNRPC: Prevent races in xs_abort_connection() commit 4bc1e68ed6a8b59be8a79eb719be515a55c7bc68 upstream. The call to xprt_disconnect_done() that is triggered by a successful connection reset will trigger another automatic wakeup of all tasks on the xprt->pending rpc_wait_queue. In particular it will cause an early wake up of the task that called xprt_connect(). All we really want to do here is clear all the socket-specific state flags, so we split that functionality out of xs_sock_mark_closed() into a helper that can be called by xs_abort_connection() Reported-by: Chris Perl Signed-off-by: Trond Myklebust Tested-by: Chris Perl Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index fc197c275e1a..79064471cd01 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1462,7 +1462,7 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt) xprt_clear_connecting(xprt); } -static void xs_sock_mark_closed(struct rpc_xprt *xprt) +static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt) { smp_mb__before_clear_bit(); clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); @@ -1470,6 +1470,11 @@ static void xs_sock_mark_closed(struct rpc_xprt *xprt) clear_bit(XPRT_CLOSE_WAIT, &xprt->state); clear_bit(XPRT_CLOSING, &xprt->state); smp_mb__after_clear_bit(); +} + +static void xs_sock_mark_closed(struct rpc_xprt *xprt) +{ + xs_sock_reset_connection_flags(xprt); /* Mark transport as closed and wake up all pending tasks */ xprt_disconnect_done(xprt); } @@ -2004,10 +2009,8 @@ static void xs_abort_connection(struct sock_xprt *transport) any.sa_family = AF_UNSPEC; result = kernel_connect(transport->sock, &any, sizeof(any), 0); if (!result) - xs_sock_mark_closed(&transport->xprt); - else - dprintk("RPC: AF_UNSPEC connect return code %d\n", - result); + xs_sock_reset_connection_flags(&transport->xprt); + dprintk("RPC: AF_UNSPEC connect return code %d\n", result); } static void xs_tcp_reuse_connection(struct sock_xprt *transport) -- GitLab From 325c6bf91fd3c2e4fea473e9ca4eb30666dadb52 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 16 Oct 2012 13:17:43 -0700 Subject: [PATCH 0867/1799] xhci: Fix potential NULL ptr deref in command cancellation. commit 43a09f7fb01fa1e091416a2aa49b6c666458c1ee upstream. The command cancellation code doesn't check whether find_trb_seg() couldn't find the segment that contains the TRB to be canceled. This could cause a NULL pointer deference later in the function when next_trb is called. It's unlikely to happen unless something is wrong with the command ring pointers, so add some debugging in case it happens. This patch should be backported to stable kernels as old as 3.0, that contain the commit b63f4053cc8aa22a98e3f9a97845afe6c15d0a0d "xHCI: handle command after aborting the command ring". Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index a23d71bba754..23aebcb4ee24 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd) cur_seg = find_trb_seg(xhci->cmd_ring->first_seg, xhci->cmd_ring->dequeue, &cycle_state); + if (!cur_seg) { + xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n", + xhci->cmd_ring->dequeue, + (unsigned long long) + xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, + xhci->cmd_ring->dequeue)); + xhci_debug_ring(xhci, xhci->cmd_ring); + xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); + return; + } + /* find the command trb matched by cd from command ring */ for (cmd_trb = xhci->cmd_ring->dequeue; cmd_trb != xhci->cmd_ring->enqueue; -- GitLab From fa3b39b05f40bf7273bcd6c152f0b59005b83480 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sat, 29 Sep 2012 22:23:19 +0200 Subject: [PATCH 0868/1799] sysfs: sysfs_pathname/sysfs_add_one: Use strlcat() instead of strcat() commit 66081a72517a131430dcf986775f3268aafcb546 upstream. The warning check for duplicate sysfs entries can cause a buffer overflow when printing the warning, as strcat() doesn't check buffer sizes. Use strlcat() instead. Since strlcat() doesn't return a pointer to the passed buffer, unlike strcat(), I had to convert the nested concatenation in sysfs_add_one() to an admittedly more obscure comma operator construct, to avoid emitting code for the concatenation if CONFIG_BUG is disabled. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 35a36d39fa2c..a545d819b495 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -457,20 +457,18 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) /** * sysfs_pathname - return full path to sysfs dirent * @sd: sysfs_dirent whose path we want - * @path: caller allocated buffer + * @path: caller allocated buffer of size PATH_MAX * * Gives the name "/" to the sysfs_root entry; any path returned * is relative to wherever sysfs is mounted. - * - * XXX: does no error checking on @path size */ static char *sysfs_pathname(struct sysfs_dirent *sd, char *path) { if (sd->s_parent) { sysfs_pathname(sd->s_parent, path); - strcat(path, "/"); + strlcat(path, "/", PATH_MAX); } - strcat(path, sd->s_name); + strlcat(path, sd->s_name, PATH_MAX); return path; } @@ -503,9 +501,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) char *path = kzalloc(PATH_MAX, GFP_KERNEL); WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s'\n", - (path == NULL) ? sd->s_name : - strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"), - sd->s_name)); + (path == NULL) ? sd->s_name + : (sysfs_pathname(acxt->parent_sd, path), + strlcat(path, "/", PATH_MAX), + strlcat(path, sd->s_name, PATH_MAX), + path)); kfree(path); } -- GitLab From c70fc22aa9f442379b1f64e863b8adf8da2356e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Tue, 16 Oct 2012 15:29:54 -0700 Subject: [PATCH 0869/1799] Staging: android: binder: Fix memory leak on thread/process exit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 675d66b0ed5fd170d6a44cf8dbb3fa56a5347bdb upstream. If a thread or process exited while a reply, one-way transaction or death notification was pending, the struct holding the pending work was leaked. Signed-off-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index c2832124bb3e..80acd0e6a57c 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -2507,14 +2507,38 @@ static void binder_release_work(struct list_head *list) struct binder_transaction *t; t = container_of(w, struct binder_transaction, work); - if (t->buffer->target_node && !(t->flags & TF_ONE_WAY)) + if (t->buffer->target_node && + !(t->flags & TF_ONE_WAY)) { binder_send_failed_reply(t, BR_DEAD_REPLY); + } else { + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered transaction %d\n", + t->debug_id); + t->buffer->transaction = NULL; + kfree(t); + binder_stats_deleted(BINDER_STAT_TRANSACTION); + } } break; case BINDER_WORK_TRANSACTION_COMPLETE: { + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered TRANSACTION_COMPLETE\n"); kfree(w); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); } break; + case BINDER_WORK_DEAD_BINDER_AND_CLEAR: + case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: { + struct binder_ref_death *death; + + death = container_of(w, struct binder_ref_death, work); + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered death notification, %p\n", + death->cookie); + kfree(death); + binder_stats_deleted(BINDER_STAT_DEATH); + } break; default: + pr_err("binder: unexpected work type, %d, not freed\n", + w->type); break; } } @@ -2984,6 +3008,7 @@ static void binder_deferred_release(struct binder_proc *proc) nodes++; rb_erase(&node->rb_node, &proc->nodes); list_del_init(&node->work.entry); + binder_release_work(&node->async_todo); if (hlist_empty(&node->refs)) { kfree(node); binder_stats_deleted(BINDER_STAT_NODE); @@ -3022,6 +3047,7 @@ static void binder_deferred_release(struct binder_proc *proc) binder_delete_ref(ref); } binder_release_work(&proc->todo); + binder_release_work(&proc->delivered_death); buffers = 0; while ((n = rb_first(&proc->allocated_buffers))) { -- GitLab From 7b76336ec39f1af832ebd29add93cfe21e839581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Tue, 16 Oct 2012 15:29:55 -0700 Subject: [PATCH 0870/1799] Staging: android: binder: Allow using highmem for binder buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 585650dcec88e704a19bb226a34b6a7166111623 upstream. The default kernel mapping for the pages allocated for the binder buffers is never used. Set the __GFP_HIGHMEM flag when allocating these pages so we don't needlessly use low memory pages that may be required elsewhere. Signed-off-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 80acd0e6a57c..223639a73b0a 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -655,7 +655,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE]; BUG_ON(*page); - *page = alloc_page(GFP_KERNEL | __GFP_ZERO); + *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); if (*page == NULL) { printk(KERN_ERR "binder: %d: binder_alloc_buf failed " "for page at %p\n", proc->pid, page_addr); -- GitLab From 057f0772b32f9a162c5104b1928b5886f1b85059 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Fri, 12 Oct 2012 13:22:42 -0700 Subject: [PATCH 0871/1799] Drivers: hv: Cleanup error handling in vmbus_open() commit 1392550240aaa72ce3a094a38bd23525cd67ce60 upstream. Fix a memory leak in the error handling path in the function vmbus_open(). Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Reported-by: Jason Wang Acked-by: Jason Wang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 406537420fff..f4c3d28cd1fc 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -146,14 +146,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (ret != 0) { err = ret; - goto errorout; + goto error0; } ret = hv_ringbuffer_init( &newchannel->inbound, in, recv_ringbuffer_size); if (ret != 0) { err = ret; - goto errorout; + goto error0; } @@ -168,7 +168,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (ret != 0) { err = ret; - goto errorout; + goto error0; } /* Create and init the channel open message */ @@ -177,7 +177,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, GFP_KERNEL); if (!open_info) { err = -ENOMEM; - goto errorout; + goto error0; } init_completion(&open_info->waitevent); @@ -193,7 +193,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (userdatalen > MAX_USER_DEFINED_BYTES) { err = -EINVAL; - goto errorout; + goto error0; } if (userdatalen) @@ -208,19 +208,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, sizeof(struct vmbus_channel_open_channel)); if (ret != 0) - goto cleanup; + goto error1; t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ); if (t == 0) { err = -ETIMEDOUT; - goto errorout; + goto error1; } if (open_info->response.open_result.status) err = open_info->response.open_result.status; -cleanup: spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); list_del(&open_info->msglistentry); spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); @@ -228,9 +227,12 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, kfree(open_info); return err; -errorout: - hv_ringbuffer_cleanup(&newchannel->outbound); - hv_ringbuffer_cleanup(&newchannel->inbound); +error1: + spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); + list_del(&open_info->msglistentry); + spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); + +error0: free_pages((unsigned long)out, get_order(send_ringbuffer_size + recv_ringbuffer_size)); kfree(open_info); -- GitLab From a8091a3cbabad7616b565a4d7148e8e6c565cdeb Mon Sep 17 00:00:00 2001 From: Anisse Astier Date: Tue, 9 Oct 2012 12:22:36 +0200 Subject: [PATCH 0872/1799] ehci: fix Lucid nohandoff pci quirk to be more generic with BIOS versions commit c323dc023b9501e5d09582ec7efd1d40a9001d99 upstream. BIOS vendors keep changing the BIOS versions. Only match the beginning of the string to match all Lucid tablets with board name M11JB. Signed-off-by: Anisse Astier Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 966d1484ee79..ead45259bf15 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -545,7 +545,7 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { /* Pegatron Lucid (Ordissimo AIRIS) */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "M11JB"), - DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"), + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), }, }, { } -- GitLab From 145f944257416e38ef00505f07cac17e86ef9655 Mon Sep 17 00:00:00 2001 From: Anisse Astier Date: Tue, 9 Oct 2012 12:22:37 +0200 Subject: [PATCH 0873/1799] ehci: Add yet-another Lucid nohandoff pci quirk commit 8daf8b6086f9d575200cd0aa3797e26137255609 upstream. Board name changed on another shipping Lucid tablet. Signed-off-by: Anisse Astier Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index ead45259bf15..39f9e4a9a2d3 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -548,6 +548,13 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), }, }, + { + /* Pegatron Lucid (Ordissimo) */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"), + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), + }, + }, { } }; -- GitLab From 313f0fd814835c64b90d14be716a6fedbbd4b08e Mon Sep 17 00:00:00 2001 From: Michael Shigorin Date: Mon, 22 Oct 2012 12:18:56 +0300 Subject: [PATCH 0874/1799] usb-storage: add unusual_devs entry for Casio EX-N1 digital camera commit d7870af7e2e3a91b462075ec1ca669b482215187 upstream. This commit sets removable subclass for Casio EX-N1 digital camera. The patch has been tested within an ALT Linux kernel: http://git.altlinux.org/people/led/packages/?p=kernel-image-3.0.git;a=commitdiff;h=c0fd891836e89fe0c93a4d536a59216d90e4e3e7 See also https://bugzilla.kernel.org/show_bug.cgi?id=49221 Signed-off-by: Oleksandr Chumachenko Signed-off-by: Michael Shigorin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 8f3cbb8dc81b..5ffa11640de4 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999, USB_SC_8070, USB_PR_CB, NULL, US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ), +/* Submitted by Oleksandr Chumachenko */ +UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100, + "Casio", + "EX-N1 DigitalCamera", + USB_SC_8070, USB_PR_DEVICE, NULL, 0), + /* Submitted by Hartmut Wahl */ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001, "Samsung", -- GitLab From 891fe9688fbd2ef1c04d8314b74c0037be2adb89 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Mon, 1 Oct 2012 22:21:12 +0300 Subject: [PATCH 0875/1799] usb hub: send clear_tt_buffer_complete events when canceling TT clear work commit 3b6054da68f9b0d5ed6a7ed0f42a79e61904352c upstream. There is a race condition in the USB hub code with regard to handling TT clear requests that can get the HCD driver in a deadlock. Usually when an TT clear request is scheduled it will be executed immediately: <7>[ 6.077583] usb 2-1.3: unlink qh1-0e01/f4d4db00 start 0 [1/2 us] <3>[ 6.078041] usb 2-1: clear tt buffer port 3, a3 ep2 t04048d82 <7>[ 6.078299] hub_tt_work:731 <7>[ 9.309089] usb 2-1.5: link qh1-0e01/f4d506c0 start 0 [1/2 us] <7>[ 9.324526] ehci_hcd 0000:00:1d.0: reused qh f4d4db00 schedule <7>[ 9.324539] usb 2-1.3: link qh1-0e01/f4d4db00 start 0 [1/2 us] <7>[ 9.341530] usb 1-1.1: link qh4-0e01/f397aec0 start 2 [1/2 us] <7>[ 10.116159] usb 2-1.3: unlink qh1-0e01/f4d4db00 start 0 [1/2 us] <3>[ 10.116459] usb 2-1: clear tt buffer port 3, a3 ep2 t04048d82 <7>[ 10.116537] hub_tt_work:731 However, if a suspend operation is triggered before hub_tt_work is scheduled, hub_quiesce will cancel the work without notifying the HCD driver: <3>[ 35.033941] usb 2-1: clear tt buffer port 3, a3 ep2 t04048d80 <5>[ 35.034022] sd 0:0:0:0: [sda] Stopping disk <7>[ 35.034039] hub 2-1:1.0: hub_suspend <7>[ 35.034067] usb 2-1: unlink qh256-0001/f3b1ab00 start 1 [1/0 us] <7>[ 35.035085] hub 1-0:1.0: hub_suspend <7>[ 35.035102] usb usb1: bus suspend, wakeup 0 <7>[ 35.035106] ehci_hcd 0000:00:1a.0: suspend root hub <7>[ 35.035298] hub 2-0:1.0: hub_suspend <7>[ 35.035313] usb usb2: bus suspend, wakeup 0 <7>[ 35.035315] ehci_hcd 0000:00:1d.0: suspend root hub <6>[ 35.250017] PM: suspend of devices complete after 216.979 msecs <6>[ 35.250822] PM: late suspend of devices complete after 0.799 msecs <7>[ 35.252343] ehci_hcd 0000:00:1d.0: wakeup: 1 <7>[ 35.262923] ehci_hcd 0000:00:1d.0: --> PCI D3hot <7>[ 35.263302] ehci_hcd 0000:00:1a.0: wakeup: 1 <7>[ 35.273912] ehci_hcd 0000:00:1a.0: --> PCI D3hot <6>[ 35.274254] PM: noirq suspend of devices complete after 23.442 msecs <6>[ 35.274975] ACPI: Preparing to enter system sleep state S3 <6>[ 35.292666] PM: Saving platform NVS memory <7>[ 35.295030] Disabling non-boot CPUs ... <6>[ 35.297351] CPU 1 is now offline <6>[ 35.300345] CPU 2 is now offline <6>[ 35.303929] CPU 3 is now offline <7>[ 35.303931] lockdep: fixing up alternatives. <6>[ 35.304825] Extended CMOS year: 2000 When the device will resume the EHCI driver will get stuck in ehci_endpoint_disable waiting for the tt_clearing flag to reset: <0>[ 47.610967] usb 2-1.3: **** DPM device timeout **** <7>[ 47.610972] f2f11c60 00000092 f2f11c0c c10624a5 00000003 f4c6e880 c1c8a4c0 c1c8a4c0 <7>[ 47.610983] 15c55698 0000000b f56b34c0 f2a45b70 f4c6e880 00000082 f2a4602c f2f11c30 <7>[ 47.610993] c10787f8 f4cac000 f2a45b70 00000000 f4cac010 f2f11c58 00000046 00000001 <7>[ 47.611004] Call Trace: <7>[ 47.611006] [] ? sched_clock_cpu+0xf5/0x160 <7>[ 47.611019] [] ? lock_release_holdtime.part.22+0x88/0xf0 <7>[ 47.611026] [] ? lock_timer_base.isra.35+0x26/0x50 <7>[ 47.611034] [] ? schedule_timeout+0x133/0x290 <7>[ 47.611044] [] schedule+0x1e/0x50 <7>[ 47.611051] [] schedule_timeout+0x138/0x290 <7>[ 47.611057] [] ? sched_clock_cpu+0xf5/0x160 <7>[ 47.611063] [] ? usleep_range+0x40/0x40 <7>[ 47.611070] [] schedule_timeout_uninterruptible+0x15/0x20 <7>[ 47.611077] [] ehci_endpoint_disable+0x64/0x160 <7>[ 47.611084] [] ? usb_hcd_flush_endpoint+0x10e/0x1d0 <7>[ 47.611092] [] ? sysfs_add_file+0x13/0x20 <7>[ 47.611100] [] usb_hcd_disable_endpoint+0x29/0x40 <7>[ 47.611107] [] usb_disable_endpoint+0x5c/0x80 <7>[ 47.611111] [] usb_disable_interface+0x37/0x50 <7>[ 47.611116] [] usb_reset_and_verify_device+0x4b0/0x640 <7>[ 47.611122] [] ? hub_port_status+0xb5/0x100 <7>[ 47.611129] [] usb_port_resume+0xd5/0x220 <7>[ 47.611136] [] generic_resume+0xf/0x30 <7>[ 47.611142] [] usb_resume+0x133/0x180 <7>[ 47.611147] [] ? usb_dev_thaw+0x10/0x10 <7>[ 47.611152] [] usb_dev_resume+0xd/0x10 <7>[ 47.611157] [] dpm_run_callback+0x40/0xb0 <7>[ 47.611164] [] ? pm_runtime_enable+0x43/0x70 <7>[ 47.611171] [] device_resume+0x1a6/0x2c0 <7>[ 47.611177] [] ? dpm_show_time+0xe0/0xe0 <7>[ 47.611183] [] async_resume+0x19/0x40 <7>[ 47.611189] [] async_run_entry_fn+0x64/0x160 <7>[ 47.611196] [] ? process_one_work+0x104/0x480 <7>[ 47.611203] [] ? process_one_work+0x10c/0x480 <7>[ 47.611209] [] process_one_work+0x180/0x480 <7>[ 47.611215] [] ? process_one_work+0x104/0x480 <7>[ 47.611220] [] ? async_schedule+0x10/0x10 <7>[ 47.611226] [] worker_thread+0x11c/0x2f0 <7>[ 47.611233] [] ? manage_workers.isra.27+0x1f0/0x1f0 <7>[ 47.611239] [] kthread+0x78/0x80 <7>[ 47.611244] [] ? timer_cpu_notify+0xd6/0x20d <7>[ 47.611253] [] ? __init_kthread_worker+0x60/0x60 <7>[ 47.611258] [] kernel_thread_helper+0x6/0xd <7>[ 47.611283] ------------[ cut here ]------------ This patch changes hub_quiesce behavior to flush the TT clear work instead of canceling it, to make sure that no TT clear request remains uncompleted before suspend. Signed-off-by: Octavian Purdila Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index e727b876726c..11344bcc1758 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -507,13 +507,16 @@ static void hub_tt_work(struct work_struct *work) int limit = 100; spin_lock_irqsave (&hub->tt.lock, flags); - while (--limit && !list_empty (&hub->tt.clear_list)) { + while (!list_empty(&hub->tt.clear_list)) { struct list_head *next; struct usb_tt_clear *clear; struct usb_device *hdev = hub->hdev; const struct hc_driver *drv; int status; + if (!hub->quiescing && --limit < 0) + break; + next = hub->tt.clear_list.next; clear = list_entry (next, struct usb_tt_clear, clear_list); list_del (&clear->clear_list); @@ -978,7 +981,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) if (hub->has_indicators) cancel_delayed_work_sync(&hub->leds); if (hub->tt.hub) - cancel_work_sync(&hub->tt.clear_work); + flush_work_sync(&hub->tt.clear_work); } /* caller has locked the hub device */ -- GitLab From 02c6b1fd52e8987597f847aecc3a74c09a48083b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:01 +0200 Subject: [PATCH 0876/1799] USB: whiteheat: fix memory leak in error path commit c129197c99550d356cf5f69b046994dd53cd1b9d upstream. Make sure command buffer is deallocated in case of errors during attach. Signed-off-by: Johan Hovold Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/whiteheat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 407e23c87946..171226ab56f2 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -525,6 +525,7 @@ static int whiteheat_attach(struct usb_serial *serial) "%s: please contact support@connecttech.com\n", serial->type->description); kfree(result); + kfree(command); return -ENODEV; no_command_private: -- GitLab From ce11958aa9b27e162fe2c1a23e50e318de0319c4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:11 +0200 Subject: [PATCH 0877/1799] USB: opticon: fix DMA from stack commit ea0dbebffe118724cd4df7d9b071ea8ee48d48f0 upstream. Make sure to allocate the control-message buffer dynamically as some platforms cannot do DMA from stack. Note that only the first byte of the old buffer was used. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 82cc9d202b83..c661c9c2998e 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -160,7 +160,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, { struct usb_serial *serial = port->serial; int retval; - u8 buffer[2]; + u8 *buffer; + + buffer = kzalloc(1, GFP_KERNEL); + if (!buffer) + return -ENOMEM; buffer[0] = val; /* Send the message to the vendor control endpoint @@ -169,6 +173,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, requesttype, USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, 0, 0, buffer, 1, 0); + kfree(buffer); return retval; } -- GitLab From ed7d272780f5185e9ca38cd63effd06a43c00cb1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:12 +0200 Subject: [PATCH 0878/1799] USB: opticon: fix memory leak in error path commit acbf0e5263de563e25f7c104868e4490b9e72b13 upstream. Fix memory leak in write error path. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index c661c9c2998e..1f850065d159 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -297,7 +297,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, if (!dr) { dev_err(&port->dev, "out of memory\n"); count = -ENOMEM; - goto error; + goto error_no_dr; } dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT; @@ -327,6 +327,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, return count; error: + kfree(dr); +error_no_dr: usb_free_urb(urb); error_no_urb: kfree(buffer); -- GitLab From a58af76b5dbe701c2d194648c579690ac6c29efd Mon Sep 17 00:00:00 2001 From: Lennart Sorensen Date: Wed, 24 Oct 2012 10:23:09 -0400 Subject: [PATCH 0879/1799] USB: serial: Fix memory leak in sierra_release() commit f7bc5051667b74c3861f79eed98c60d5c3b883f7 upstream. I found a memory leak in sierra_release() (well sierra_probe() I guess) that looses 8 bytes each time the driver releases a device. Signed-off-by: Len Sorensen Acked-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 449bf6d31e2a..0223ca77d2da 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -992,6 +992,7 @@ static void sierra_release(struct usb_serial *serial) continue; kfree(portdata); } + kfree(serial->private); } #ifdef CONFIG_PM -- GitLab From 96e42e6acf74ad78cf9f37c2f2f2998ad7814929 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:17 +0200 Subject: [PATCH 0880/1799] USB: sierra: fix memory leak in attach error path commit 7e41f9bcdd2e813ea2a3c40db291d87ea06b559f upstream. Make sure port private data is deallocated on errors in attach. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 0223ca77d2da..3942f12f2ef2 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -936,7 +936,7 @@ static int sierra_startup(struct usb_serial *serial) dev_dbg(&port->dev, "%s: kmalloc for " "sierra_port_private (%d) failed!\n", __func__, i); - return -ENOMEM; + goto err; } spin_lock_init(&portdata->lock); init_usb_anchor(&portdata->active); @@ -973,6 +973,13 @@ static int sierra_startup(struct usb_serial *serial) } return 0; +err: + for (--i; i >= 0; --i) { + portdata = usb_get_serial_port_data(serial->port[i]); + kfree(portdata); + } + + return -ENOMEM; } static void sierra_release(struct usb_serial *serial) -- GitLab From 5b312595bebcd2216f8617778a55ccaa93fc5a51 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:18 +0200 Subject: [PATCH 0881/1799] USB: sierra: fix memory leak in probe error path commit 084817d79399ab5ccab2f90a148b0369912a8369 upstream. Move interface data allocation to attach so that it is deallocated on errors in usb-serial probe. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 3942f12f2ef2..b622d695fdbc 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -171,7 +171,6 @@ static int sierra_probe(struct usb_serial *serial, { int result = 0; struct usb_device *udev; - struct sierra_intf_private *data; u8 ifnum; udev = serial->dev; @@ -199,11 +198,6 @@ static int sierra_probe(struct usb_serial *serial, return -ENODEV; } - data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL); - if (!data) - return -ENOMEM; - spin_lock_init(&data->susp_lock); - return result; } @@ -914,6 +908,7 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on) static int sierra_startup(struct usb_serial *serial) { struct usb_serial_port *port; + struct sierra_intf_private *intfdata; struct sierra_port_private *portdata; struct sierra_iface_info *himemoryp = NULL; int i; @@ -921,6 +916,14 @@ static int sierra_startup(struct usb_serial *serial) dev_dbg(&serial->dev->dev, "%s\n", __func__); + intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL); + if (!intfdata) + return -ENOMEM; + + spin_lock_init(&intfdata->susp_lock); + + usb_set_serial_data(serial, intfdata); + /* Set Device mode to D0 */ sierra_set_power_state(serial->dev, 0x0000); @@ -978,6 +981,7 @@ static int sierra_startup(struct usb_serial *serial) portdata = usb_get_serial_port_data(serial->port[i]); kfree(portdata); } + kfree(intfdata); return -ENOMEM; } -- GitLab From b296aacfcceb3e6511b5d5fe77b22f5840ebe290 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 13:35:09 +0200 Subject: [PATCH 0882/1799] USB: mos7840: fix urb leak at release commit 65a4cdbb170e4ec1a7fa0e94936d47e24a17b0e8 upstream. Make sure control urb is freed at release. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index c1505c3c557a..1d87d9d88d94 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2657,6 +2657,7 @@ static void mos7840_release(struct usb_serial *serial) mos7840_port = mos7840_get_port_private(serial->port[i]); dbg("mos7840_port %d = %p", i, mos7840_port); if (mos7840_port) { + usb_free_urb(mos7840_port->control_urb); kfree(mos7840_port->ctrl_buf); kfree(mos7840_port->dr); kfree(mos7840_port); -- GitLab From 45af0b209e5bdd66804a07b06dec30b5ccaef2de Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 13:35:10 +0200 Subject: [PATCH 0883/1799] USB: mos7840: fix port-device leak in error path commit 3eb55cc4ed88eee3b5230f66abcdbd2a91639eda upstream. The driver set the usb-serial port pointers to NULL on errors in attach, effectively preventing usb-serial core from decrementing the port ref counters and releasing the port devices and associated data. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 1d87d9d88d94..672894f7312f 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2590,7 +2590,6 @@ static int mos7840_startup(struct usb_serial *serial) kfree(mos7840_port->ctrl_buf); usb_free_urb(mos7840_port->control_urb); kfree(mos7840_port); - serial->port[i] = NULL; } return status; } -- GitLab From 380c05e97c6393557757dc180c04bc405de9b620 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 18:56:32 +0200 Subject: [PATCH 0884/1799] USB: mos7840: remove NULL-urb submission commit 28c3ae9a8cf45f439c9a0779ebd0256e2ae72813 upstream. The private int_urb is never allocated so the submission from the control completion handler will always fail. Remove this odd piece of broken code. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 672894f7312f..6f07880552fc 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -235,7 +235,6 @@ struct moschip_port { int port_num; /*Actual port number in the device(1,2,etc) */ struct urb *write_urb; /* write URB for this port */ struct urb *read_urb; /* read URB for this port */ - struct urb *int_urb; __u8 shadowLCR; /* last LCR value received */ __u8 shadowMCR; /* last MCR value received */ char open; @@ -505,7 +504,6 @@ static void mos7840_control_callback(struct urb *urb) unsigned char *data; struct moschip_port *mos7840_port; __u8 regval = 0x0; - int result = 0; int status = urb->status; mos7840_port = urb->context; @@ -524,7 +522,7 @@ static void mos7840_control_callback(struct urb *urb) default: dbg("%s - nonzero urb status received: %d", __func__, status); - goto exit; + return; } dbg("%s urb buffer size is %d", __func__, urb->actual_length); @@ -537,17 +535,6 @@ static void mos7840_control_callback(struct urb *urb) mos7840_handle_new_msr(mos7840_port, regval); else if (mos7840_port->MsrLsr == 1) mos7840_handle_new_lsr(mos7840_port, regval); - -exit: - spin_lock(&mos7840_port->pool_lock); - if (!mos7840_port->zombie) - result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC); - spin_unlock(&mos7840_port->pool_lock); - if (result) { - dev_err(&urb->dev->dev, - "%s - Error %d submitting interrupt urb\n", - __func__, result); - } } static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, -- GitLab From 8d649dd97f1ec8fd9c8ffd94877c5c806a202e8a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 18:56:33 +0200 Subject: [PATCH 0885/1799] USB: mos7840: remove invalid disconnect handling commit e681b66f2e19fadbe8a7e2a17900978cb6bc921f upstream. Remove private zombie flag used to signal disconnect and to prevent control urb from being submitted from interrupt urb completion handler. The control urb will not be re-submitted as both the control urb and the interrupt urb is killed on disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 6f07880552fc..0179d348c260 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -239,7 +239,6 @@ struct moschip_port { __u8 shadowMCR; /* last MCR value received */ char open; char open_ports; - char zombie; wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ int delta_msr_cond; @@ -642,14 +641,7 @@ static void mos7840_interrupt_callback(struct urb *urb) wreg = MODEM_STATUS_REGISTER; break; } - spin_lock(&mos7840_port->pool_lock); - if (!mos7840_port->zombie) { - rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); - } else { - spin_unlock(&mos7840_port->pool_lock); - return; - } - spin_unlock(&mos7840_port->pool_lock); + rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); } } } @@ -2607,9 +2599,6 @@ static void mos7840_disconnect(struct usb_serial *serial) mos7840_port = mos7840_get_port_private(serial->port[i]); dbg ("mos7840_port %d = %p", i, mos7840_port); if (mos7840_port) { - spin_lock_irqsave(&mos7840_port->pool_lock, flags); - mos7840_port->zombie = 1; - spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); usb_kill_urb(mos7840_port->control_urb); } } -- GitLab From 02b21626c5e97ab2286ed5b5a7e35181b16b9382 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 24 Oct 2012 20:37:51 +0200 Subject: [PATCH 0886/1799] vhost: fix mergeable bufs on BE hosts commit 910a578f7e9400a78a3b13aba0b4d2df16a2cb05 upstream. We copy head count to a 16 bit field, this works by chance on LE but on BE guest gets 0. Fix it up. Signed-off-by: Michael S. Tsirkin Tested-by: Alexander Graf Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/vhost/net.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 5c170100de9c..4134e53d7311 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -376,7 +376,8 @@ static void handle_rx(struct vhost_net *net) .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE }; size_t total_len = 0; - int err, headcount, mergeable; + int err, mergeable; + s16 headcount; size_t vhost_hlen, sock_hlen; size_t vhost_len, sock_len; /* TODO: check that we are running from vhost_worker? */ -- GitLab From baa526f45d3f096a1cd9f14b668203a03bbab6f9 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 17 Oct 2012 16:47:11 +0900 Subject: [PATCH 0887/1799] ARM: SAMSUNG: Add naming of s3c64xx-spi devices commit 308b3afb97dc342e9c4f958d8b4c459ae0e22bd7 upstream. Commit a5238e360b71 (spi: s3c64xx: move controller information into driver data) introduced separate device names for the different subtypes of the spi controller but forgot to set these in the relevant machines. To fix this introduce a s3c64xx_spi_setname function and populate all Samsung arches with the correct names. The function resides in a new header, as the s3c64xx-spi.h contains driver platform data and should therefore at some later point move out of the Samsung include dir. Tested on a s3c2416-based machine. Signed-off-by: Heiko Stuebner Reviewed-by: Sylwester Nawrocki [s.nawrocki@samsung.com: tested on mach-exynos] Tested-by: Sylwester Nawrocki Signed-off-by: Kukjin Kim Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-exynos/common.c | 5 ++++ arch/arm/mach-s3c24xx/s3c2416.c | 2 ++ arch/arm/mach-s3c24xx/s3c2443.c | 4 +++ arch/arm/mach-s5p64x0/common.c | 3 ++ arch/arm/mach-s5pc100/common.c | 3 ++ arch/arm/mach-s5pv210/common.c | 3 ++ arch/arm/plat-samsung/include/plat/spi-core.h | 30 +++++++++++++++++++ 7 files changed, 50 insertions(+) create mode 100644 arch/arm/plat-samsung/include/plat/spi-core.h diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 5ccd6e80a607..c2b77e5a5421 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include "common.h" @@ -338,6 +339,8 @@ static void __init exynos4_map_io(void) s5p_fb_setname(0, "exynos4-fb"); s5p_hdmi_setname("exynos4-hdmi"); + + s3c64xx_spi_setname("exynos4210-spi"); } static void __init exynos5_map_io(void) @@ -358,6 +361,8 @@ static void __init exynos5_map_io(void) s3c_i2c0_setname("s3c2440-i2c"); s3c_i2c1_setname("s3c2440-i2c"); s3c_i2c2_setname("s3c2440-i2c"); + + s3c64xx_spi_setname("exynos4210-spi"); } static void __init exynos4_init_clocks(int xtal) diff --git a/arch/arm/mach-s3c24xx/s3c2416.c b/arch/arm/mach-s3c24xx/s3c2416.c index 7743fade50df..f74818da5803 100644 --- a/arch/arm/mach-s3c24xx/s3c2416.c +++ b/arch/arm/mach-s3c24xx/s3c2416.c @@ -61,6 +61,7 @@ #include #include #include +#include static struct map_desc s3c2416_iodesc[] __initdata = { IODESC_ENT(WATCHDOG), @@ -131,6 +132,7 @@ void __init s3c2416_map_io(void) /* initialize device information early */ s3c2416_default_sdhci0(); s3c2416_default_sdhci1(); + s3c64xx_spi_setname("s3c2443-spi"); iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc)); } diff --git a/arch/arm/mach-s3c24xx/s3c2443.c b/arch/arm/mach-s3c24xx/s3c2443.c index ab648ad8fa50..165b6a6b3daa 100644 --- a/arch/arm/mach-s3c24xx/s3c2443.c +++ b/arch/arm/mach-s3c24xx/s3c2443.c @@ -43,6 +43,7 @@ #include #include #include +#include static struct map_desc s3c2443_iodesc[] __initdata = { IODESC_ENT(WATCHDOG), @@ -100,6 +101,9 @@ void __init s3c2443_map_io(void) s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull; s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull; + /* initialize device information early */ + s3c64xx_spi_setname("s3c2443-spi"); + iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc)); } diff --git a/arch/arm/mach-s5p64x0/common.c b/arch/arm/mach-s5p64x0/common.c index 6e6a0a9d6778..111e404a81fd 100644 --- a/arch/arm/mach-s5p64x0/common.c +++ b/arch/arm/mach-s5p64x0/common.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -179,6 +180,7 @@ void __init s5p6440_map_io(void) /* initialize any device information early */ s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); + s3c64xx_spi_setname("s5p64x0-spi"); s5p64x0_default_sdhci0(); s5p64x0_default_sdhci1(); @@ -193,6 +195,7 @@ void __init s5p6450_map_io(void) /* initialize any device information early */ s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); + s3c64xx_spi_setname("s5p64x0-spi"); s5p64x0_default_sdhci0(); s5p64x0_default_sdhci1(); diff --git a/arch/arm/mach-s5pc100/common.c b/arch/arm/mach-s5pc100/common.c index 621908658861..cc6e561c9958 100644 --- a/arch/arm/mach-s5pc100/common.c +++ b/arch/arm/mach-s5pc100/common.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -165,6 +166,8 @@ void __init s5pc100_map_io(void) s3c_onenand_setname("s5pc100-onenand"); s3c_fb_setname("s5pc100-fb"); s3c_cfcon_setname("s5pc100-pata"); + + s3c64xx_spi_setname("s5pc100-spi"); } void __init s5pc100_init_clocks(int xtal) diff --git a/arch/arm/mach-s5pv210/common.c b/arch/arm/mach-s5pv210/common.c index 4c9e9027df9a..a0c50efe8145 100644 --- a/arch/arm/mach-s5pv210/common.c +++ b/arch/arm/mach-s5pv210/common.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "common.h" @@ -196,6 +197,8 @@ void __init s5pv210_map_io(void) /* setup TV devices */ s5p_hdmi_setname("s5pv210-hdmi"); + + s3c64xx_spi_setname("s5pv210-spi"); } void __init s5pv210_init_clocks(int xtal) diff --git a/arch/arm/plat-samsung/include/plat/spi-core.h b/arch/arm/plat-samsung/include/plat/spi-core.h new file mode 100644 index 000000000000..0b9428ab3fc3 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/spi-core.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 Heiko Stuebner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __PLAT_S3C_SPI_CORE_H +#define __PLAT_S3C_SPI_CORE_H + +/* These functions are only for use with the core support code, such as + * the cpu specific initialisation code + */ + +/* re-define device name depending on support. */ +static inline void s3c64xx_spi_setname(char *name) +{ +#ifdef CONFIG_S3C64XX_DEV_SPI0 + s3c64xx_device_spi0.name = name; +#endif +#ifdef CONFIG_S3C64XX_DEV_SPI1 + s3c64xx_device_spi1.name = name; +#endif +#ifdef CONFIG_S3C64XX_DEV_SPI2 + s3c64xx_device_spi2.name = name; +#endif +} + +#endif /* __PLAT_S3C_SPI_CORE_H */ -- GitLab From 0a6904a552465521b33d25d767a7db06ad04e434 Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Fri, 14 Sep 2012 17:01:29 +0800 Subject: [PATCH 0888/1799] ARM: at91/tc: fix typo in the DT document commit 11930c530f3edf81160e4962e363d579f5cdce7e upstream. Signed-off-by: Josh Wu Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/arm/atmel-at91.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index ecc81e368715..d187e9f7cf1c 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -8,7 +8,7 @@ PIT Timer required properties: shared across all System Controller members. TC/TCLIB Timer required properties: -- compatible: Should be "atmel,-pit". +- compatible: Should be "atmel,-tcb". can be "at91rm9200" or "at91sam9x5" - reg: Should contain registers location and length - interrupts: Should contain all interrupts for the TC block -- GitLab From 6ff5ef252d9903de2b29dd2cdcea587d192d7635 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Mon, 15 Oct 2012 17:30:27 +0800 Subject: [PATCH 0889/1799] ARM: at91/i2c: change id to let i2c-gpio work commit 7840487cd6298f9f931103b558290d8d98d41c49 upstream. The i2c core driver will turn the platform device ID to busnum When using platfrom device ID as -1, it means dynamically assigned the busnum. When writing code, we need to make sure the busnum, and call i2c_register_board_info(int busnum, ...) to register device if using -1, we do not know the value of busnum In order to solve this issue, set the platform device ID as a fix number Here using 0 to match the busnum used in i2c_regsiter_board_info() Signed-off-by: Bo Shen Acked-by: Jean Delvare Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Ludovic Desroches Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-at91/at91rm9200_devices.c | 2 +- arch/arm/mach-at91/at91sam9260_devices.c | 2 +- arch/arm/mach-at91/at91sam9261_devices.c | 2 +- arch/arm/mach-at91/at91sam9263_devices.c | 2 +- arch/arm/mach-at91/at91sam9rl_devices.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 05774e5b1cba..3b0c719f9fe9 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -463,7 +463,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91rm9200_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 5652dde4bbe2..151fec4ccf2f 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -468,7 +468,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9260_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 4db961a93085..8a29c6cbe08c 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -285,7 +285,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9261_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index fe99206de880..8d443225266e 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -542,7 +542,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9263_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index fe4ae22e8561..b8d4114ea228 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -314,7 +314,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9rl_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; -- GitLab From adb91f6de096f878fb1cb9e0ff5839b2d432e67e Mon Sep 17 00:00:00 2001 From: Ivan Shugov Date: Wed, 24 Oct 2012 11:02:44 +0200 Subject: [PATCH 0890/1799] ARM: at91: at91sam9g10: fix SOC type detection commit 3d9a0183dd3423353e9e363bcc261c1220d05f9f upstream. Newer at91sam9g10 SoC revision can't be detected, so the kernel can't boot with this kind of kernel panic: "AT91: Impossible to detect the SOC type" CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177 CPU: VIVT data cache, VIVT instruction cache Machine: Atmel AT91SAM9G10-EK Ignoring tag cmdline (using the default kernel command line) bootconsole [earlycon0] enabled Memory policy: ECC disabled, Data cache writeback Kernel panic - not syncing: AT91: Impossible to detect the SOC type [] (unwind_backtrace+0x0/0xe0) from [] (panic+0x78/0x1cc) [] (panic+0x78/0x1cc) from [] (at91_map_io+0x90/0xc8) [] (at91_map_io+0x90/0xc8) from [] (paging_init+0x564/0x6d0) [] (paging_init+0x564/0x6d0) from [] (setup_arch+0x464/0x704) [] (setup_arch+0x464/0x704) from [] (start_kernel+0x6c/0x2d4) [] (start_kernel+0x6c/0x2d4) from [<20008040>] (0x20008040) The reason for this is that the Debug Unit Chip ID Register has changed between Engineering Sample and definitive revision of the SoC. Changing the check of cidr to socid will address the problem. We do not integrate this check to the list just above because we also have to make sure that the extended id is disregarded. Signed-off-by: Ivan Shugov [nicolas.ferre@atmel.com: change commit message] Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-at91/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index f44a2e7272e3..582142e049a8 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -146,7 +146,7 @@ static void __init soc_detect(u32 dbgu_base) } /* at91sam9g10 */ - if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) { + if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) { at91_soc_initdata.type = AT91_SOC_SAM9G10; at91_boot_soc = at91sam9261_soc; } -- GitLab From 5a01241c81ac4bf6a7a486051699f791634e7b22 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 2 Oct 2012 21:34:23 +0200 Subject: [PATCH 0891/1799] mac80211: check if key has TKIP type before updating IV commit 4045f72bcf3c293c7c5932ef001742d8bb5ded76 upstream. This patch fix corruption which can manifest itself by following crash when switching on rfkill switch with rt2x00 driver: https://bugzilla.redhat.com/attachment.cgi?id=615362 Pointer key->u.ccmp.tfm of group key get corrupted in: ieee80211_rx_h_michael_mic_verify(): /* update IV in key information to be able to detect replays */ rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32; rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16; because rt2x00 always set RX_FLAG_MMIC_STRIPPED, even if key is not TKIP. We already check type of the key in different path in ieee80211_rx_h_michael_mic_verify() function, so adding additional check here is reasonable. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/wpa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 0ae23c60968c..ea6d03bd5d5f 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -106,7 +106,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) if (status->flag & RX_FLAG_MMIC_ERROR) goto mic_fail; - if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) + if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key && + rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP) goto update_iv; return RX_CONTINUE; -- GitLab From 0fb0773f2da4ffa566e0c813dc295c44208debb5 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 11 Oct 2012 16:26:06 +0200 Subject: [PATCH 0892/1799] Bluetooth: SMP: Fix setting unknown auth_req bits commit 065a13e2cc665f6547dc7e8a9d6b6565badf940a upstream. When sending a pairing request or response we should not just blindly copy the value that the remote device sent. Instead we should at least make sure to mask out any unknown bits. This is particularly critical from the upcoming LE Secure Connections feature perspective as incorrectly indicating support for it (by copying the remote value) would cause a failure to pair with devices that support it. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/smp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 1f6cb1f1cd2d..208edc0cc60f 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -31,6 +31,8 @@ #define SMP_TIMEOUT msecs_to_jiffies(30000) +#define AUTH_REQ_MASK 0x07 + static inline void swap128(u8 src[16], u8 dst[16]) { int i; @@ -229,7 +231,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, req->max_key_size = SMP_MAX_ENC_KEY_SIZE; req->init_key_dist = 0; req->resp_key_dist = dist_keys; - req->auth_req = authreq; + req->auth_req = (authreq & AUTH_REQ_MASK); return; } @@ -238,7 +240,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; rsp->init_key_dist = 0; rsp->resp_key_dist = req->resp_key_dist & dist_keys; - rsp->auth_req = authreq; + rsp->auth_req = (authreq & AUTH_REQ_MASK); } static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) -- GitLab From a2c439d432f759533d396b31f856fcb484268104 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Thu, 25 Oct 2012 22:28:12 +0200 Subject: [PATCH 0893/1799] freezer: exec should clear PF_NOFREEZE along with PF_KTHREAD commit b40a79591ca918e7b91b0d9b6abd5d00f2e88c19 upstream. flush_old_exec() clears PF_KTHREAD but forgets about PF_NOFREEZE. Signed-off-by: Oleg Nesterov Acked-by: Tejun Heo Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- fs/exec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/exec.c b/fs/exec.c index 126e01cb2434..6c4791d4634a 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1114,7 +1114,8 @@ int flush_old_exec(struct linux_binprm * bprm) bprm->mm = NULL; /* We're using it now */ set_fs(USER_DS); - current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD); + current->flags &= + ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE); flush_thread(); current->personality &= ~bprm->per_clear; -- GitLab From 16642956664f3e93c88e9e2a22713d5456568822 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Thu, 27 Sep 2012 16:35:38 +0800 Subject: [PATCH 0894/1799] dmaengine: sirf: fix a typo in dma_prep_interleaved commit 5997e089e4c3a7f0958a8fb0a54ec2b5a6f06168 upstream. either DEV_TO_MEM or MEM_TO_DEV is supported, so change OR to AND. Signed-off-by: Barry Song Signed-off-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/sirf-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 434ad31174f2..35a329da97fd 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -428,7 +428,7 @@ static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved( unsigned long iflags; int ret; - if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) { + if ((xt->dir != DMA_MEM_TO_DEV) && (xt->dir != DMA_DEV_TO_MEM)) { ret = -EINVAL; goto err_dir; } -- GitLab From 73cb40932358f82d55117a70a0d38026923e823f Mon Sep 17 00:00:00 2001 From: Barry Song Date: Thu, 27 Sep 2012 16:36:10 +0800 Subject: [PATCH 0895/1799] dmaengine: sirf: fix a typo in moving running dma_desc to active queue commit 26fd12209c08fe947be1828896ef4ffc5bd0e6df upstream. list_move_tail(&schan->queued, &schan->active) makes the list_empty(schan->queued) undefined, we either should change it to: list_move_tail(schan->queued.next, &schan->active) or list_move_tail(&sdesc->node, &schan->active) Signed-off-by: Barry Song Signed-off-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/sirf-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 35a329da97fd..c4394892edab 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -109,7 +109,7 @@ static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan) sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc, node); /* Move the first queued descriptor to active list */ - list_move_tail(&schan->queued, &schan->active); + list_move_tail(&sdesc->node, &schan->active); /* Start the DMA transfer */ writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 + -- GitLab From 7e8cec32110be45739569e04f35d83d47064dd86 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 21 Oct 2012 19:58:30 +0800 Subject: [PATCH 0896/1799] dmaengine: imx-dma: fix missing unlock on error in imxdma_xfer_desc() commit 720dfd250e48a8c7fd1b2b8645955413989c4ee0 upstream. Add the missing unlock on the error handling path in function imxdma_xfer_desc(). Signed-off-by: Wei Yongjun Signed-off-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/imx-dma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index bb787d8e1529..180f5235acc2 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -473,8 +473,10 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) slot = i; break; } - if (slot < 0) + if (slot < 0) { + spin_unlock_irqrestore(&imxdma->lock, flags); return -EBUSY; + } imxdma->slots_2d[slot].xsr = d->x; imxdma->slots_2d[slot].ysr = d->y; -- GitLab From 44b977a87305bb075adb5b764f115237e474e626 Mon Sep 17 00:00:00 2001 From: Piotr Haber Date: Thu, 11 Oct 2012 14:05:15 +0200 Subject: [PATCH 0897/1799] bcma: fix unregistration of cores commit 1fffa905adffbf0d3767fc978ef09afb830275eb upstream. When cores are unregistered, entries need to be removed from cores list in a safe manner. Reported-by: Stanislaw Gruszka Reviewed-by: Arend Van Spriel Signed-off-by: Piotr Haber Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/bcma/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 7e138ec21357..edb9233b26d2 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -131,9 +131,10 @@ static int bcma_register_cores(struct bcma_bus *bus) static void bcma_unregister_cores(struct bcma_bus *bus) { - struct bcma_device *core; + struct bcma_device *core, *tmp; - list_for_each_entry(core, &bus->cores, list) { + list_for_each_entry_safe(core, tmp, &bus->cores, list) { + list_del(&core->list); if (core->dev_registered) device_unregister(&core->dev); } -- GitLab From 0b79a8a53612672adf053aaebb74ebc51a44e321 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Tue, 23 Oct 2012 00:55:10 +0200 Subject: [PATCH 0898/1799] cpufreq / powernow-k8: Remove usage of smp_processor_id() in preemptible code commit e4df1cbcc1f329e53a1fff7450b2229e0addff20 upstream. Commit 6889125b8b4e09c5e53e6ecab3433bed1ce198c9 (cpufreq/powernow-k8: workqueue user shouldn't migrate the kworker to another CPU) causes powernow-k8 to trigger a preempt warning, e.g.: BUG: using smp_processor_id() in preemptible [00000000] code: cpufreq/3776 caller is powernowk8_target+0x20/0x49 Pid: 3776, comm: cpufreq Not tainted 3.6.0 #9 Call Trace: [] debug_smp_processor_id+0xc7/0xe0 [] powernowk8_target+0x20/0x49 [] __cpufreq_driver_target+0x82/0x8a [] cpufreq_governor_performance+0x4e/0x54 [] __cpufreq_governor+0x8c/0xc9 [] __cpufreq_set_policy+0x1a9/0x21e [] store_scaling_governor+0x16f/0x19b [] ? cpufreq_update_policy+0x124/0x124 [] ? _raw_spin_unlock_irqrestore+0x2c/0x49 [] store+0x60/0x88 [] sysfs_write_file+0xf4/0x130 [] vfs_write+0xb5/0x151 [] sys_write+0x4a/0x71 [] system_call_fastpath+0x16/0x1b Fix this by by always using work_on_cpu(). Signed-off-by: Andreas Herrmann Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/cpufreq/powernow-k8.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 1a40935c85fd..c671369a05bf 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1223,14 +1223,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq, .relation = relation }; - /* - * Must run on @pol->cpu. cpufreq core is responsible for ensuring - * that we're bound to the current CPU and pol->cpu stays online. - */ - if (smp_processor_id() == pol->cpu) - return powernowk8_target_fn(&pta); - else - return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); + return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); } /* Driver entry point to verify the policy and range of frequencies */ -- GitLab From 6c422bb689034ce2c2b781754b03fb93bc67fa78 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 17 Oct 2012 13:50:43 +0200 Subject: [PATCH 0899/1799] Revert "ath9k_hw: Updated AR9003 tx gain table for 5GHz" commit 73b26df5fa1a6245d6fc982362518b620bc7c2fe upstream. This reverts commit a240dc7b3c7463bd60cf0a9b2a90f52f78aae0fd. This commit is reducing tx power by at least 10 db on some devices, e.g. the Buffalo WZR-HP-G450H. Signed-off-by: Felix Fietkau Cc: rmanohar@qca.qualcomm.com Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- .../wireless/ath/ath9k/ar9003_2p2_initvals.h | 164 +++++++++--------- 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 46c79a3d4737..2b4b63318da6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -533,107 +533,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = { static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400}, - {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402}, - {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404}, - {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640}, - {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400}, - {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402}, - {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, + {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, + {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000}, - {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501}, - {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501}, - {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, + {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, + {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; -- GitLab From 3fd37d2b84e53427b10e6900f7039f9ea9c3a408 Mon Sep 17 00:00:00 2001 From: Jacob Shin Date: Wed, 24 Oct 2012 14:24:44 -0500 Subject: [PATCH 0900/1799] x86, mm: Find_early_table_space based on ranges that are actually being mapped commit 844ab6f993b1d32eb40512503d35ff6ad0c57030 upstream. Current logic finds enough space for direct mapping page tables from 0 to end. Instead, we only need to find enough space to cover mr[0].start to mr[nr_range].end -- the range that is actually being mapped by init_memory_mapping() This is needed after 1bbbbe779aabe1f0768c2bf8f8c0a5583679b54a, to address the panic reported here: https://lkml.org/lkml/2012/10/20/160 https://lkml.org/lkml/2012/10/21/157 Signed-off-by: Jacob Shin Link: http://lkml.kernel.org/r/20121024195311.GB11779@jshin-Toonie Tested-by: Tom Rini Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/init.c | 73 +++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 4f0cec7e4ffb..6ef7a6344fa8 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -29,36 +29,54 @@ int direct_gbpages #endif ; -static void __init find_early_table_space(unsigned long end, int use_pse, - int use_gbpages) +struct map_range { + unsigned long start; + unsigned long end; + unsigned page_size_mask; +}; + +/* + * First calculate space needed for kernel direct mapping page tables to cover + * mr[0].start to mr[nr_range - 1].end, while accounting for possible 2M and 1GB + * pages. Then find enough contiguous space for those page tables. + */ +static void __init find_early_table_space(struct map_range *mr, int nr_range) { - unsigned long puds, pmds, ptes, tables, start = 0, good_end = end; + int i; + unsigned long puds = 0, pmds = 0, ptes = 0, tables; + unsigned long start = 0, good_end; phys_addr_t base; - puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; - tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); + for (i = 0; i < nr_range; i++) { + unsigned long range, extra; - if (use_gbpages) { - unsigned long extra; + range = mr[i].end - mr[i].start; + puds += (range + PUD_SIZE - 1) >> PUD_SHIFT; - extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT); - pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT; - } else - pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; - - tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); + if (mr[i].page_size_mask & (1 << PG_LEVEL_1G)) { + extra = range - ((range >> PUD_SHIFT) << PUD_SHIFT); + pmds += (extra + PMD_SIZE - 1) >> PMD_SHIFT; + } else { + pmds += (range + PMD_SIZE - 1) >> PMD_SHIFT; + } - if (use_pse) { - unsigned long extra; - - extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT); + if (mr[i].page_size_mask & (1 << PG_LEVEL_2M)) { + extra = range - ((range >> PMD_SHIFT) << PMD_SHIFT); #ifdef CONFIG_X86_32 - extra += PMD_SIZE; + extra += PMD_SIZE; #endif - ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; - } else - ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; + /* The first 2/4M doesn't use large pages. */ + if (mr[i].start < PMD_SIZE) + extra += range; + + ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; + } else { + ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT; + } + } + tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); + tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE); #ifdef CONFIG_X86_32 @@ -75,8 +93,9 @@ static void __init find_early_table_space(unsigned long end, int use_pse, pgt_buf_end = pgt_buf_start; pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT); - printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n", - end, pgt_buf_start << PAGE_SHIFT, pgt_buf_top << PAGE_SHIFT); + printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n", + mr[nr_range - 1].end - 1, pgt_buf_start << PAGE_SHIFT, + (pgt_buf_top << PAGE_SHIFT) - 1); } void __init native_pagetable_reserve(u64 start, u64 end) @@ -84,12 +103,6 @@ void __init native_pagetable_reserve(u64 start, u64 end) memblock_reserve(start, end - start); } -struct map_range { - unsigned long start; - unsigned long end; - unsigned page_size_mask; -}; - #ifdef CONFIG_X86_32 #define NR_RANGE_MR 3 #else /* CONFIG_X86_64 */ @@ -261,7 +274,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, * nodes are discovered. */ if (!after_bootmem) - find_early_table_space(end, use_pse, use_gbpages); + find_early_table_space(mr, nr_range); for (i = 0; i < nr_range; i++) ret = kernel_physical_mapping_init(mr[i].start, mr[i].end, -- GitLab From 7a32a0b9985742493575ffa1c6fedf043d966708 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 25 Oct 2012 15:45:26 -0700 Subject: [PATCH 0901/1799] x86, mm: Undo incorrect revert in arch/x86/mm/init.c commit f82f64dd9f485e13f29f369772d4a0e868e5633a upstream. Commit 844ab6f9 x86, mm: Find_early_table_space based on ranges that are actually being mapped added back some lines back wrongly that has been removed in commit 7b16bbf97 Revert "x86/mm: Fix the size calculation of mapping tables" remove them again. Signed-off-by: Yinghai Lu Link: http://lkml.kernel.org/r/CAE9FiQW_vuaYQbmagVnxT2DGsYc=9tNeAbdBq53sYkitPOwxSQ@mail.gmail.com Acked-by: Jacob Shin Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/init.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 6ef7a6344fa8..fae70904ed08 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -65,10 +65,6 @@ static void __init find_early_table_space(struct map_range *mr, int nr_range) #ifdef CONFIG_X86_32 extra += PMD_SIZE; #endif - /* The first 2/4M doesn't use large pages. */ - if (mr[i].start < PMD_SIZE) - extra += range; - ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; } else { ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT; -- GitLab From a57a57aea0ad2ced60a8aa59d49fe542f23efb72 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 28 Sep 2012 17:55:44 -0700 Subject: [PATCH 0902/1799] efi: Defer freeing boot services memory until after ACPI init commit 785107923a83d8456bbd8564e288a24d84109a46 upstream. Some new ACPI 5.0 tables reference resources stored in boot services memory, so keep that memory around until we have ACPI and can extract data from it. Signed-off-by: Josh Triplett Link: http://lkml.kernel.org/r/baaa6d44bdc4eb0c58e5d1b4ccd2c729f854ac55.1348876882.git.josh@joshtriplett.org Signed-off-by: H. Peter Anvin Cc: Matt Fleming Signed-off-by: Greg Kroah-Hartman --- arch/x86/platform/efi/efi.c | 31 ++++++++++++++++++------------- include/linux/efi.h | 5 +++++ init/main.c | 3 +++ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index f55a4ce6dc49..b3dbbdbd2a42 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -419,10 +419,21 @@ void __init efi_reserve_boot_services(void) } } -static void __init efi_free_boot_services(void) +static void __init efi_unmap_memmap(void) +{ + if (memmap.map) { + early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); + memmap.map = NULL; + } +} + +void __init efi_free_boot_services(void) { void *p; + if (!efi_native) + return; + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { efi_memory_desc_t *md = p; unsigned long long start = md->phys_addr; @@ -438,6 +449,8 @@ static void __init efi_free_boot_services(void) free_bootmem_late(start, size); } + + efi_unmap_memmap(); } static int __init efi_systab_init(void *phys) @@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void) * non-native EFI */ - if (!efi_native) - goto out; + if (!efi_native) { + efi_unmap_memmap(); + return; + } /* Merge contiguous regions of the same type and attribute */ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { @@ -877,13 +892,6 @@ void __init efi_enter_virtual_mode(void) panic("EFI call to SetVirtualAddressMap() failed!"); } - /* - * Thankfully, it does seem that no runtime services other than - * SetVirtualAddressMap() will touch boot services code, so we can - * get rid of it all at this point - */ - efi_free_boot_services(); - /* * Now that EFI is in virtual mode, update the function * pointers in the runtime service table to the new virtual addresses. @@ -907,9 +915,6 @@ void __init efi_enter_virtual_mode(void) if (__supported_pte_mask & _PAGE_NX) runtime_code_page_mkexec(); -out: - early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); - memmap.map = NULL; kfree(new_memmap); } diff --git a/include/linux/efi.h b/include/linux/efi.h index ec45ccd8708a..5782114f4838 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -496,6 +496,11 @@ extern void efi_map_pal_code (void); extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); extern void efi_gettimeofday (struct timespec *ts); extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ +#ifdef CONFIG_X86 +extern void efi_free_boot_services(void); +#else +static inline void efi_free_boot_services(void) {} +#endif extern u64 efi_get_iobase (void); extern u32 efi_mem_type (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr); diff --git a/init/main.c b/init/main.c index b08c5f75974f..c2178d267c1a 100644 --- a/init/main.c +++ b/init/main.c @@ -630,6 +630,9 @@ asmlinkage void __init start_kernel(void) acpi_early_init(); /* before LAPIC and SMP init */ sfi_init_late(); + if (efi_enabled) + efi_free_boot_services(); + ftrace_init(); /* Do the rest non-__init'ed, we're now alive */ -- GitLab From 775dc1a3fd51abc6e459aa92e049fd3687b66c2f Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 24 Oct 2012 10:00:44 -0700 Subject: [PATCH 0903/1799] x86: efi: Turn off efi_enabled after setup on mixed fw/kernel commit 5189c2a7c7769ee9d037d76c1a7b8550ccf3481c upstream. When 32-bit EFI is used with 64-bit kernel (or vice versa), turn off efi_enabled once setup is done. Beyond setup, it is normally used to determine if runtime services are available and we will have none. This will resolve issues stemming from efivars modprobe panicking on a 32/64-bit setup, as well as some reboot issues on similar setups. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45991 Reported-by: Marko Kohtala Reported-by: Maxim Kammerer Signed-off-by: Olof Johansson Acked-by: Maarten Lankhorst Cc: Matthew Garrett Signed-off-by: Matt Fleming Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/efi.h | 1 + arch/x86/kernel/setup.c | 12 ++++++++++++ arch/x86/platform/efi/efi.c | 18 ++++++++++-------- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index c9dcc181d4d1..029189db84de 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -98,6 +98,7 @@ extern void efi_set_executable(efi_memory_desc_t *md, bool executable); extern int efi_memblock_x86_reserve_range(void); extern void efi_call_phys_prelog(void); extern void efi_call_phys_epilog(void); +extern void efi_unmap_memmap(void); #ifndef CONFIG_EFI /* diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index fbbd1eb6c68e..031979840367 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1053,6 +1053,18 @@ void __init setup_arch(char **cmdline_p) mcheck_init(); arch_init_ideal_nops(); + +#ifdef CONFIG_EFI + /* Once setup is done above, disable efi_enabled on mismatched + * firmware/kernel archtectures since there is no support for + * runtime services. + */ + if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) { + pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); + efi_unmap_memmap(); + efi_enabled = 0; + } +#endif } #ifdef CONFIG_X86_32 diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index b3dbbdbd2a42..72d88992f384 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -69,11 +69,15 @@ EXPORT_SYMBOL(efi); struct efi_memory_map memmap; bool efi_64bit; -static bool efi_native; static struct efi efi_phys __initdata; static efi_system_table_t efi_systab __initdata; +static inline bool efi_is_native(void) +{ + return IS_ENABLED(CONFIG_X86_64) == efi_64bit; +} + static int __init setup_noefi(char *arg) { efi_enabled = 0; @@ -419,7 +423,7 @@ void __init efi_reserve_boot_services(void) } } -static void __init efi_unmap_memmap(void) +void __init efi_unmap_memmap(void) { if (memmap.map) { early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); @@ -431,7 +435,7 @@ void __init efi_free_boot_services(void) { void *p; - if (!efi_native) + if (!efi_is_native()) return; for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { @@ -683,12 +687,10 @@ void __init efi_init(void) return; } efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; - efi_native = !efi_64bit; #else efi_phys.systab = (efi_system_table_t *) (boot_params.efi_info.efi_systab | ((__u64)boot_params.efi_info.efi_systab_hi<<32)); - efi_native = efi_64bit; #endif if (efi_systab_init(efi_phys.systab)) { @@ -722,7 +724,7 @@ void __init efi_init(void) * that doesn't match the kernel 32/64-bit mode. */ - if (!efi_native) + if (!efi_is_native()) pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); else if (efi_runtime_init()) { efi_enabled = 0; @@ -734,7 +736,7 @@ void __init efi_init(void) return; } #ifdef CONFIG_X86_32 - if (efi_native) { + if (efi_is_native()) { x86_platform.get_wallclock = efi_get_time; x86_platform.set_wallclock = efi_set_rtc_mmss; } @@ -800,7 +802,7 @@ void __init efi_enter_virtual_mode(void) * non-native EFI */ - if (!efi_native) { + if (!efi_is_native()) { efi_unmap_memmap(); return; } -- GitLab From a0419caba889d9a5f743a51b7cf9269c16c397a5 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 3 Oct 2012 16:25:17 +0100 Subject: [PATCH 0904/1799] staging: comedi: amplc_pc236: fix invalid register access during detach commit aaeb61a97b7159ebe30b18a422d04eeabfa8790b upstream. `pc236_detach()` is called by the comedi core if it attempted to attach a device and failed. `pc236_detach()` calls `pc236_intr_disable()` if the comedi device private data pointer (`devpriv`) is non-null. This test is insufficient as `pc236_intr_disable()` accesses hardware registers and the attach routine may have failed before it has saved their I/O base addresses. Fix it by checking `dev->iobase` is non-zero before calling `pc236_intr_disable()` as that means the I/O base addresses have been saved and the hardware registers can be accessed. It also implies the comedi device private data pointer is valid, so there is no need to check it. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 7972cadd403e..9a23d20938a5 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -468,7 +468,7 @@ static int pc236_detach(struct comedi_device *dev) { printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor, PC236_DRIVER_NAME); - if (devpriv) + if (dev->iobase) pc236_intr_disable(dev); if (dev->irq) -- GitLab From 0187c24809c9590412c0112dab88f28621a961ed Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Oct 2012 16:35:18 -0700 Subject: [PATCH 0905/1799] x86, mm: Use memblock memory loop instead of e820_RAM commit 1f2ff682ac951ed82cc043cf140d2851084512df upstream. We need to handle E820_RAM and E820_RESERVED_KERNEL at the same time. Also memblock has page aligned range for ram, so we could avoid mapping partial pages. Signed-off-by: Yinghai Lu Link: http://lkml.kernel.org/r/CAE9FiQVZirvaBMFYRfXMmWEcHbKSicQEHz4VAwUv0xFCk51ZNw@mail.gmail.com Acked-by: Jacob Shin Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/setup.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 031979840367..ae98dbb5b8c1 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -928,18 +928,19 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_X86_64 if (max_pfn > max_low_pfn) { int i; - for (i = 0; i < e820.nr_map; i++) { - struct e820entry *ei = &e820.map[i]; + unsigned long start, end; + unsigned long start_pfn, end_pfn; - if (ei->addr + ei->size <= 1UL << 32) - continue; + for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, + NULL) { - if (ei->type == E820_RESERVED) + end = PFN_PHYS(end_pfn); + if (end <= (1UL<<32)) continue; + start = PFN_PHYS(start_pfn); max_pfn_mapped = init_memory_mapping( - ei->addr < 1UL << 32 ? 1UL << 32 : ei->addr, - ei->addr + ei->size); + max((1UL<<32), start), end); } /* can we preseve max_low_pfn ?*/ -- GitLab From 1f94bd43033d37549313c2b3cc2447800a20291c Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Fri, 22 Jun 2012 09:43:07 +0200 Subject: [PATCH 0906/1799] drm/i915: no lvds quirk for Zotac ZDBOX SD ID12/ID13 commit 9756fe38d10b2bf90c81dc4d2f17d5632e135364 upstream. This box claims to have an LVDS interface but doesn't actually have one. Signed-off-by: Sjoerd Simons Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- 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 9fadd6431815..4ff7d5f06da6 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -777,6 +777,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "MS-7469"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "ZOTAC ZBOXSD-ID12/ID13", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"), + DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), + }, + }, { } /* terminating entry */ }; -- GitLab From 5390967b2f98e6aa46f20eae09580e7db73826b9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Oct 2012 10:05:17 -0700 Subject: [PATCH 0907/1799] Linux 3.4.17 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 470d96b8ba6d..3f9f0762e88e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 16 +SUBLEVEL = 17 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 0d819068496793d2f8ef48a6fcec4c7d329d8b8a Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Sun, 28 Oct 2012 22:24:57 -0400 Subject: [PATCH 0908/1799] ext4: fix unjournaled inode bitmap modification commit ffb5387e85d528fb6d0d924abfa3fbf0fc484071 upstream. commit 119c0d4460b001e44b41dcf73dc6ee794b98bd31 changed ext4_new_inode() such that the inode bitmap was being modified outside a transaction, which could lead to corruption, and was discovered when journal_checksum found a bad checksum in the journal during log replay. Nix ran into this when using the journal_async_commit mount option, which enables journal checksumming. The ensuing journal replay failures due to the bad checksums led to filesystem corruption reported as the now infamous "Apparent serious progressive ext4 data corruption bug" [ Changed by tytso to only call ext4_journal_get_write_access() only when we're fairly certain that we're going to allocate the inode. ] I've tested this by mounting with journal_checksum and running fsstress then dropping power; I've also tested by hacking DM to create snapshots w/o first quiescing, which allows me to test journal replay repeatedly w/o actually power-cycling the box. Without the patch I hit a journal checksum error every time. With this fix it survives many iterations. Reported-by: Nix Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/ialloc.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 0ee374d27fdb..556cc821652c 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -697,6 +697,10 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, "inode=%lu", ino + 1); continue; } + BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); + err = ext4_journal_get_write_access(handle, inode_bitmap_bh); + if (err) + goto fail; ext4_lock_group(sb, group); ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data); ext4_unlock_group(sb, group); @@ -710,6 +714,11 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, goto out; got: + BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); + err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); + if (err) + goto fail; + /* We may have to initialize the block bitmap if it isn't already */ if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM) && gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { @@ -742,11 +751,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, goto fail; } - BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); - err = ext4_journal_get_write_access(handle, inode_bitmap_bh); - if (err) - goto fail; - BUFFER_TRACE(group_desc_bh, "get_write_access"); err = ext4_journal_get_write_access(handle, group_desc_bh); if (err) @@ -789,11 +793,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, ext4_unlock_group(sb, group); } - BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); - err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); - if (err) - goto fail; - BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata"); err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh); if (err) -- GitLab From 0659a3107481012c778d9e249a3561474a4b4a7d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 11 Oct 2012 09:56:35 +0300 Subject: [PATCH 0909/1799] gpio-timberdale: fix a potential wrapping issue commit d79550a7bc35c16476ebdc27c78378d8093390ec upstream. ->last_ier is an unsigned long but the high bits can't be used int the original code because the shift wraps. Signed-off-by: Dan Carpenter Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpio-timberdale.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 031c6adf5b65..1a3e2b9b4772 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d) unsigned long flags; spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier &= ~(1 << offset); + tgpio->last_ier &= ~(1UL << offset); iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); spin_unlock_irqrestore(&tgpio->lock, flags); } @@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d) unsigned long flags; spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier |= 1 << offset; + tgpio->last_ier |= 1UL << offset; iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); spin_unlock_irqrestore(&tgpio->lock, flags); } -- GitLab From e7355f1112773a015e914b4f815460b7bbe88954 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 25 Oct 2012 14:03:03 +0300 Subject: [PATCH 0910/1799] gpiolib: Don't return -EPROBE_DEFER to sysfs, or for invalid gpios commit ad2fab36d7922401c4576fb7ea9b21a47a29a17f upstream. gpios requested with invalid numbers, or gpios requested from userspace via sysfs should not try to be deferred on failure. Signed-off-by: Mathias Nyman Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpiolib.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5a75510d66bb..112c16e08471 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class, */ status = gpio_request(gpio, "sysfs"); - if (status < 0) + if (status < 0) { + if (status == -EPROBE_DEFER) + status = -ENODEV; goto done; - + } status = gpio_export(gpio, true); if (status < 0) gpio_free(gpio); @@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label) spin_lock_irqsave(&gpio_lock, flags); - if (!gpio_is_valid(gpio)) + if (!gpio_is_valid(gpio)) { + status = -EINVAL; goto done; + } desc = &gpio_desc[gpio]; chip = desc->chip; if (chip == NULL) -- GitLab From 32f25ea28ad28fbb4080d0b7a279279c7e21b1d0 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 31 Oct 2012 11:42:03 +1100 Subject: [PATCH 0911/1799] md/raid1: Fix assembling of arrays containing Replacements. commit 02b898f2f04e418094f0093a3ad0b415bcdbe8eb upstream. setup_conf in raid1.c uses conf->raid_disks before assigning a value. It is used when including 'Replacement' devices. The consequence is that assembling an array which contains a replacement will misbehave and either not include the replacement, or not include the device being replaced. Though this doesn't lead directly to data corruption, it could lead to reduced data safety. So use mddev->raid_disks, which is initialised, instead. Bug was introduced by commit c19d57980b38a5bb613a898937a1cf85f422fb9b md/raid1: recognise replacements when assembling arrays. in 3.3, so fix is suitable for 3.3.y thru 3.6.y. Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 23904d233735..df445091384a 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2564,7 +2564,7 @@ static struct r1conf *setup_conf(struct mddev *mddev) || disk_idx < 0) continue; if (test_bit(Replacement, &rdev->flags)) - disk = conf->mirrors + conf->raid_disks + disk_idx; + disk = conf->mirrors + mddev->raid_disks + disk_idx; else disk = conf->mirrors + disk_idx; -- GitLab From 7db4c1707a323c62fa3d8e6c58d197d23c02fdfc Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Mon, 27 Aug 2012 20:56:52 -0300 Subject: [PATCH 0912/1799] floppy: do put_disk on current dr if blk_init_queue fails commit 238ab78469c6ab7845b43d5061cd3c92331b2452 upstream. If blk_init_queue fails, we do not call put_disk on the current dr (dr is decremented first in the error handling loop). Reviewed-by: Ben Hutchings Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Jiri Kosina Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/floppy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index b0b00d70c166..c82f06e639f8 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4161,6 +4161,7 @@ static int __init floppy_init(void) disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); if (!disks[dr]->queue) { + put_disk(disks[dr]); err = -ENOMEM; goto out_put_disk; } -- GitLab From 4bd1d456218f48e77be45feaadcacce29ce6e3ac Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 24 Oct 2012 08:57:16 -0500 Subject: [PATCH 0913/1799] b43: Fix oops on unload when firmware not found commit f89ff6441df06abc2d95f3ef67525923032d6283 upstream. When b43 fails to find firmware when loaded, a subsequent unload will oops due to calling ieee80211_unregister_hw() when the corresponding register call was never made. Commit 2d838bb608e2d1f6cb4280e76748cb812dc822e7 fixed the same problem for b43legacy. Signed-off-by: Larry Finger Tested-by: Markus Kanet Cc: Markus Kanet Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/b43/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index e4d6dc2e37d1..d6ffd434f413 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -5430,6 +5430,8 @@ static void b43_ssb_remove(struct ssb_device *sdev) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); + if (!wldev->fw.ucode.data) + return; /* NULL if firmware never loaded */ if (wl->current_dev == wldev) { /* Restore the queues count before unregistering, because firmware detect * might have modified it. Restoring is important, so the networking -- GitLab From 8c9c9dfcd1d31e2f149ea991f15bfdd4b5e1496e Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 26 Oct 2012 15:35:45 -0700 Subject: [PATCH 0914/1799] target: Fix double-free of se_cmd in target_complete_tmr_failure commit e13d5fef88c40b87c8430f8274c3a9ca32ef90bc upstream. Fabric drivers currently expect to internally release se_cmd in the event of a TMR failure during target_submit_tmr(), which means the immediate call to transport_generic_free_cmd() after TFO->queue_tm_rsp() from within target_complete_tmr_failure() workqueue context is wrong. This is done as some fabrics expect TMR operations to be acknowledged before releasing the descriptor, so the assumption that core is releasing se_cmd associated TMR memory is incorrect. This fixes a OOPs where transport_generic_free_cmd() was being called more than once. This bug was originally observed with tcm_qla2xxx fabric ports. Signed-off-by: Nicholas Bellinger Cc: Christoph Hellwig Cc: Roland Dreier Cc: Andy Grover Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_transport.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index d594460ed988..69f3f7d53a04 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1748,7 +1748,6 @@ static void target_complete_tmr_failure(struct work_struct *work) se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; se_cmd->se_tfo->queue_tm_rsp(se_cmd); - transport_generic_free_cmd(se_cmd, 0); } /** -- GitLab From ac219f9df7c4dc152bc33e7dbe0573a1764d741c Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 19 Oct 2012 13:28:46 +0200 Subject: [PATCH 0915/1799] HID: microsoft: fix invalid rdesc for 3k kbd commit 3ccc60f9d8c39180c205dba1a020735bda1b2491 upstream. Microsoft Digital Media Keyboard 3000 has two interfaces, and the second one has a report descriptor with a bug. The second collection says: 05 01 -- global; usage page -- 01 -- Generic Desktop Controls 09 80 -- local; usage -- 80 -- System Control a1 01 -- main; collection -- 01 -- application 85 03 -- global; report ID -- 03 19 00 -- local; Usage Minimum -- 00 29 ff -- local; Usage Maximum -- ff 15 00 -- global; Logical Minimum -- 0 26 ff 00 -- global; Logical Maximum -- ff 81 00 -- main; input c0 -- main; End Collection I.e. it makes us think that there are all kinds of usages of system control. That the keyboard is a not only a keyboard, but also a joystick, mouse, gamepad, keypad, etc. The same as for the Wireless Desktop Receiver, this should be Physical Min/Max. So fix that appropriately. References: https://bugzilla.novell.com/show_bug.cgi?id=776834 Signed-off-by: Jiri Slaby Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-microsoft.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index e5c699b6c6f3..38999898d041 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -29,22 +29,30 @@ #define MS_RDESC 0x08 #define MS_NOGET 0x10 #define MS_DUPLICATE_USAGES 0x20 +#define MS_RDESC_3K 0x40 -/* - * Microsoft Wireless Desktop Receiver (Model 1028) has - * 'Usage Min/Max' where it ought to have 'Physical Min/Max' - */ static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); + /* + * Microsoft Wireless Desktop Receiver (Model 1028) has + * 'Usage Min/Max' where it ought to have 'Physical Min/Max' + */ if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 && rdesc[559] == 0x29) { hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n"); rdesc[557] = 0x35; rdesc[559] = 0x45; } + /* the same as above (s/usage/physical/) */ + if ((quirks & MS_RDESC_3K) && *rsize == 106 && + !memcmp((char []){ 0x19, 0x00, 0x29, 0xff }, + &rdesc[94], 4)) { + rdesc[94] = 0x35; + rdesc[96] = 0x45; + } return rdesc; } @@ -193,7 +201,7 @@ static const struct hid_device_id ms_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB), .driver_data = MS_PRESENTER }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K), - .driver_data = MS_ERGONOMY }, + .driver_data = MS_ERGONOMY | MS_RDESC_3K }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0), .driver_data = MS_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), -- GitLab From ba76a5d4ee853b23e8bbc2d6a5acbb6f8d743dcd Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 29 Oct 2012 09:03:07 +1000 Subject: [PATCH 0916/1799] drm/nouveau: silence modesetting spam on pre-gf8 chipsets commit cee59f15a60cc6269a25e3f6fbf1a577d6ab8115 upstream. Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nv04_dac.c | 8 ++++---- drivers/gpu/drm/nouveau/nv04_dfp.c | 6 +++--- drivers/gpu/drm/nouveau/nv04_tv.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index 8300266ffaea..f180dcfb12fd 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -210,7 +210,7 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode); if (blue == 0x18) { - NV_INFO(dev, "Load detected on head A\n"); + NV_DEBUG(dev, "Load detected on head A\n"); return connector_status_connected; } @@ -323,7 +323,7 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) if (nv17_dac_sample_load(encoder) & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { - NV_INFO(dev, "Load detected on output %c\n", + NV_DEBUG(dev, "Load detected on output %c\n", '@' + ffs(dcb->or)); return connector_status_connected; } else { @@ -398,7 +398,7 @@ static void nv04_dac_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + NV_DEBUG(dev, "Output %s is running on CRTC %d using output %c\n", drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } @@ -447,7 +447,7 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(dev, "Setting dpms mode %d on vga encoder (output %d)\n", + NV_DEBUG(dev, "Setting dpms mode %d on vga encoder (output %d)\n", mode, nv_encoder->dcb->index); nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 2258746016f8..473f30a4194a 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -476,7 +476,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + NV_DEBUG(dev, "Output %s is running on CRTC %d using output %c\n", drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } @@ -519,7 +519,7 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(dev, "Setting dpms mode %d on lvds encoder (output %d)\n", + NV_DEBUG(dev, "Setting dpms mode %d on lvds encoder (output %d)\n", mode, nv_encoder->dcb->index); if (was_powersaving && is_powersaving_dpms(mode)) @@ -564,7 +564,7 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(dev, "Setting dpms mode %d on tmds encoder (output %d)\n", + NV_DEBUG(dev, "Setting dpms mode %d on tmds encoder (output %d)\n", mode, nv_encoder->dcb->index); nv04_dfp_update_backlight(encoder, mode); diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 3eb605ddfd03..4de1fbeb8497 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c @@ -69,7 +69,7 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) struct nv04_mode_state *state = &dev_priv->mode_reg; uint8_t crtc1A; - NV_INFO(dev, "Setting dpms mode %d on TV encoder (output %d)\n", + NV_DEBUG(dev, "Setting dpms mode %d on TV encoder (output %d)\n", mode, nv_encoder->dcb->index); state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); @@ -162,7 +162,7 @@ static void nv04_tv_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + NV_DEBUG(dev, "Output %s is running on CRTC %d using output %c\n", drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } -- GitLab From de540b704e2ba5681f5e697aa14cfd4e739b42ef Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 1 Nov 2012 16:16:31 +1000 Subject: [PATCH 0917/1799] drm/nouveau: fix suspend/resume when in headless mode Backport of fixes from upstream commit: 9430738d80223a1cd791a2baa74fa170d3df1262 Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nouveau_drv.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 4f2030bd5676..b5232582d1e8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -186,11 +186,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; - NV_INFO(dev, "Disabling display...\n"); - nouveau_display_fini(dev); + if (dev->mode_config.num_crtc) { + NV_INFO(dev, "Disabling display...\n"); + nouveau_display_fini(dev); - NV_INFO(dev, "Disabling fbcon...\n"); - nouveau_fbcon_set_suspend(dev, 1); + NV_INFO(dev, "Disabling fbcon...\n"); + nouveau_fbcon_set_suspend(dev, 1); + } NV_INFO(dev, "Unpinning framebuffer(s)...\n"); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -363,10 +365,12 @@ nouveau_pci_resume(struct pci_dev *pdev) NV_ERROR(dev, "Could not pin/map cursor.\n"); } - nouveau_fbcon_set_suspend(dev, 0); - nouveau_fbcon_zfill_all(dev); + if (dev->mode_config.num_crtc) { + nouveau_fbcon_set_suspend(dev, 0); + nouveau_fbcon_zfill_all(dev); - nouveau_display_init(dev); + nouveau_display_init(dev); + } /* Force CLUT to get re-loaded during modeset */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { -- GitLab From 88f002cc7c9c55f40bdaaa720a39b6484cdfbb3f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 1 Nov 2012 16:16:32 +1000 Subject: [PATCH 0918/1799] drm/nouveau: headless mode by default if pci class != vga display This is to prevent nouveau from taking over the console on headless boards such as Tesla. Backport of upstream commit: e412e95a268fa8544858ebfe066826b290430d51 Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nouveau_drv.c | 2 -- drivers/gpu/drm/nouveau/nouveau_state.c | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index b5232582d1e8..05091c22a037 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -472,9 +472,7 @@ static int __init nouveau_init(void) #ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force()) nouveau_modeset = 0; - else #endif - nouveau_modeset = 1; } if (!nouveau_modeset) diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index c2a8511e855a..b096cf28213a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -47,6 +47,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->engine; + u32 pclass = dev->pdev->class >> 8; switch (dev_priv->chipset & 0xf0) { case 0x00: @@ -526,7 +527,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) } /* headless mode */ - if (nouveau_modeset == 2) { + if (nouveau_modeset == 2 || + (nouveau_modeset < 0 && pclass != PCI_CLASS_DISPLAY_VGA)) { engine->display.early_init = nouveau_stub_init; engine->display.late_takedown = nouveau_stub_takedown; engine->display.create = nouveau_stub_init; -- GitLab From 0b1743f0b0e1f8db0be800c301c0cf83add46fe9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 17 Oct 2012 16:47:11 +0900 Subject: [PATCH 0919/1799] Revert: ARM: SAMSUNG: Add naming of s3c64xx-spi devices This reverts commit baa526f45d3f096a1cd9f14b668203a03bbab6f9, which is commit 308b3afb97dc342e9c4f958d8b4c459ae0e22bd7 upstream. To quote Colin Cross: This patch breaks Exynos5 spi on 3.4.17. The patch with the bug that this patch was supposed to address went in to 3.6 and not 3.4, so this patch causes a driver name mismatch when applied to 3.4. Cc: Colin Cross Cc: Heiko Stuebner Cc: Sylwester Nawrocki Cc: Kukjin Kim Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-exynos/common.c | 5 ---- arch/arm/mach-s3c24xx/s3c2416.c | 2 -- arch/arm/mach-s3c24xx/s3c2443.c | 4 --- arch/arm/mach-s5p64x0/common.c | 3 -- arch/arm/mach-s5pc100/common.c | 3 -- arch/arm/mach-s5pv210/common.c | 3 -- arch/arm/plat-samsung/include/plat/spi-core.h | 30 ------------------- 7 files changed, 50 deletions(-) delete mode 100644 arch/arm/plat-samsung/include/plat/spi-core.h diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index c2b77e5a5421..5ccd6e80a607 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include "common.h" @@ -339,8 +338,6 @@ static void __init exynos4_map_io(void) s5p_fb_setname(0, "exynos4-fb"); s5p_hdmi_setname("exynos4-hdmi"); - - s3c64xx_spi_setname("exynos4210-spi"); } static void __init exynos5_map_io(void) @@ -361,8 +358,6 @@ static void __init exynos5_map_io(void) s3c_i2c0_setname("s3c2440-i2c"); s3c_i2c1_setname("s3c2440-i2c"); s3c_i2c2_setname("s3c2440-i2c"); - - s3c64xx_spi_setname("exynos4210-spi"); } static void __init exynos4_init_clocks(int xtal) diff --git a/arch/arm/mach-s3c24xx/s3c2416.c b/arch/arm/mach-s3c24xx/s3c2416.c index f74818da5803..7743fade50df 100644 --- a/arch/arm/mach-s3c24xx/s3c2416.c +++ b/arch/arm/mach-s3c24xx/s3c2416.c @@ -61,7 +61,6 @@ #include #include #include -#include static struct map_desc s3c2416_iodesc[] __initdata = { IODESC_ENT(WATCHDOG), @@ -132,7 +131,6 @@ void __init s3c2416_map_io(void) /* initialize device information early */ s3c2416_default_sdhci0(); s3c2416_default_sdhci1(); - s3c64xx_spi_setname("s3c2443-spi"); iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc)); } diff --git a/arch/arm/mach-s3c24xx/s3c2443.c b/arch/arm/mach-s3c24xx/s3c2443.c index 165b6a6b3daa..ab648ad8fa50 100644 --- a/arch/arm/mach-s3c24xx/s3c2443.c +++ b/arch/arm/mach-s3c24xx/s3c2443.c @@ -43,7 +43,6 @@ #include #include #include -#include static struct map_desc s3c2443_iodesc[] __initdata = { IODESC_ENT(WATCHDOG), @@ -101,9 +100,6 @@ void __init s3c2443_map_io(void) s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull; s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull; - /* initialize device information early */ - s3c64xx_spi_setname("s3c2443-spi"); - iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc)); } diff --git a/arch/arm/mach-s5p64x0/common.c b/arch/arm/mach-s5p64x0/common.c index 111e404a81fd..6e6a0a9d6778 100644 --- a/arch/arm/mach-s5p64x0/common.c +++ b/arch/arm/mach-s5p64x0/common.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -180,7 +179,6 @@ void __init s5p6440_map_io(void) /* initialize any device information early */ s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); - s3c64xx_spi_setname("s5p64x0-spi"); s5p64x0_default_sdhci0(); s5p64x0_default_sdhci1(); @@ -195,7 +193,6 @@ void __init s5p6450_map_io(void) /* initialize any device information early */ s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); - s3c64xx_spi_setname("s5p64x0-spi"); s5p64x0_default_sdhci0(); s5p64x0_default_sdhci1(); diff --git a/arch/arm/mach-s5pc100/common.c b/arch/arm/mach-s5pc100/common.c index cc6e561c9958..621908658861 100644 --- a/arch/arm/mach-s5pc100/common.c +++ b/arch/arm/mach-s5pc100/common.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include @@ -166,8 +165,6 @@ void __init s5pc100_map_io(void) s3c_onenand_setname("s5pc100-onenand"); s3c_fb_setname("s5pc100-fb"); s3c_cfcon_setname("s5pc100-pata"); - - s3c64xx_spi_setname("s5pc100-spi"); } void __init s5pc100_init_clocks(int xtal) diff --git a/arch/arm/mach-s5pv210/common.c b/arch/arm/mach-s5pv210/common.c index a0c50efe8145..4c9e9027df9a 100644 --- a/arch/arm/mach-s5pv210/common.c +++ b/arch/arm/mach-s5pv210/common.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include "common.h" @@ -197,8 +196,6 @@ void __init s5pv210_map_io(void) /* setup TV devices */ s5p_hdmi_setname("s5pv210-hdmi"); - - s3c64xx_spi_setname("s5pv210-spi"); } void __init s5pv210_init_clocks(int xtal) diff --git a/arch/arm/plat-samsung/include/plat/spi-core.h b/arch/arm/plat-samsung/include/plat/spi-core.h deleted file mode 100644 index 0b9428ab3fc3..000000000000 --- a/arch/arm/plat-samsung/include/plat/spi-core.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2012 Heiko Stuebner - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __PLAT_S3C_SPI_CORE_H -#define __PLAT_S3C_SPI_CORE_H - -/* These functions are only for use with the core support code, such as - * the cpu specific initialisation code - */ - -/* re-define device name depending on support. */ -static inline void s3c64xx_spi_setname(char *name) -{ -#ifdef CONFIG_S3C64XX_DEV_SPI0 - s3c64xx_device_spi0.name = name; -#endif -#ifdef CONFIG_S3C64XX_DEV_SPI1 - s3c64xx_device_spi1.name = name; -#endif -#ifdef CONFIG_S3C64XX_DEV_SPI2 - s3c64xx_device_spi2.name = name; -#endif -} - -#endif /* __PLAT_S3C_SPI_CORE_H */ -- GitLab From 8ddd4813010397b5aa3bf9f81de1994c415dfc10 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 Nov 2012 09:50:52 +0100 Subject: [PATCH 0920/1799] Linux 3.4.18 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3f9f0762e88e..95de44764c4d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 17 +SUBLEVEL = 18 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From ccd37ab3230af7b32db1a139d9fe95918813bc23 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Wed, 24 Oct 2012 12:39:02 +0100 Subject: [PATCH 0921/1799] xen/gntdev: don't leak memory from IOCTL_GNTDEV_MAP_GRANT_REF commit a67baeb77375199bbd842fa308cb565164dd1f19 upstream. map->kmap_ops allocated in gntdev_alloc_map() wasn't freed by gntdev_put_map(). Add a gntdev_free_map() helper function to free everything allocated by gntdev_alloc_map(). Signed-off-by: David Vrabel Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/xen/gntdev.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 7f1241608489..9a113b714b47 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv, #endif } +static void gntdev_free_map(struct grant_map *map) +{ + if (map == NULL) + return; + + if (map->pages) + free_xenballooned_pages(map->count, map->pages); + kfree(map->pages); + kfree(map->grants); + kfree(map->map_ops); + kfree(map->unmap_ops); + kfree(map->kmap_ops); + kfree(map); +} + static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) { struct grant_map *add; @@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) return add; err: - kfree(add->pages); - kfree(add->grants); - kfree(add->map_ops); - kfree(add->unmap_ops); - kfree(add->kmap_ops); - kfree(add); + gntdev_free_map(add); return NULL; } @@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map) evtchn_put(map->notify.event); } - if (map->pages) { - if (!use_ptemod) - unmap_grant_pages(map, 0, map->count); - - free_xenballooned_pages(map->count, map->pages); - } - kfree(map->pages); - kfree(map->grants); - kfree(map->map_ops); - kfree(map->unmap_ops); - kfree(map); + if (map->pages && !use_ptemod) + unmap_grant_pages(map, 0, map->count); + gntdev_free_map(map); } /* ------------------------------------------------------------------ */ -- GitLab From da205c80275a7f7a90c2baab423783c55c406878 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 31 Oct 2012 12:38:31 -0400 Subject: [PATCH 0922/1799] xen/mmu: Use Xen specific TLB flush instead of the generic one. commit 95a7d76897c1e7243d4137037c66d15cbf2cce76 upstream. As Mukesh explained it, the MMUEXT_TLB_FLUSH_ALL allows the hypervisor to do a TLB flush on all active vCPUs. If instead we were using the generic one (which ends up being xen_flush_tlb) we end up making the MMUEXT_TLB_FLUSH_LOCAL hypercall. But before we make that hypercall the kernel will IPI all of the vCPUs (even those that were asleep from the hypervisor perspective). The end result is that we needlessly wake them up and do a TLB flush when we can just let the hypervisor do it correctly. This patch gives around 50% speed improvement when migrating idle guest's from one host to another. Oracle-bug: 14630170 Tested-by: Jingjie Jiang Suggested-by: Mukesh Rathor Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/mmu.c | 21 ++++++++++++++++++++- include/trace/events/xen.h | 8 ++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 69f5857660ac..5cb8e27d43d2 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1203,6 +1203,25 @@ unsigned long xen_read_cr2_direct(void) return this_cpu_read(xen_vcpu_info.arch.cr2); } +void xen_flush_tlb_all(void) +{ + struct mmuext_op *op; + struct multicall_space mcs; + + trace_xen_mmu_flush_tlb_all(0); + + preempt_disable(); + + mcs = xen_mc_entry(sizeof(*op)); + + op = mcs.args; + op->cmd = MMUEXT_TLB_FLUSH_ALL; + MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); + + xen_mc_issue(PARAVIRT_LAZY_MMU); + + preempt_enable(); +} static void xen_flush_tlb(void) { struct mmuext_op *op; @@ -2364,7 +2383,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, err = 0; out: - flush_tlb_all(); + xen_flush_tlb_all(); return err; } diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h index 92f1a796829e..348c4febdcbb 100644 --- a/include/trace/events/xen.h +++ b/include/trace/events/xen.h @@ -377,6 +377,14 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd, DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin); DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin); +TRACE_EVENT(xen_mmu_flush_tlb_all, + TP_PROTO(int x), + TP_ARGS(x), + TP_STRUCT__entry(__array(char, x, 0)), + TP_fast_assign((void)x), + TP_printk("%s", "") + ); + TRACE_EVENT(xen_mmu_flush_tlb, TP_PROTO(int x), TP_ARGS(x), -- GitLab From 180bed351c02841004ee1c9d45a7efb1e207acf1 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Tue, 30 Oct 2012 23:39:10 -0700 Subject: [PATCH 0923/1799] Input: tsc40 - remove wrong announcement of pressure support commit 32ed1911fc79908d704023317d4ddeb3883fd07e upstream. The tsc40 driver announces it supports the pressure event, but will never send one. The announcement will cause tslib to wait for such events and sending all touch events with a pressure of 0. Removing the announcement will make tslib fall back to emulating the pressure on touch events so everything works as expected. Signed-off-by: Rolf Eike Beer Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/touchscreen/tsc40.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c index 29d5ed4dd31c..80d46100d37e 100644 --- a/drivers/input/touchscreen/tsc40.c +++ b/drivers/input/touchscreen/tsc40.c @@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv) __set_bit(BTN_TOUCH, input_dev->keybit); input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0); input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0); - input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0); serio_set_drvdata(serio, ptsc); -- GitLab From a2fad9a26b1a8a6e9732925cd97bd7b9ee25d6cc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 26 Oct 2012 00:31:11 +0200 Subject: [PATCH 0924/1799] ath9k: fix stale pointers potentially causing access to free'd skbs commit 8c6e30936a7893a85f6222084f0f26aceb81137a upstream. bf->bf_next is only while buffers are chained as part of an A-MPDU in the tx queue. When a tid queue is flushed (e.g. on tearing down an aggregation session), frames can be enqueued again as normal transmission, without bf_next being cleared. This can lead to the old pointer being dereferenced again later. This patch might fix crashes and "Failed to stop TX DMA!" messages. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/xmit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index b78773b48dba..11f252f88bd7 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -337,6 +337,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) } bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); + bf->bf_next = NULL; list_del(&bf->list); spin_unlock_bh(&sc->tx.txbuflock); @@ -1760,6 +1761,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, list_add_tail(&bf->list, &bf_head); bf->bf_state.bf_type = 0; + bf->bf_next = NULL; bf->bf_lastbf = bf; ath_tx_fill_desc(sc, bf, txq, fi->framelen); ath_tx_txqaddbuf(sc, txq, &bf_head, false); -- GitLab From 7bbaeecbffccbb38fcaf5f7c6af466c16e095d4b Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Mon, 29 Oct 2012 13:25:20 +0100 Subject: [PATCH 0925/1799] ath9k: Test for TID only in BlockAcks while checking tx status commit 6fe7cc71bbf3a0bc28c9cec3c00bc11e81344412 upstream. The ath9k xmit functions for AMPDUs can send frames as non-aggregate in case only one frame is currently available. The client will then answer using a normal Ack instead of a BlockAck. This acknowledgement has no TID stored and therefore the hardware is not able to provide us the corresponding TID. The TID set by the hardware in the tx status descriptor has to be seen as undefined and not as a valid TID value for normal acknowledgements. Doing otherwise results in a massive amount of retransmissions and stalls of connections. Users may experience low bandwidth and complete connection stalls in environments with transfers using multiple TIDs. This regression was introduced in b11b160defc48e4daa283f785192ea3a23a51f8e ("ath9k: validate the TID in the tx status information"). Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich Acked-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/xmit.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 11f252f88bd7..12a42f2c1e84 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -419,7 +419,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first; u32 ba[WME_BA_BMP_SIZE >> 5]; int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; - bool rc_update = true; + bool rc_update = true, isba; struct ieee80211_tx_rate rates[4]; struct ath_frame_info *fi; int nframes; @@ -463,13 +463,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; tid = ATH_AN_2_TID(an, tidno); seq_first = tid->seq_start; + isba = ts->ts_flags & ATH9K_TX_BA; /* * The hardware occasionally sends a tx status for the wrong TID. * In this case, the BA status cannot be considered valid and all * subframes need to be retransmitted + * + * Only BlockAcks have a TID and therefore normal Acks cannot be + * checked */ - if (tidno != ts->tid) + if (isba && tidno != ts->tid) txok = false; isaggr = bf_isaggr(bf); -- GitLab From 75d1ac720f8e92d2334ff7cc4e9a58ddb5213636 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 25 Oct 2012 09:51:39 +0200 Subject: [PATCH 0926/1799] rt2800: validate step value for temperature compensation commit bf7e1abe434ba9e22e8dc04a4cba4ab504b788b8 upstream. Some hardware has correct (!= 0xff) value of tssi_bounds[4] in the EEPROM, but step is equal to 0xff. This results on ridiculous delta calculations and completely broke TX power settings. Reported-and-tested-by: Pavel Lucik Signed-off-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 6c0a12ea6a15..2ce6bf5b6715 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2235,7 +2235,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) /* * Check if temperature compensation is supported. */ - if (tssi_bounds[4] == 0xff) + if (tssi_bounds[4] == 0xff || step == 0xff) return 0; /* -- GitLab From 506485a3c6d926cc01e6d05088eac94adf1d6ae5 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 31 Oct 2012 09:16:44 -0700 Subject: [PATCH 0927/1799] target: Don't return success from module_init() if setup fails commit 0d0f9dfb31e0a6c92063e235417b42df185b3275 upstream. If the call to core_dev_release_virtual_lun0() fails, then nothing sets ret to anything other than 0, so even though everything is torn down and freed, target_core_init_configfs() will seem to succeed and the module will be loaded. Fix this by passing the return value on up the chain. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_configfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 3f90d4b03e64..dbcede31ff8b 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -3197,7 +3197,8 @@ static int __init target_core_init_configfs(void) if (ret < 0) goto out; - if (core_dev_setup_virtual_lun0() < 0) + ret = core_dev_setup_virtual_lun0(); + if (ret < 0) goto out; return 0; -- GitLab From 227ab73196544a25f0c03338c5b49d3fdc1d1e38 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 31 Oct 2012 09:16:45 -0700 Subject: [PATCH 0928/1799] target: Avoid integer overflow in se_dev_align_max_sectors() commit 3e03989b5868acf69a391a424dc71fcd6cc48167 upstream. The expression (max_sectors * block_size) might overflow a u32 (indeed, since iblock sets max_hw_sectors to UINT_MAX, it is guaranteed to overflow and end up with a much-too-small result in many common cases). Fix this by doing an equivalent calculation that doesn't require multiplication. While we're touching this code, avoid splitting a printk format across two lines and use pr_info(...) instead of printk(KERN_INFO ...). Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_device.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index aa6267746383..4df8022fe3c8 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -826,20 +826,20 @@ int se_dev_check_shutdown(struct se_device *dev) u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) { - u32 tmp, aligned_max_sectors; + u32 aligned_max_sectors; + u32 alignment; /* * Limit max_sectors to a PAGE_SIZE aligned value for modern * transport_allocate_data_tasks() operation. */ - tmp = rounddown((max_sectors * block_size), PAGE_SIZE); - aligned_max_sectors = (tmp / block_size); - if (max_sectors != aligned_max_sectors) { - printk(KERN_INFO "Rounding down aligned max_sectors from %u" - " to %u\n", max_sectors, aligned_max_sectors); - return aligned_max_sectors; - } + alignment = max(1ul, PAGE_SIZE / block_size); + aligned_max_sectors = rounddown(max_sectors, alignment); + + if (max_sectors != aligned_max_sectors) + pr_info("Rounding down aligned max_sectors from %u to %u\n", + max_sectors, aligned_max_sectors); - return max_sectors; + return aligned_max_sectors; } void se_dev_set_default_attribs( -- GitLab From 7f83bc1f1bff2e9b89b3a505750b067f0073fe5c Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 31 Oct 2012 09:16:46 -0700 Subject: [PATCH 0929/1799] iscsi-target: Fix missed wakeup race in TX thread commit d5627acba9ae584cf4928af19f7ddf5f6837de32 upstream. The sleeping code in iscsi_target_tx_thread() is susceptible to the classic missed wakeup race: - TX thread finishes handle_immediate_queue() and handle_response_queue(), thinks both queues are empty. - Another thread adds a queue entry and does wake_up_process(), which does nothing because the TX thread is still awake. - TX thread does schedule_timeout() and sleeps forever. In practice this can kill an iSCSI connection if for example an initiator does single-threaded writes and the target misses the wakeup window when queueing an R2T; in this case the connection will be stuck until the initiator loses patience and does some task management operation (or kills the connection entirely). Fix this by converting to wait_event_interruptible(), which does not suffer from this sort of race. Signed-off-by: Roland Dreier Cc: Andy Grover Cc: Hannes Reinecke Cc: Christoph Hellwig Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target.c | 4 +++- drivers/target/iscsi/iscsi_target_core.h | 1 + drivers/target/iscsi/iscsi_target_login.c | 1 + drivers/target/iscsi/iscsi_target_util.c | 22 ++++++++++++++++++++-- drivers/target/iscsi/iscsi_target_util.h | 1 + 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 23e122a5daf1..ad202b342bf5 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3514,7 +3514,9 @@ int iscsi_target_tx_thread(void *arg) */ iscsit_thread_check_cpumask(conn, current, 1); - schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT); + wait_event_interruptible(conn->queues_wq, + !iscsit_conn_all_queues_empty(conn) || + ts->status == ISCSI_THREAD_SET_RESET); if ((ts->status == ISCSI_THREAD_SET_RESET) || signal_pending(current)) diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 1596aec0c3d7..2e46ea404cab 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -491,6 +491,7 @@ struct iscsi_tmr_req { }; struct iscsi_conn { + wait_queue_head_t queues_wq; /* Authentication Successful for this connection */ u8 auth_complete; /* State connection is currently in */ diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index ae304248c8c2..3cb7a4f5b988 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -45,6 +45,7 @@ extern spinlock_t sess_idr_lock; static int iscsi_login_init_conn(struct iscsi_conn *conn) { + init_waitqueue_head(&conn->queues_wq); INIT_LIST_HEAD(&conn->conn_list); INIT_LIST_HEAD(&conn->conn_cmd_list); INIT_LIST_HEAD(&conn->immed_queue_list); diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 4eba86d2bd82..4c05ed6beccc 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -656,7 +656,7 @@ void iscsit_add_cmd_to_immediate_queue( atomic_set(&conn->check_immediate_queue, 1); spin_unlock_bh(&conn->immed_queue_lock); - wake_up_process(conn->thread_set->tx_thread); + wake_up(&conn->queues_wq); } struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn) @@ -730,7 +730,7 @@ void iscsit_add_cmd_to_response_queue( atomic_inc(&cmd->response_queue_count); spin_unlock_bh(&conn->response_queue_lock); - wake_up_process(conn->thread_set->tx_thread); + wake_up(&conn->queues_wq); } struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn) @@ -784,6 +784,24 @@ static void iscsit_remove_cmd_from_response_queue( } } +bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn) +{ + bool empty; + + spin_lock_bh(&conn->immed_queue_lock); + empty = list_empty(&conn->immed_queue_list); + spin_unlock_bh(&conn->immed_queue_lock); + + if (!empty) + return empty; + + spin_lock_bh(&conn->response_queue_lock); + empty = list_empty(&conn->response_queue_list); + spin_unlock_bh(&conn->response_queue_lock); + + return empty; +} + void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn) { struct iscsi_queue_req *qr, *qr_tmp; diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index 835bf7de0281..cfac698fb3cb 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h @@ -28,6 +28,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_ extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8); extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *); extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *); +extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *); extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *); extern void iscsit_release_cmd(struct iscsi_cmd *); extern void iscsit_free_cmd(struct iscsi_cmd *); -- GitLab From bfc5de3bc907e97b9aabce6d6517a55d5ed6d791 Mon Sep 17 00:00:00 2001 From: Steve Hodgson Date: Wed, 31 Oct 2012 10:24:02 -0700 Subject: [PATCH 0930/1799] target: Fix incorrect usage of nested IRQ spinlocks in ABORT_TASK path commit ab74b3d62f05192bf8fb8f169e7999d1183b2e08 upstream. This patch changes core_tmr_abort_task() to use spin_lock -> spin_unlock around se_cmd->t_state_lock while spin_lock_irqsave is held via se_sess->sess_cmd_lock. Signed-off-by: Steve Hodgson Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_tmr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index f015839aef89..4a5c6d758c47 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -140,15 +140,15 @@ void core_tmr_abort_task( printk("ABORT_TASK: Found referenced %s task_tag: %u\n", se_cmd->se_tfo->get_fabric_name(), ref_tag); - spin_lock_irq(&se_cmd->t_state_lock); + spin_lock(&se_cmd->t_state_lock); if (se_cmd->transport_state & CMD_T_COMPLETE) { printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag); - spin_unlock_irq(&se_cmd->t_state_lock); + spin_unlock(&se_cmd->t_state_lock); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); goto out; } se_cmd->transport_state |= CMD_T_ABORTED; - spin_unlock_irq(&se_cmd->t_state_lock); + spin_unlock(&se_cmd->t_state_lock); list_del_init(&se_cmd->se_cmd_list); kref_get(&se_cmd->cmd_kref); -- GitLab From 91721d4a83437f183d29ae6397a3934fcfa28436 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 17 Oct 2012 13:56:19 +0200 Subject: [PATCH 0931/1799] cfg80211: fix antenna gain handling commit c4a9fafc77a5318f5ed26c509bbcddf03e18c201 upstream. No driver initializes chan->max_antenna_gain to something sensible, and the only place where it is being used right now is inside ath9k. This leads to ath9k potentially using less tx power than it can use, which can decrease performance/range in some rare cases. Rather than going through every single driver, this patch initializes chan->orig_mag in wiphy_register(), ignoring whatever value the driver left in there. If a driver for some reason wishes to limit it independent from regulatory rulesets, it can do so internally. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/wireless/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index bb5302dd592d..7917c74b25b2 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -552,8 +552,7 @@ int wiphy_register(struct wiphy *wiphy) for (i = 0; i < sband->n_channels; i++) { sband->channels[i].orig_flags = sband->channels[i].flags; - sband->channels[i].orig_mag = - sband->channels[i].max_antenna_gain; + sband->channels[i].orig_mag = INT_MAX; sband->channels[i].orig_mpwr = sband->channels[i].max_power; sband->channels[i].band = band; -- GitLab From 2404ce30fd4e4c46d3c3869093a5987c0d56fee6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 25 Oct 2012 21:51:59 +0200 Subject: [PATCH 0932/1799] wireless: drop invalid mesh address extension frames commit 7dd111e8ee10cc6816669eabcad3334447673236 upstream. The mesh header can have address extension by a 4th or a 5th and 6th address, but never both. Drop such frames in 802.11 -> 802.3 conversion along with any frames that have the wrong extension. Reviewed-by: Javier Cardona Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/wireless/util.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/wireless/util.c b/net/wireless/util.c index d835377b4da7..d39a6c239c24 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -293,18 +293,15 @@ EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) { int ae = meshhdr->flags & MESH_FLAGS_AE; - /* 7.1.3.5a.2 */ + /* 802.11-2012, 8.2.4.7.3 */ switch (ae) { + default: case 0: return 6; case MESH_FLAGS_AE_A4: return 12; case MESH_FLAGS_AE_A5_A6: return 18; - case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6): - return 24; - default: - return 6; } } @@ -354,6 +351,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, /* make sure meshdr->flags is on the linear part */ if (!pskb_may_pull(skb, hdrlen + 1)) return -1; + if (meshdr->flags & MESH_FLAGS_AE_A4) + return -1; if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { skb_copy_bits(skb, hdrlen + offsetof(struct ieee80211s_hdr, eaddr1), @@ -378,6 +377,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, /* make sure meshdr->flags is on the linear part */ if (!pskb_may_pull(skb, hdrlen + 1)) return -1; + if (meshdr->flags & MESH_FLAGS_AE_A5_A6) + return -1; if (meshdr->flags & MESH_FLAGS_AE_A4) skb_copy_bits(skb, hdrlen + offsetof(struct ieee80211s_hdr, eaddr1), -- GitLab From fec9a0c8f048db2807646fea92bdd87dc8adbade Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 24 Oct 2012 14:19:53 +0200 Subject: [PATCH 0933/1799] mac80211: use blacklist for duplicate IE check commit 9690fb169b433a66485c808e4fc352b8a0f8d866 upstream. Instead of the current whitelist which accepts duplicates only for the quiet and vendor IEs, use a blacklist of all IEs (that we currently parse) that can't be duplicated. This avoids detecting a beacon as corrupt in the future when new IEs are added that can be duplicated. Signed-off-by: Paul Stewart Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/util.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index eb9d7c0529b6..266d0925ba28 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -592,13 +592,38 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, break; } - if (id != WLAN_EID_VENDOR_SPECIFIC && - id != WLAN_EID_QUIET && - test_bit(id, seen_elems)) { - elems->parse_error = true; - left -= elen; - pos += elen; - continue; + switch (id) { + case WLAN_EID_SSID: + case WLAN_EID_SUPP_RATES: + case WLAN_EID_FH_PARAMS: + case WLAN_EID_DS_PARAMS: + case WLAN_EID_CF_PARAMS: + case WLAN_EID_TIM: + case WLAN_EID_IBSS_PARAMS: + case WLAN_EID_CHALLENGE: + case WLAN_EID_RSN: + case WLAN_EID_ERP_INFO: + case WLAN_EID_EXT_SUPP_RATES: + case WLAN_EID_HT_CAPABILITY: + case WLAN_EID_MESH_ID: + case WLAN_EID_MESH_CONFIG: + case WLAN_EID_PEER_MGMT: + case WLAN_EID_PREQ: + case WLAN_EID_PREP: + case WLAN_EID_PERR: + case WLAN_EID_RANN: + case WLAN_EID_CHANNEL_SWITCH: + case WLAN_EID_EXT_CHANSWITCH_ANN: + case WLAN_EID_COUNTRY: + case WLAN_EID_PWR_CONSTRAINT: + case WLAN_EID_TIMEOUT_INTERVAL: + if (test_bit(id, seen_elems)) { + elems->parse_error = true; + left -= elen; + pos += elen; + continue; + } + break; } if (calc_crc && id < 64 && (filter & (1ULL << id))) -- GitLab From 739b9fa801cab6bd63d51de7d7a97b7bd8bbbdc8 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Wed, 24 Oct 2012 12:43:30 -0700 Subject: [PATCH 0934/1799] mac80211: Only process mesh config header on frames that RA_MATCH commit 555cb715be8ef98b8ec362b23dfc254d432a35b1 upstream. Doing otherwise is wrong, and may wreak havoc on the mpp tables, specially if the frame is encrypted. Reported-by: Chaoxing Lin Signed-off-by: Javier Cardona Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/rx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c9b508ea9d6b..94b6f397fd3e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1900,7 +1900,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) return RX_DROP_MONITOR; - if (!ieee80211_is_data(hdr->frame_control)) + if (!ieee80211_is_data(hdr->frame_control) || + !(status->rx_flags & IEEE80211_RX_RA_MATCH)) return RX_CONTINUE; if (!mesh_hdr->ttl) @@ -1944,9 +1945,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) } skb_set_queue_mapping(skb, q); - if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) - goto out; - if (!--mesh_hdr->ttl) { IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); return RX_DROP_MONITOR; -- GitLab From 7be001e0fa58fa84e81fcc8a7951a3f3fe7c642c Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Thu, 25 Oct 2012 11:10:18 -0700 Subject: [PATCH 0935/1799] mac80211: don't inspect Sequence Control field on control frames commit f7fbf70ee9db6da6033ae50d100e017ac1f26555 upstream. Per IEEE Std. 802.11-2012, Sec 8.2.4.4.1, the sequence Control field is not present in control frames. We noticed this problem when processing Block Ack Requests. Signed-off-by: Javier Cardona Signed-off-by: Javier Lopez Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/rx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 94b6f397fd3e..d58a3285233d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1465,6 +1465,10 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) hdr = (struct ieee80211_hdr *)rx->skb->data; fc = hdr->frame_control; + + if (ieee80211_is_ctl(fc)) + return RX_CONTINUE; + sc = le16_to_cpu(hdr->seq_ctrl); frag = sc & IEEE80211_SCTL_FRAG; -- GitLab From f93a53b38d63be316156ad8a332ed982ad33a59d Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Wed, 24 Oct 2012 18:29:49 +0200 Subject: [PATCH 0936/1799] DRM/Radeon: Fix Load Detection on legacy primary DAC. commit 83325d072185899b706de2956170b246585aaec9 upstream. An uninitialized variable led to broken load detection. Signed-off-by: Egbert Eich Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 1461e2ce359e..d92f483fed41 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -650,6 +650,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; WREG32(RADEON_DAC_CNTL, tmp); + tmp = dac_macro_cntl; tmp &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B); -- GitLab From 4b51c17efde8501badb4bf7355172eb262407ad8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 1 Nov 2012 13:47:09 +1000 Subject: [PATCH 0937/1799] drm/udl: fix stride issues scanning out stride != width*bpp commit 3916e1d71b62b120888aa50bcc8d9a6200fc19a7 upstream. When buffer sharing with the i915 and using a 1680x1050 monitor, the i915 gives is a 6912 buffer for the 6720 width, the code doesn't render this properly as it uses one value to set the base address for reading from the vmap and for where to start on the device. This fixes it by calculating the values correctly for the device and for the pixmap. No idea how I haven't seen this before now. Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/udl/udl_drv.h | 2 +- drivers/gpu/drm/udl/udl_fb.c | 12 +++++++----- drivers/gpu/drm/udl/udl_transfer.c | 5 +++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 96820d03a303..e76057586612 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -103,7 +103,7 @@ udl_fb_user_fb_create(struct drm_device *dev, int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, const char *front, char **urb_buf_ptr, - u32 byte_offset, u32 byte_width, + u32 byte_offset, u32 device_byte_offset, u32 byte_width, int *ident_ptr, int *sent_ptr); int udl_dumb_create(struct drm_file *file_priv, diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 4d9c3a5d8a45..b9282cf7aea3 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info, list_for_each_entry(cur, &fbdefio->pagelist, lru) { if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), - &urb, (char *) info->fix.smem_start, - &cmd, cur->index << PAGE_SHIFT, - PAGE_SIZE, &bytes_identical, &bytes_sent)) + &urb, (char *) info->fix.smem_start, + &cmd, cur->index << PAGE_SHIFT, + cur->index << PAGE_SHIFT, + PAGE_SIZE, &bytes_identical, &bytes_sent)) goto error; bytes_rendered += PAGE_SIZE; } @@ -178,10 +179,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, for (i = y; i < y + height ; i++) { const int line_offset = fb->base.pitches[0] * i; const int byte_offset = line_offset + (x * bpp); - + const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); if (udl_render_hline(dev, bpp, &urb, (char *) fb->obj->vmapping, - &cmd, byte_offset, width * bpp, + &cmd, byte_offset, dev_byte_offset, + width * bpp, &bytes_identical, &bytes_sent)) goto error; } diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index b9320e2608dd..fc1134416bcc 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -213,11 +213,12 @@ static void udl_compress_hline16( */ int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, const char *front, char **urb_buf_ptr, - u32 byte_offset, u32 byte_width, + u32 byte_offset, u32 device_byte_offset, + u32 byte_width, int *ident_ptr, int *sent_ptr) { const u8 *line_start, *line_end, *next_pixel; - u32 base16 = 0 + (byte_offset / bpp) * 2; + u32 base16 = 0 + (device_byte_offset / bpp) * 2; struct urb *urb = *urb_ptr; u8 *cmd = *urb_buf_ptr; u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; -- GitLab From 537d86c490a03bcb56dfa24c0327c18e61b1ced5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 26 Oct 2012 00:33:36 +0200 Subject: [PATCH 0938/1799] mac80211: check management frame header length commit 4a4f1a5808c8bb0b72a4f6e5904c53fb8c9cd966 upstream. Due to pskb_may_pull() checking the skb length, all non-management frames are checked on input whether their 802.11 header is fully present. Also add that check for management frames and remove a check that is now duplicate. This prevents accessing skb data beyond the frame end. Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/rx.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d58a3285233d..06025a9065f1 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1473,7 +1473,6 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) frag = sc & IEEE80211_SCTL_FRAG; if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || - (rx->skb)->len < 24 || is_multicast_ether_addr(hdr->addr1))) { /* not fragmented */ goto out; @@ -2929,10 +2928,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, test_bit(SCAN_SW_SCANNING, &local->scanning))) status->rx_flags |= IEEE80211_RX_IN_SCAN; - if (ieee80211_is_mgmt(fc)) - err = skb_linearize(skb); - else + if (ieee80211_is_mgmt(fc)) { + /* drop frame if too short for header */ + if (skb->len < ieee80211_hdrlen(fc)) + err = -ENOBUFS; + else + err = skb_linearize(skb); + } else { err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); + } if (err) { dev_kfree_skb(skb); -- GitLab From 4435990b6d456a8c5cac203c025d1f10e0b48a93 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 26 Oct 2012 00:36:40 +0200 Subject: [PATCH 0939/1799] mac80211: verify that skb data is present commit 9b395bc3be1cebf0144a127c7e67d56dbdac0930 upstream. A number of places in the mesh code don't check that the frame data is present and in the skb header when trying to access. Add those checks and the necessary pskb_may_pull() calls. This prevents accessing data that doesn't actually exist. To do this, export ieee80211_get_mesh_hdrlen() to be able to use it in mac80211. Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- include/net/cfg80211.h | 9 +++++++++ net/mac80211/rx.c | 32 +++++++++++++++++++++++++++++++- net/wireless/util.c | 3 ++- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 83d800c31e3c..b4de1942c6fa 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2479,6 +2479,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); */ unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); +/** + * ieee80211_get_mesh_hdrlen - get mesh extension header length + * @meshhdr: the mesh extension header, only the flags field + * (first byte) will be accessed + * Returns the length of the extension header, which is always at + * least 6 bytes and at most 18 if address 5 and 6 are present. + */ +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); + /** * DOC: Data path helpers * diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 06025a9065f1..efe1b98fa3fb 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -513,6 +513,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) if (ieee80211_is_action(hdr->frame_control)) { u8 category; + + /* make sure category field is present */ + if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE) + return RX_DROP_MONITOR; + mgmt = (struct ieee80211_mgmt *)hdr; category = mgmt->u.action.category; if (category != WLAN_CATEGORY_MESH_ACTION && @@ -1895,6 +1900,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) hdr = (struct ieee80211_hdr *) skb->data; hdrlen = ieee80211_hdrlen(hdr->frame_control); + + /* make sure fixed part of mesh header is there, also checks skb len */ + if (!pskb_may_pull(rx->skb, hdrlen + 6)) + return RX_DROP_MONITOR; + + mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + + /* make sure full mesh header is there, also checks skb len */ + if (!pskb_may_pull(rx->skb, + hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr))) + return RX_DROP_MONITOR; + + /* reload pointers */ + hdr = (struct ieee80211_hdr *) skb->data; mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); /* frame is in RMC, don't forward */ @@ -1918,9 +1937,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) if (is_multicast_ether_addr(hdr->addr1)) { mpp_addr = hdr->addr3; proxied_addr = mesh_hdr->eaddr1; - } else { + } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { + /* has_a4 already checked in ieee80211_rx_mesh_check */ mpp_addr = hdr->addr4; proxied_addr = mesh_hdr->eaddr2; + } else { + return RX_DROP_MONITOR; } rcu_read_lock(); @@ -2362,6 +2384,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) } break; case WLAN_CATEGORY_SELF_PROTECTED: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.self_prot.action_code))) + break; + switch (mgmt->u.action.u.self_prot.action_code) { case WLAN_SP_MESH_PEERING_OPEN: case WLAN_SP_MESH_PEERING_CLOSE: @@ -2380,6 +2406,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) } break; case WLAN_CATEGORY_MESH_ACTION: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.mesh_action.action_code))) + break; + if (!ieee80211_vif_is_mesh(&sdata->vif)) break; if (mesh_action_is_path_sel(mgmt) && diff --git a/net/wireless/util.c b/net/wireless/util.c index d39a6c239c24..d22dce7b8b80 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -290,7 +290,7 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) } EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); -static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) { int ae = meshhdr->flags & MESH_FLAGS_AE; /* 802.11-2012, 8.2.4.7.3 */ @@ -304,6 +304,7 @@ static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) return 18; } } +EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, enum nl80211_iftype iftype) -- GitLab From d39904cae2cb6e0dcbee3f80692b6052515e43ea Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 26 Oct 2012 00:41:23 +0200 Subject: [PATCH 0940/1799] mac80211: make sure data is accessible in EAPOL check commit 6dbda2d00d466225f9db1dc695ff852443f28832 upstream. The code to allow EAPOL frames even when the station isn't yet marked associated needs to check that the incoming frame is long enough and due to paged RX it also can't assume skb->data contains the right data, it must use skb_copy_bits(). Fix this to avoid using data that doesn't really exist. Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/rx.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index efe1b98fa3fb..8ce9feb13010 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -874,14 +874,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) */ if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && ieee80211_is_data_present(hdr->frame_control)) { - u16 ethertype; - u8 *payload; - - payload = rx->skb->data + - ieee80211_hdrlen(hdr->frame_control); - ethertype = (payload[6] << 8) | payload[7]; - if (cpu_to_be16(ethertype) == - rx->sdata->control_port_protocol) + unsigned int hdrlen; + __be16 ethertype; + + hdrlen = ieee80211_hdrlen(hdr->frame_control); + + if (rx->skb->len < hdrlen + 8) + return RX_DROP_MONITOR; + + skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2); + if (ethertype == rx->sdata->control_port_protocol) return RX_CONTINUE; } -- GitLab From 1feb89af489539f927fc9ff0de99c945eec181c2 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Fri, 26 Oct 2012 18:54:25 +0200 Subject: [PATCH 0941/1799] mac80211: fix SSID copy on IBSS JOIN commit badecb001a310408d3473b1fc2ed5aefd0bc92a9 upstream. The 'ssid' field of the cfg80211_ibss_params is a u8 pointer and its length is likely to be less than IEEE80211_MAX_SSID_LEN most of the time. This patch fixes the ssid copy in ieee80211_ibss_join() by using the SSID length to prevent it from reading beyond the string. Signed-off-by: Antonio Quartulli [rewrapped commit message, small rewording] Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ibss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index cef7c29214a8..4a3666b678ea 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -1110,7 +1110,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; sdata->u.ibss.ibss_join_req = jiffies; - memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); + memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len); sdata->u.ibss.ssid_len = params->ssid_len; mutex_unlock(&sdata->u.ibss.mtx); -- GitLab From b37d05604ce92f1c118fb6aeb2af8af71998d3e7 Mon Sep 17 00:00:00 2001 From: Scott Mayhew Date: Tue, 16 Oct 2012 13:22:19 -0400 Subject: [PATCH 0942/1799] nfsv3: Make v3 mounts fail with ETIMEDOUTs instead EIO on mountd timeouts commit acce94e68a0f346115fd41cdc298197d2d5a59ad upstream. In very busy v3 environment, rpc.mountd can respond to the NULL procedure but not the MNT procedure in a timely manner causing the MNT procedure to time out. The problem is the mount system call returns EIO which causes the mount to fail, instead of ETIMEDOUT, which would cause the mount to be retried. This patch sets the RPC_TASK_SOFT|RPC_TASK_TIMEOUT flags to the rpc_call_sync() call in nfs_mount() which causes ETIMEDOUT to be returned on timed out connections. Signed-off-by: Steve Dickson Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/mount_clnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 8e65c7f1f87c..015f71f8f62c 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c @@ -181,7 +181,7 @@ int nfs_mount(struct nfs_mount_request *info) else msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT]; - status = rpc_call_sync(mnt_clnt, &msg, 0); + status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT); rpc_shutdown_client(mnt_clnt); if (status < 0) -- GitLab From 43113027b701f7b3f63c577056a9160dd3053f37 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 21 Oct 2012 19:23:52 +0100 Subject: [PATCH 0943/1799] nfs: Show original device name verbatim in /proc/*/mount{s,info} commit 97a54868262da1629a3e65121e65b8e8c4419d9f upstream. Since commit c7f404b ('vfs: new superblock methods to override /proc/*/mount{s,info}'), nfs_path() is used to generate the mounted device name reported back to userland. nfs_path() always generates a trailing slash when the given dentry is the root of an NFS mount, but userland may expect the original device name to be returned verbatim (as it used to be). Make this canonicalisation optional and change the callers accordingly. [jrnieder@gmail.com: use flag instead of bool argument] Reported-and-tested-by: Chris Hiestand Reference: http://bugs.debian.org/669314 Signed-off-by: Ben Hutchings Signed-off-by: Jonathan Nieder Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/internal.h | 5 +++-- fs/nfs/namespace.c | 19 ++++++++++++++----- fs/nfs/nfs4namespace.c | 3 ++- fs/nfs/super.c | 2 +- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index b777bdaba4c5..33aa76fec3aa 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -277,8 +277,9 @@ extern void nfs_sb_active(struct super_block *sb); extern void nfs_sb_deactive(struct super_block *sb); /* namespace.c */ +#define NFS_PATH_CANONICAL 1 extern char *nfs_path(char **p, struct dentry *dentry, - char *buffer, ssize_t buflen); + char *buffer, ssize_t buflen, unsigned flags); extern struct vfsmount *nfs_d_automount(struct path *path); #ifdef CONFIG_NFS_V4 rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); @@ -371,7 +372,7 @@ static inline char *nfs_devname(struct dentry *dentry, char *buffer, ssize_t buflen) { char *dummy; - return nfs_path(&dummy, dentry, buffer, buflen); + return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL); } /* diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index d51868e5683c..2257d1f33e3c 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -37,6 +37,7 @@ static struct vfsmount *nfs_do_submount(struct dentry *dentry, * @dentry - pointer to dentry * @buffer - result buffer * @buflen - length of buffer + * @flags - options (see below) * * Helper function for constructing the server pathname * by arbitrary hashed dentry. @@ -44,8 +45,14 @@ static struct vfsmount *nfs_do_submount(struct dentry *dentry, * This is mainly for use in figuring out the path on the * server side when automounting on top of an existing partition * and in generating /proc/mounts and friends. + * + * Supported flags: + * NFS_PATH_CANONICAL: ensure there is exactly one slash after + * the original device (export) name + * (if unset, the original name is returned verbatim) */ -char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) +char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen, + unsigned flags) { char *end; int namelen; @@ -78,7 +85,7 @@ char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) rcu_read_unlock(); goto rename_retry; } - if (*end != '/') { + if ((flags & NFS_PATH_CANONICAL) && *end != '/') { if (--buflen < 0) { spin_unlock(&dentry->d_lock); rcu_read_unlock(); @@ -95,9 +102,11 @@ char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) return end; } namelen = strlen(base); - /* Strip off excess slashes in base string */ - while (namelen > 0 && base[namelen - 1] == '/') - namelen--; + if (flags & NFS_PATH_CANONICAL) { + /* Strip off excess slashes in base string */ + while (namelen > 0 && base[namelen - 1] == '/') + namelen--; + } buflen -= namelen; if (buflen < 0) { spin_unlock(&dentry->d_lock); diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index a7f3dedc4ec7..b604be2dae6a 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c @@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end) static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) { char *limit; - char *path = nfs_path(&limit, dentry, buffer, buflen); + char *path = nfs_path(&limit, dentry, buffer, buflen, + NFS_PATH_CANONICAL); if (!IS_ERR(path)) { char *path_component = nfs_path_component(path, limit); if (path_component) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 5976e243d24a..feabe7a394c3 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -812,7 +812,7 @@ static int nfs_show_devname(struct seq_file *m, struct dentry *root) int err = 0; if (!page) return -ENOMEM; - devname = nfs_path(&dummy, root, page, PAGE_SIZE); + devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0); if (IS_ERR(devname)) err = PTR_ERR(devname); else -- GitLab From 8827f3112b5f3bd0ffa21dc647cb22b197558c59 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 29 Oct 2012 18:53:23 -0400 Subject: [PATCH 0944/1799] NFSv4: nfs4_locku_done must release the sequence id commit 2b1bc308f492589f7d49012ed24561534ea2be8c upstream. If the state recovery machinery is triggered by the call to nfs4_async_handle_error() then we can deadlock. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index b106b9729bcf..3b005ebb4685 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -4306,6 +4306,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) rpc_restart_call_prepare(task); } + nfs_release_seqid(calldata->arg.seqid); } static void nfs4_locku_prepare(struct rpc_task *task, void *data) -- GitLab From 0ada2107a13f1b1ae8bdd5fec32912bc40f4e679 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 29 Oct 2012 18:37:40 -0400 Subject: [PATCH 0945/1799] NFSv4.1: We must release the sequence id when we fail to get a session slot commit 2240a9e2d013d8269ea425b73e1d7a54c7bc141f upstream. If we do not release the sequence id in cases where we fail to get a session slot, then we can deadlock if we hit a recovery scenario. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 3b005ebb4685..5e801803072b 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1478,9 +1478,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) data->timestamp = jiffies; if (nfs4_setup_sequence(data->o_arg.server, &data->o_arg.seq_args, - &data->o_res.seq_res, task)) - return; - rpc_call_start(task); + &data->o_res.seq_res, + task) != 0) + nfs_release_seqid(data->o_arg.seqid); + else + rpc_call_start(task); return; unlock_no_action: rcu_read_unlock(); @@ -2097,9 +2099,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) if (nfs4_setup_sequence(NFS_SERVER(calldata->inode), &calldata->arg.seq_args, &calldata->res.seq_res, - task)) - goto out; - rpc_call_start(task); + task) != 0) + nfs_release_seqid(calldata->arg.seqid); + else + rpc_call_start(task); out: dprintk("%s: done!\n", __func__); } @@ -4323,9 +4326,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) calldata->timestamp = jiffies; if (nfs4_setup_sequence(calldata->server, &calldata->arg.seq_args, - &calldata->res.seq_res, task)) - return; - rpc_call_start(task); + &calldata->res.seq_res, + task) != 0) + nfs_release_seqid(calldata->arg.seqid); + else + rpc_call_start(task); } static const struct rpc_call_ops nfs4_locku_ops = { @@ -4470,7 +4475,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) /* Do we need to do an open_to_lock_owner? */ if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) - return; + goto out_release_lock_seqid; data->arg.open_stateid = &state->stateid; data->arg.new_lock_owner = 1; data->res.open_seqid = data->arg.open_seqid; @@ -4479,10 +4484,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) data->timestamp = jiffies; if (nfs4_setup_sequence(data->server, &data->arg.seq_args, - &data->res.seq_res, task)) + &data->res.seq_res, + task) == 0) { + rpc_call_start(task); return; - rpc_call_start(task); - dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); + } + nfs_release_seqid(data->arg.open_seqid); +out_release_lock_seqid: + nfs_release_seqid(data->arg.lock_seqid); + dprintk("%s: done!, ret = %d\n", __func__, task->tk_status); } static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) -- GitLab From 588c72e88125b1abe50efb3f1b6b768b98302e2c Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 12 Jun 2012 16:54:16 -0400 Subject: [PATCH 0946/1799] nfsd: add get_uint for u32's commit a007c4c3e943ecc054a806c259d95420a188754b upstream. I don't think there's a practical difference for the range of values these interfaces should see, but it would be safer to be unambiguous. Signed-off-by: J. Bruce Fields Cc: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/export.c | 6 +++--- include/linux/sunrpc/cache.h | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 8e9689abbc0c..e9a020f283f7 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -401,7 +401,7 @@ fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) int migrated, i, err; /* listsize */ - err = get_int(mesg, &fsloc->locations_count); + err = get_uint(mesg, &fsloc->locations_count); if (err) return err; if (fsloc->locations_count > MAX_FS_LOCATIONS) @@ -459,7 +459,7 @@ static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp) return -EINVAL; for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) { - err = get_int(mesg, &f->pseudoflavor); + err = get_uint(mesg, &f->pseudoflavor); if (err) return err; /* @@ -468,7 +468,7 @@ static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp) * problem at export time instead of when a client fails * to authenticate. */ - err = get_int(mesg, &f->flags); + err = get_uint(mesg, &f->flags); if (err) return err; /* Only some flags are allowed to differ between flavors: */ diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index f5fd6160dbca..dd2bb84526a4 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -228,6 +228,22 @@ static inline int get_int(char **bpp, int *anint) return 0; } +static inline int get_uint(char **bpp, unsigned int *anint) +{ + char buf[50]; + int len = qword_get(bpp, buf, sizeof(buf)); + + if (len < 0) + return -EINVAL; + if (len == 0) + return -ENOENT; + + if (kstrtouint(buf, 0, anint)) + return -EINVAL; + + return 0; +} + /* * timestamps kept in the cache are expressed in seconds * since boot. This is the best for measuring differences in -- GitLab From 088eb1bed178645788538611ac31ba9991cd88c4 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 31 Oct 2012 12:16:01 +1100 Subject: [PATCH 0947/1799] NFS: fix bug in legacy DNS resolver. commit 8d96b10639fb402357b75b055b1e82a65ff95050 upstream. The DNS resolver's use of the sunrpc cache involves a 'ttl' number (relative) rather that a timeout (absolute). This confused me when I wrote commit c5b29f885afe890f953f7f23424045cdad31d3e4 "sunrpc: use seconds since boot in expiry cache" and I managed to break it. The effect is that any TTL is interpreted as 0, and nothing useful gets into the cache. This patch removes the use of get_expiry() - which really expects an expiry time - and uses get_uint() instead, treating the int correctly as a ttl. This fixes a regression that has been present since 2.6.37, causing certain NFS accesses in certain environments to incorrectly fail. Reported-by: Chuck Lever Tested-by: Chuck Lever Signed-off-by: NeilBrown Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/dns_resolve.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index b3924b8a6000..786cd6533713 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c @@ -214,7 +214,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen) { char buf1[NFS_DNS_HOSTNAME_MAXLEN+1]; struct nfs_dns_ent key, *item; - unsigned long ttl; + unsigned int ttl; ssize_t len; int ret = -EINVAL; @@ -237,7 +237,8 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen) key.namelen = len; memset(&key.h, 0, sizeof(key.h)); - ttl = get_expiry(&buf); + if (get_uint(&buf, &ttl) < 0) + goto out; if (ttl == 0) goto out; key.h.expiry_time = ttl + seconds_since_boot(); -- GitLab From cde52501359fecbcb5832c77c49f11af2cfaa21b Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 22 Aug 2012 16:08:17 -0400 Subject: [PATCH 0948/1799] NFS: Fix Oopses in nfs_lookup_revalidate and nfs4_lookup_revalidate [Fixed upstream as part of 0b728e1911c, but that's a much larger patch, this is only the nfs portion backported as needed.] Fix the following Oops in 3.5.1: BUG: unable to handle kernel NULL pointer dereference at 0000000000000038 IP: [] nfs_lookup_revalidate+0x2d/0x480 [nfs] PGD 337c63067 PUD 0 Oops: 0000 [#1] SMP CPU 5 Modules linked in: nfs fscache nfsd lockd nfs_acl auth_rpcgss sunrpc af_packet binfmt_misc cpufreq_conservative cpufreq_userspace cpufreq_powersave dm_mod acpi_cpufreq mperf coretemp gpio_ich kvm_intel joydev kvm ioatdma hid_generic igb lpc_ich i7core_edac edac_core ptp serio_raw dca pcspkr i2c_i801 mfd_core sg pps_core usbhid crc32c_intel microcode button autofs4 uhci_hcd ttm drm_kms_helper drm i2c_algo_bit sysimgblt sysfillrect syscopyarea ehci_hcd usbcore usb_common scsi_dh_rdac scsi_dh_emc scsi_dh_hp_sw scsi_dh_alua scsi_dh edd fan ata_piix thermal processor thermal_sys Pid: 30431, comm: java Not tainted 3.5.1-2-default #1 Supermicro X8DTT/X8DTT RIP: 0010:[] [] nfs_lookup_revalidate+0x2d/0x480 [nfs] RSP: 0018:ffff8801b418bd38 EFLAGS: 00010292 RAX: 00000000fffffff6 RBX: ffff88032016d800 RCX: 0000000000000020 RDX: ffffffff00000000 RSI: 0000000000000000 RDI: ffff8801824a7b00 RBP: ffff8801b418bdf8 R08: 7fffff0034323030 R09: fffffffff04c03ed R10: ffff8801824a7b00 R11: 0000000000000002 R12: ffff8801824a7b00 R13: ffff8801824a7b00 R14: 0000000000000000 R15: ffff8803201725d0 FS: 00002b53a46cb700(0000) GS:ffff88033fc20000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000038 CR3: 000000020a426000 CR4: 00000000000007e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process java (pid: 30431, threadinfo ffff8801b418a000, task ffff8801b5d20600) Stack: ffff8801b418be44 ffff88032016d800 ffff8801b418bdf8 0000000000000000 ffff8801824a7b00 ffff8801b418bdd7 ffff8803201725d0 ffffffff8116a9c0 ffff8801b5c38dc0 0000000000000007 ffff88032016d800 0000000000000000 Call Trace: [] lookup_dcache+0x80/0xe0 [] __lookup_hash+0x23/0x90 [] lookup_one_len+0xc5/0x100 [] nfs_sillyrename+0xe3/0x210 [nfs] [] vfs_unlink.part.25+0x7f/0xe0 [] do_unlinkat+0x1ac/0x1d0 [] system_call_fastpath+0x16/0x1b [<00002b5348b5f527>] 0x2b5348b5f526 Code: ec 38 b8 f6 ff ff ff 4c 89 64 24 18 4c 89 74 24 28 49 89 fc 48 89 5c 24 08 48 89 6c 24 10 49 89 f6 4c 89 6c 24 20 4c 89 7c 24 30 46 38 40 0f 85 d1 00 00 00 e8 c4 c4 df e0 48 8b 58 30 49 89 RIP [] nfs_lookup_revalidate+0x2d/0x480 [nfs] RSP CR2: 0000000000000038 ---[ end trace 845113ed191985dd ]--- This Oops affects 3.5 kernels and older, and is due to lookup_one_len() calling down to the dentry revalidation code with a NULL pointer to struct nameidata. It is fixed upstream by commit 0b728e1911c (stop passing nameidata * to ->d_revalidate()) Reported-by: Richard Ems Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 8789210c6905..53ad9d1c37e4 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1103,7 +1103,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) struct nfs_fattr *fattr = NULL; int error; - if (nd->flags & LOOKUP_RCU) + if (nd && (nd->flags & LOOKUP_RCU)) return -ECHILD; parent = dget_parent(dentry); @@ -1502,7 +1502,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) struct iattr attr; int openflags, ret = 0; - if (nd->flags & LOOKUP_RCU) + if (nd && (nd->flags & LOOKUP_RCU)) return -ECHILD; inode = dentry->d_inode; -- GitLab From 47baf0d8ba90a5765f8f51130f9b20dc49ff6da4 Mon Sep 17 00:00:00 2001 From: Ilija Hadzic Date: Mon, 29 Oct 2012 17:35:00 +0000 Subject: [PATCH 0949/1799] drm: restore open_count if drm_setup fails commit 0f1cb1bd94a9c967cd4ad3de51cfdabe61eb5dcc upstream. If drm_setup (called at first open) fails, the whole open call has failed, so we should not keep the open_count incremented. Signed-off-by: Ilija Hadzic Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_fops.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 123de28f94ef..b90abff19341 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -139,8 +139,11 @@ int drm_open(struct inode *inode, struct file *filp) retcode = drm_open_helper(inode, filp, dev); if (!retcode) { atomic_inc(&dev->counts[_DRM_STAT_OPENS]); - if (!dev->open_count++) + if (!dev->open_count++) { retcode = drm_setup(dev); + if (retcode) + dev->open_count--; + } } if (!retcode) { mutex_lock(&dev->struct_mutex); -- GitLab From 45820dcb6cfe07b7ebb6ae5a5688f06b83996478 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 5 Nov 2012 21:54:39 +0100 Subject: [PATCH 0950/1799] hwmon: (w83627ehf) Force initial bank selection commit 3300fb4f88688029fff8dfb9ec0734f6e4cba3e7 upstream. Don't assume bank 0 is selected at device probe time. This may not be the case. Force bank selection at first register access to guarantee that we read the right registers upon driver loading. Signed-off-by: Jean Delvare Reviewed-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83627ehf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 54922ed12978..88effda19198 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -2082,6 +2082,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) mutex_init(&data->lock); mutex_init(&data->update_lock); data->name = w83627ehf_device_names[sio_data->kind]; + data->bank = 0xff; /* Force initial bank selection */ platform_set_drvdata(pdev, data); /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ -- GitLab From 5fee99c200f8138f3eb1cd6b3d69b199b3d86686 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 12:39:51 +0100 Subject: [PATCH 0951/1799] ALSA: PCM: Fix some races at disconnection commit 9b0573c07f278e9888c352aa9724035c75784ea0 upstream. Fix races at PCM disconnection: - while a PCM device is being opened or closed - while the PCM state is being changed without lock in prepare, hw_params, hw_free ops Reported-by: Matthieu CASTET Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/pcm.c | 7 ++++++- sound/core/pcm_native.c | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 1a3070b4e5b5..099f3fdd120a 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1086,11 +1086,15 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) if (list_empty(&pcm->list)) goto unlock; + mutex_lock(&pcm->open_mutex); list_del_init(&pcm->list); for (cidx = 0; cidx < 2; cidx++) - for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) + for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { + snd_pcm_stream_lock_irq(substream); if (substream->runtime) substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; + snd_pcm_stream_unlock_irq(substream); + } list_for_each_entry(notify, &snd_pcm_notify_list, list) { notify->n_disconnect(pcm); } @@ -1106,6 +1110,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) } snd_unregister_device(devtype, pcm->card, pcm->device); } + mutex_unlock(&pcm->open_mutex); unlock: mutex_unlock(®ister_mutex); return 0; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 3fe99e644eb8..608a2e18d6df 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime) return usecs; } +static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state) +{ + snd_pcm_stream_lock_irq(substream); + if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) + substream->runtime->status->state = state; + snd_pcm_stream_unlock_irq(substream); +} + static int snd_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, runtime->boundary *= 2; snd_pcm_timer_resolution_change(substream); - runtime->status->state = SNDRV_PCM_STATE_SETUP; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP); if (pm_qos_request_active(&substream->latency_pm_qos_req)) pm_qos_remove_request(&substream->latency_pm_qos_req); @@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, /* hardware might be unusable from this time, so we force application to retry to set the correct hardware parameter settings */ - runtime->status->state = SNDRV_PCM_STATE_OPEN; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); if (substream->ops->hw_free != NULL) substream->ops->hw_free(substream); return err; @@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) return -EBADFD; if (substream->ops->hw_free) result = substream->ops->hw_free(substream); - runtime->status->state = SNDRV_PCM_STATE_OPEN; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); pm_qos_remove_request(&substream->latency_pm_qos_req); return result; } @@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state) { struct snd_pcm_runtime *runtime = substream->runtime; runtime->control->appl_ptr = runtime->status->hw_ptr; - runtime->status->state = SNDRV_PCM_STATE_PREPARED; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED); } static struct action_ops snd_pcm_action_prepare = { -- GitLab From 799c92f2aecb348e4a4c6dab80c7206e48caf201 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 12:42:44 +0100 Subject: [PATCH 0952/1799] ALSA: usb-audio: Fix races at disconnection commit 978520b75f0a1ce82b17e1e8186417250de6d545 upstream. Close some races at disconnection of a USB audio device by adding the chip->shutdown_mutex and chip->shutdown check at appropriate places. The spots to put bandaids are: - PCM prepare, hw_params and hw_free - where the usb device is accessed for communication or get speed, in mixer.c and others; the device speed is now cached in subs->speed instead of accessing to chip->dev The accesses in PCM open and close don't need the mutex protection because these are already handled in the core PCM disconnection code. The autosuspend/autoresume codes are still uncovered by this patch because of possible mutex deadlocks. They'll be covered by the upcoming change to rwsem. Also the mixer codes are untouched, too. These will be fixed in another patch, too. Reported-by: Matthieu CASTET Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/card.h | 1 + sound/usb/endpoint.c | 9 ++++-- sound/usb/mixer.c | 65 +++++++++++++++++++++++++++++--------------- sound/usb/pcm.c | 31 ++++++++++++++++----- sound/usb/proc.c | 4 +-- 5 files changed, 76 insertions(+), 34 deletions(-) diff --git a/sound/usb/card.h b/sound/usb/card.h index da5fa1ac4eda..7932b2ac0dec 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -87,6 +87,7 @@ struct snd_usb_substream { struct snd_urb_ctx syncurb[SYNC_URBS]; /* sync urb table */ char *syncbuf; /* sync buffer for all sync URBs */ dma_addr_t sync_dma; /* DMA address of syncbuf */ + unsigned int speed; /* USB_SPEED_XXX */ u64 formats; /* format bitmasks (all or'ed) */ unsigned int num_formats; /* number of supported audio formats (list) */ diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 08dcce53720b..24c511491b45 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -148,8 +148,10 @@ void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force) int i; /* stop urbs (to be sure) */ - deactivate_urbs(subs, force, 1); - wait_clear_urbs(subs); + if (!subs->stream->chip->shutdown) { + deactivate_urbs(subs, force, 1); + wait_clear_urbs(subs); + } for (i = 0; i < MAX_URBS; i++) release_urb_ctx(&subs->dataurb[i]); @@ -895,7 +897,8 @@ void snd_usb_init_substream(struct snd_usb_stream *as, subs->dev = as->chip->dev; subs->txfr_quirk = as->chip->txfr_quirk; subs->ops = audio_urb_ops[stream]; - if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH) + subs->speed = snd_usb_get_speed(subs->dev); + if (subs->speed >= USB_SPEED_HIGH) subs->ops.prepare_sync = prepare_capture_sync_urb_hs; snd_usb_set_pcm_ops(as->pcm, stream); diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 8a818a4573af..b3b63f769916 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v unsigned char buf[2]; int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; int timeout = 10; - int err; + int idx = 0, err; err = snd_usb_autoresume(cval->mixer->chip); if (err < 0) return -EIO; + mutex_lock(&chip->shutdown_mutex); while (timeout-- > 0) { + if (chip->shutdown) + break; + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, val_len) >= val_len) { + validx, idx, buf, val_len) >= val_len) { *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); - snd_usb_autosuspend(cval->mixer->chip); - return 0; + err = 0; + goto out; } } - snd_usb_autosuspend(cval->mixer->chip); snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); - return -EINVAL; + request, validx, idx, cval->val_type); + err = -EINVAL; + + out: + mutex_unlock(&chip->shutdown_mutex); + snd_usb_autosuspend(cval->mixer->chip); + return err; } static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) @@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v struct snd_usb_audio *chip = cval->mixer->chip; unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ unsigned char *val; - int ret, size; + int idx = 0, ret, size; __u8 bRequest; if (request == UAC_GET_CUR) { @@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v if (ret) goto error; - ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, + mutex_lock(&chip->shutdown_mutex); + if (chip->shutdown) + ret = -ENODEV; + else { + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); + ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, size); + validx, idx, buf, size); + } + mutex_unlock(&chip->shutdown_mutex); snd_usb_autosuspend(chip); if (ret < 0) { error: snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); + request, validx, idx, cval->val_type); return ret; } @@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, { struct snd_usb_audio *chip = cval->mixer->chip; unsigned char buf[2]; - int val_len, err, timeout = 10; + int idx = 0, val_len, err, timeout = 10; if (cval->mixer->protocol == UAC_VERSION_1) { val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; @@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, err = snd_usb_autoresume(chip); if (err < 0) return -EIO; - while (timeout-- > 0) + mutex_lock(&chip->shutdown_mutex); + while (timeout-- > 0) { + if (chip->shutdown) + break; + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); if (snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, val_len) >= 0) { - snd_usb_autosuspend(chip); - return 0; + validx, idx, buf, val_len) >= 0) { + err = 0; + goto out; } - snd_usb_autosuspend(chip); + } snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); - return -EINVAL; + request, validx, idx, cval->val_type, buf[0], buf[1]); + err = -EINVAL; + + out: + mutex_unlock(&chip->shutdown_mutex); + snd_usb_autosuspend(chip); + return err; } static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 67a4d6dbb32b..4f49ca75d6f1 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -67,6 +67,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream unsigned int hwptr_done; subs = (struct snd_usb_substream *)substream->runtime->private_data; + if (subs->stream->chip->shutdown) + return SNDRV_PCM_POS_XRUN; spin_lock(&subs->lock); hwptr_done = subs->hwptr_done; substream->runtime->delay = snd_usb_pcm_delay(subs, @@ -373,8 +375,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, changed = subs->cur_audiofmt != fmt || subs->period_bytes != params_period_bytes(hw_params) || subs->cur_rate != rate; + + mutex_lock(&subs->stream->chip->shutdown_mutex); + if (subs->stream->chip->shutdown) { + ret = -ENODEV; + goto unlock; + } if ((ret = set_format(subs, fmt)) < 0) - return ret; + goto unlock; if (subs->cur_rate != rate) { struct usb_host_interface *alts; @@ -383,12 +391,11 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, alts = &iface->altsetting[fmt->altset_idx]; ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate); if (ret < 0) - return ret; + goto unlock; subs->cur_rate = rate; } if (changed) { - mutex_lock(&subs->stream->chip->shutdown_mutex); /* format changed */ snd_usb_release_substream_urbs(subs, 0); /* influenced: period_bytes, channels, rate, format, */ @@ -396,9 +403,10 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, params_rate(hw_params), snd_pcm_format_physical_width(params_format(hw_params)) * params_channels(hw_params)); - mutex_unlock(&subs->stream->chip->shutdown_mutex); } +unlock: + mutex_unlock(&subs->stream->chip->shutdown_mutex); return ret; } @@ -429,12 +437,18 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_usb_substream *subs = runtime->private_data; + int ret = 0; if (! subs->cur_audiofmt) { snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); return -ENXIO; } + mutex_lock(&subs->stream->chip->shutdown_mutex); + if (subs->stream->chip->shutdown) { + ret = -ENODEV; + goto unlock; + } /* some unit conversions in runtime */ subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize); subs->curframesize = bytes_to_frames(runtime, subs->curpacksize); @@ -447,7 +461,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) subs->last_frame_number = 0; runtime->delay = 0; - return snd_usb_substream_prepare(subs, runtime); + ret = snd_usb_substream_prepare(subs, runtime); + unlock: + mutex_unlock(&subs->stream->chip->shutdown_mutex); + return ret; } static struct snd_pcm_hardware snd_usb_hardware = @@ -500,7 +517,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs, return 0; } /* check whether the period time is >= the data packet interval */ - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { + if (subs->speed != USB_SPEED_FULL) { ptime = 125 * (1 << fp->datainterval); if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); @@ -778,7 +795,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre return err; param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; - if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) + if (subs->speed == USB_SPEED_FULL) /* full speed devices have fixed data packet interval */ ptmin = 1000; if (ptmin == 1000) diff --git a/sound/usb/proc.c b/sound/usb/proc.c index 961c9a250686..aef03db3870d 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -107,7 +107,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s } snd_iprintf(buffer, "\n"); } - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) + if (subs->speed != USB_SPEED_FULL) snd_iprintf(buffer, " Data packet interval: %d us\n", 125 * (1 << fp->datainterval)); // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); @@ -128,7 +128,7 @@ static void proc_dump_substream_status(struct snd_usb_substream *subs, struct sn snd_iprintf(buffer, "]\n"); snd_iprintf(buffer, " Packet Size = %d\n", subs->curpacksize); snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", - snd_usb_get_speed(subs->dev) == USB_SPEED_FULL + subs->speed == USB_SPEED_FULL ? get_full_speed_hz(subs->freqm) : get_high_speed_hz(subs->freqm), subs->freqm >> 16, subs->freqm & 0xffff); -- GitLab From 49e44e317fdb73d75a00a058df75a6b6fe172c08 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 12:42:45 +0100 Subject: [PATCH 0953/1799] ALSA: usb-audio: Use rwsem for disconnect protection commit 34f3c89fda4fba9fe689db22253ca8db2f5e6386 upstream. Replace mutex with rwsem for codec->shutdown protection so that concurrent accesses are allowed. Also add the protection to snd_usb_autosuspend() and snd_usb_autoresume(), too. Reported-by: Matthieu CASTET Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/card.c | 12 ++++++++---- sound/usb/mixer.c | 12 ++++++------ sound/usb/pcm.c | 12 ++++++------ sound/usb/usbaudio.h | 2 +- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 4a7be7b98331..147a5c42b95d 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -336,7 +336,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, return -ENOMEM; } - mutex_init(&chip->shutdown_mutex); + init_rwsem(&chip->shutdown_rwsem); chip->index = idx; chip->dev = dev; chip->card = card; @@ -556,7 +556,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, card = chip->card; mutex_lock(®ister_mutex); - mutex_lock(&chip->shutdown_mutex); + down_write(&chip->shutdown_rwsem); chip->shutdown = 1; chip->num_interfaces--; if (chip->num_interfaces <= 0) { @@ -574,11 +574,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, snd_usb_mixer_disconnect(p); } usb_chip[chip->index] = NULL; - mutex_unlock(&chip->shutdown_mutex); + up_write(&chip->shutdown_rwsem); mutex_unlock(®ister_mutex); snd_card_free_when_closed(card); } else { - mutex_unlock(&chip->shutdown_mutex); + up_write(&chip->shutdown_rwsem); mutex_unlock(®ister_mutex); } } @@ -610,16 +610,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) { int err = -ENODEV; + down_read(&chip->shutdown_rwsem); if (!chip->shutdown && !chip->probing) err = usb_autopm_get_interface(chip->pm_intf); + up_read(&chip->shutdown_rwsem); return err; } void snd_usb_autosuspend(struct snd_usb_audio *chip) { + down_read(&chip->shutdown_rwsem); if (!chip->shutdown && !chip->probing) usb_autopm_put_interface(chip->pm_intf); + up_read(&chip->shutdown_rwsem); } static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index b3b63f769916..29ae209344d4 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -292,7 +292,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v err = snd_usb_autoresume(cval->mixer->chip); if (err < 0) return -EIO; - mutex_lock(&chip->shutdown_mutex); + down_read(&chip->shutdown_rwsem); while (timeout-- > 0) { if (chip->shutdown) break; @@ -310,7 +310,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v err = -EINVAL; out: - mutex_unlock(&chip->shutdown_mutex); + up_read(&chip->shutdown_rwsem); snd_usb_autosuspend(cval->mixer->chip); return err; } @@ -337,7 +337,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v if (ret) goto error; - mutex_lock(&chip->shutdown_mutex); + down_read(&chip->shutdown_rwsem); if (chip->shutdown) ret = -ENODEV; else { @@ -346,7 +346,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx, idx, buf, size); } - mutex_unlock(&chip->shutdown_mutex); + up_read(&chip->shutdown_rwsem); snd_usb_autosuspend(chip); if (ret < 0) { @@ -453,7 +453,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, err = snd_usb_autoresume(chip); if (err < 0) return -EIO; - mutex_lock(&chip->shutdown_mutex); + down_read(&chip->shutdown_rwsem); while (timeout-- > 0) { if (chip->shutdown) break; @@ -471,7 +471,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, err = -EINVAL; out: - mutex_unlock(&chip->shutdown_mutex); + up_read(&chip->shutdown_rwsem); snd_usb_autosuspend(chip); return err; } diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 4f49ca75d6f1..4a99f6ca4b66 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -376,7 +376,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, subs->period_bytes != params_period_bytes(hw_params) || subs->cur_rate != rate; - mutex_lock(&subs->stream->chip->shutdown_mutex); + down_read(&subs->stream->chip->shutdown_rwsem); if (subs->stream->chip->shutdown) { ret = -ENODEV; goto unlock; @@ -406,7 +406,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, } unlock: - mutex_unlock(&subs->stream->chip->shutdown_mutex); + up_read(&subs->stream->chip->shutdown_rwsem); return ret; } @@ -422,9 +422,9 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->cur_audiofmt = NULL; subs->cur_rate = 0; subs->period_bytes = 0; - mutex_lock(&subs->stream->chip->shutdown_mutex); + down_read(&subs->stream->chip->shutdown_rwsem); snd_usb_release_substream_urbs(subs, 0); - mutex_unlock(&subs->stream->chip->shutdown_mutex); + up_read(&subs->stream->chip->shutdown_rwsem); return snd_pcm_lib_free_vmalloc_buffer(substream); } @@ -444,7 +444,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) return -ENXIO; } - mutex_lock(&subs->stream->chip->shutdown_mutex); + down_read(&subs->stream->chip->shutdown_rwsem); if (subs->stream->chip->shutdown) { ret = -ENODEV; goto unlock; @@ -463,7 +463,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) ret = snd_usb_substream_prepare(subs, runtime); unlock: - mutex_unlock(&subs->stream->chip->shutdown_mutex); + up_read(&subs->stream->chip->shutdown_rwsem); return ret; } diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 3e2b03577936..6c805a51d7d7 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -36,7 +36,7 @@ struct snd_usb_audio { struct snd_card *card; struct usb_interface *pm_intf; u32 usb_id; - struct mutex shutdown_mutex; + struct rw_semaphore shutdown_rwsem; unsigned int shutdown:1; unsigned int probing:1; unsigned int autosuspended:1; -- GitLab From 1c694ffc72666085a5ad880fef913ee2c8c69c4a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 12:42:46 +0100 Subject: [PATCH 0954/1799] ALSA: usb-audio: Fix races at disconnection in mixer_quirks.c commit 888ea7d5ac6815ba16b3b3a20f665a92c7af6724 upstream. Similar like the previous commit, cover with chip->shutdown_rwsem and chip->shutdown checks. Reported-by: Matthieu CASTET Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/mixer_quirks.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index ab125ee0b0f0..38a607a7ae2c 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -186,6 +186,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (value > 1) return -EINVAL; changed = value != mixer->audigy2nx_leds[index]; + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) { + err = -ENODEV; + goto out; + } if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) err = snd_usb_ctl_msg(mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, @@ -202,6 +207,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, value, index + 2, NULL, 0); + out: + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; mixer->audigy2nx_leds[index] = value; @@ -295,11 +302,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, for (i = 0; jacks[i].name; ++i) { snd_iprintf(buffer, "%s: ", jacks[i].name); - err = snd_usb_ctl_msg(mixer->chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = 0; + else + err = snd_usb_ctl_msg(mixer->chip->dev, usb_rcvctrlpipe(mixer->chip->dev, 0), UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, jacks[i].unitid << 8, buf, 3); + up_read(&mixer->chip->shutdown_rwsem); if (err == 3 && (buf[0] == 3 || buf[0] == 6)) snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); else @@ -329,10 +341,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, else new_status = old_status & ~0x02; changed = new_status != old_status; - err = snd_usb_ctl_msg(mixer->chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = -ENODEV; + else + err = snd_usb_ctl_msg(mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, 50, 0, &new_status, 1); + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; mixer->xonar_u1_status = new_status; @@ -371,11 +388,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, u8 bRequest = (kcontrol->private_value >> 16) & 0xff; u16 wIndex = kcontrol->private_value & 0xffff; u8 tmp; + int ret; - int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + ret = -ENODEV; + else + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0, cpu_to_le16(wIndex), &tmp, sizeof(tmp), 1000); + up_read(&mixer->chip->shutdown_rwsem); if (ret < 0) { snd_printk(KERN_ERR @@ -396,11 +419,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, u8 bRequest = (kcontrol->private_value >> 16) & 0xff; u16 wIndex = kcontrol->private_value & 0xffff; u16 wValue = ucontrol->value.integer.value[0]; + int ret; - int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + ret = -ENODEV; + else + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, cpu_to_le16(wValue), cpu_to_le16(wIndex), NULL, 0, 1000); + up_read(&mixer->chip->shutdown_rwsem); if (ret < 0) { snd_printk(KERN_ERR -- GitLab From 41a496238dae4c117548be819b0a3b3edbc48dc8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 12:42:47 +0100 Subject: [PATCH 0955/1799] ALSA: Add a reference counter to card instance commit a0830dbd4e42b38aefdf3fb61ba5019a1a99ea85 upstream. For more strict protection for wild disconnections, a refcount is introduced to the card instance, and let it up/down when an object is referred via snd_lookup_*() in the open ops. The free-after-last-close check is also changed to check this refcount instead of the empty list, too. Reported-by: Matthieu CASTET Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- include/sound/core.h | 3 +++ sound/core/compress_offload.c | 9 +++++-- sound/core/control.c | 3 +++ sound/core/hwdep.c | 5 +++- sound/core/init.c | 50 +++++++++++++++++++++-------------- sound/core/oss/mixer_oss.c | 10 +++++-- sound/core/oss/pcm_oss.c | 2 ++ sound/core/pcm_native.c | 9 +++++-- sound/core/rawmidi.c | 6 ++++- sound/core/sound.c | 11 ++++++-- sound/core/sound_oss.c | 10 +++++-- 11 files changed, 86 insertions(+), 32 deletions(-) diff --git a/include/sound/core.h b/include/sound/core.h index bc056687f647..93896ad1fcdd 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -132,6 +132,7 @@ struct snd_card { int shutdown; /* this card is going down */ int free_on_last_close; /* free in context of file_release */ wait_queue_head_t shutdown_sleep; + atomic_t refcount; /* refcount for disconnection */ struct device *dev; /* device assigned to this card */ struct device *card_dev; /* cardX object for sysfs */ @@ -189,6 +190,7 @@ struct snd_minor { const struct file_operations *f_ops; /* file operations */ void *private_data; /* private data for f_ops->open */ struct device *dev; /* device for sysfs */ + struct snd_card *card_ptr; /* assigned card instance */ }; /* return a device pointer linked to each sound device as a parent */ @@ -295,6 +297,7 @@ int snd_card_info_done(void); int snd_component_add(struct snd_card *card, const char *component); int snd_card_file_add(struct snd_card *card, struct file *file); int snd_card_file_remove(struct snd_card *card, struct file *file); +void snd_card_unref(struct snd_card *card); #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr)) diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index a68aed7fce02..a58cf3594130 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -102,12 +102,15 @@ static int snd_compr_open(struct inode *inode, struct file *f) if (dirn != compr->direction) { pr_err("this device doesn't support this direction\n"); + snd_card_unref(compr->card); return -EINVAL; } data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) + if (!data) { + snd_card_unref(compr->card); return -ENOMEM; + } data->stream.ops = compr->ops; data->stream.direction = dirn; data->stream.private_data = compr->private_data; @@ -115,6 +118,7 @@ static int snd_compr_open(struct inode *inode, struct file *f) runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); if (!runtime) { kfree(data); + snd_card_unref(compr->card); return -ENOMEM; } runtime->state = SNDRV_PCM_STATE_OPEN; @@ -128,7 +132,8 @@ static int snd_compr_open(struct inode *inode, struct file *f) kfree(runtime); kfree(data); } - return ret; + snd_card_unref(compr->card); + return 0; } static int snd_compr_free(struct inode *inode, struct file *f) diff --git a/sound/core/control.c b/sound/core/control.c index 2487a6bb1c54..151597b431af 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -86,6 +86,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file) write_lock_irqsave(&card->ctl_files_rwlock, flags); list_add_tail(&ctl->list, &card->ctl_files); write_unlock_irqrestore(&card->ctl_files_rwlock, flags); + snd_card_unref(card); return 0; __error: @@ -93,6 +94,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file) __error2: snd_card_file_remove(card, file); __error1: + if (card) + snd_card_unref(card); return err; } diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 75ea16f35b1a..53a6ba5ad615 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -100,8 +100,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) if (hw == NULL) return -ENODEV; - if (!try_module_get(hw->card->module)) + if (!try_module_get(hw->card->module)) { + snd_card_unref(hw->card); return -EFAULT; + } init_waitqueue_entry(&wait, current); add_wait_queue(&hw->open_wait, &wait); @@ -148,6 +150,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) mutex_unlock(&hw->open_mutex); if (err < 0) module_put(hw->card->module); + snd_card_unref(hw->card); return err; } diff --git a/sound/core/init.c b/sound/core/init.c index d8ec849af128..7b012d15c2cf 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -213,6 +213,7 @@ int snd_card_create(int idx, const char *xid, spin_lock_init(&card->files_lock); INIT_LIST_HEAD(&card->files_list); init_waitqueue_head(&card->shutdown_sleep); + atomic_set(&card->refcount, 0); #ifdef CONFIG_PM mutex_init(&card->power_lock); init_waitqueue_head(&card->power_sleep); @@ -446,21 +447,36 @@ static int snd_card_do_free(struct snd_card *card) return 0; } +/** + * snd_card_unref - release the reference counter + * @card: the card instance + * + * Decrements the reference counter. When it reaches to zero, wake up + * the sleeper and call the destructor if needed. + */ +void snd_card_unref(struct snd_card *card) +{ + if (atomic_dec_and_test(&card->refcount)) { + wake_up(&card->shutdown_sleep); + if (card->free_on_last_close) + snd_card_do_free(card); + } +} +EXPORT_SYMBOL(snd_card_unref); + int snd_card_free_when_closed(struct snd_card *card) { - int free_now = 0; - int ret = snd_card_disconnect(card); - if (ret) - return ret; + int ret; - spin_lock(&card->files_lock); - if (list_empty(&card->files_list)) - free_now = 1; - else - card->free_on_last_close = 1; - spin_unlock(&card->files_lock); + atomic_inc(&card->refcount); + ret = snd_card_disconnect(card); + if (ret) { + atomic_dec(&card->refcount); + return ret; + } - if (free_now) + card->free_on_last_close = 1; + if (atomic_dec_and_test(&card->refcount)) snd_card_do_free(card); return 0; } @@ -474,7 +490,7 @@ int snd_card_free(struct snd_card *card) return ret; /* wait, until all devices are ready for the free operation */ - wait_event(card->shutdown_sleep, list_empty(&card->files_list)); + wait_event(card->shutdown_sleep, !atomic_read(&card->refcount)); snd_card_do_free(card); return 0; } @@ -886,6 +902,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file) return -ENODEV; } list_add(&mfile->list, &card->files_list); + atomic_inc(&card->refcount); spin_unlock(&card->files_lock); return 0; } @@ -908,7 +925,6 @@ EXPORT_SYMBOL(snd_card_file_add); int snd_card_file_remove(struct snd_card *card, struct file *file) { struct snd_monitor_file *mfile, *found = NULL; - int last_close = 0; spin_lock(&card->files_lock); list_for_each_entry(mfile, &card->files_list, list) { @@ -923,19 +939,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) break; } } - if (list_empty(&card->files_list)) - last_close = 1; spin_unlock(&card->files_lock); - if (last_close) { - wake_up(&card->shutdown_sleep); - if (card->free_on_last_close) - snd_card_do_free(card); - } if (!found) { snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); return -ENOENT; } kfree(found); + snd_card_unref(card); return 0; } diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 18297f7f2c55..05395aaeaa32 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) SNDRV_OSS_DEVICE_TYPE_MIXER); if (card == NULL) return -ENODEV; - if (card->mixer_oss == NULL) + if (card->mixer_oss == NULL) { + snd_card_unref(card); return -ENODEV; + } err = snd_card_file_add(card, file); - if (err < 0) + if (err < 0) { + snd_card_unref(card); return err; + } fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL); if (fmixer == NULL) { snd_card_file_remove(card, file); + snd_card_unref(card); return -ENOMEM; } fmixer->card = card; @@ -68,6 +73,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) if (!try_module_get(card->module)) { kfree(fmixer); snd_card_file_remove(card, file); + snd_card_unref(card); return -EFAULT; } return 0; diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 08fde0060fd9..2529e01538e9 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2457,6 +2457,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) __error2: snd_card_file_remove(pcm->card, file); __error1: + if (pcm) + snd_card_unref(pcm->card); return err; } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 608a2e18d6df..98e7591de6ea 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1631,6 +1631,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) write_unlock_irq(&snd_pcm_link_rwlock); up_write(&snd_pcm_link_rwsem); _nolock: + snd_card_unref(substream1->pcm->card); fput(file); if (res < 0) kfree(group); @@ -2105,7 +2106,9 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file) return err; pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_PLAYBACK); - return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); + err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); + snd_card_unref(pcm->card); + return err; } static int snd_pcm_capture_open(struct inode *inode, struct file *file) @@ -2116,7 +2119,9 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) return err; pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_CAPTURE); - return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); + err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); + snd_card_unref(pcm->card); + return err; } static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index ebf6e49ad3d4..7d4f62ab6711 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -379,8 +379,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) if (rmidi == NULL) return -ENODEV; - if (!try_module_get(rmidi->card->module)) + if (!try_module_get(rmidi->card->module)) { + snd_card_unref(rmidi->card); return -ENXIO; + } mutex_lock(&rmidi->open_mutex); card = rmidi->card; @@ -440,6 +442,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) #endif file->private_data = rawmidi_file; mutex_unlock(&rmidi->open_mutex); + snd_card_unref(rmidi->card); return 0; __error: @@ -447,6 +450,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) __error_card: mutex_unlock(&rmidi->open_mutex); module_put(rmidi->card->module); + snd_card_unref(rmidi->card); return err; } diff --git a/sound/core/sound.c b/sound/core/sound.c index 28f35593a750..7c0640eeee52 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -99,6 +99,10 @@ static void snd_request_other(int minor) * * Checks that a minor device with the specified type is registered, and returns * its user data pointer. + * + * This function increments the reference counter of the card instance + * if an associated instance with the given minor number and type is found. + * The caller must call snd_card_unref() appropriately later. */ void *snd_lookup_minor_data(unsigned int minor, int type) { @@ -109,9 +113,11 @@ void *snd_lookup_minor_data(unsigned int minor, int type) return NULL; mutex_lock(&sound_mutex); mreg = snd_minors[minor]; - if (mreg && mreg->type == type) + if (mreg && mreg->type == type) { private_data = mreg->private_data; - else + if (mreg->card_ptr) + atomic_inc(&mreg->card_ptr->refcount); + } else private_data = NULL; mutex_unlock(&sound_mutex); return private_data; @@ -276,6 +282,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev, preg->device = dev; preg->f_ops = f_ops; preg->private_data = private_data; + preg->card_ptr = card; mutex_lock(&sound_mutex); #ifdef CONFIG_SND_DYNAMIC_MINORS minor = snd_find_free_minor(type); diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index c70092043061..7442c7ac2469 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -40,6 +40,9 @@ static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; static DEFINE_MUTEX(sound_oss_mutex); +/* NOTE: This function increments the refcount of the associated card like + * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately + */ void *snd_lookup_oss_minor_data(unsigned int minor, int type) { struct snd_minor *mreg; @@ -49,9 +52,11 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) return NULL; mutex_lock(&sound_oss_mutex); mreg = snd_oss_minors[minor]; - if (mreg && mreg->type == type) + if (mreg && mreg->type == type) { private_data = mreg->private_data; - else + if (mreg->card_ptr) + atomic_inc(&mreg->card_ptr->refcount); + } else private_data = NULL; mutex_unlock(&sound_oss_mutex); return private_data; @@ -123,6 +128,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, preg->device = dev; preg->f_ops = f_ops; preg->private_data = private_data; + preg->card_ptr = card; mutex_lock(&sound_oss_mutex); snd_oss_minors[minor] = preg; minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); -- GitLab From 9de4f2694044af68a826a568f0c97b1b83b5b173 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 12:42:48 +0100 Subject: [PATCH 0956/1799] ALSA: Avoid endless sleep after disconnect commit 0914f7961babbf28aaa2f19b453951fb4841c03f upstream. When disconnect callback is called, each component should wake up sleepers and check card->shutdown flag for avoiding the endless sleep blocking the proper resource release. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/control.c | 2 ++ sound/core/hwdep.c | 7 +++++++ sound/core/oss/pcm_oss.c | 4 ++++ sound/core/pcm.c | 6 +++++- sound/core/pcm_native.c | 8 ++++++++ sound/core/rawmidi.c | 20 ++++++++++++++++++++ 6 files changed, 46 insertions(+), 1 deletion(-) diff --git a/sound/core/control.c b/sound/core/control.c index 151597b431af..daa4fc8872f3 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1436,6 +1436,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, spin_unlock_irq(&ctl->read_lock); schedule(); remove_wait_queue(&ctl->change_sleep, &wait); + if (ctl->card->shutdown) + return -ENODEV; if (signal_pending(current)) return -ERESTARTSYS; spin_lock_irq(&ctl->read_lock); diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 53a6ba5ad615..3f7f6628cf7b 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -131,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) mutex_unlock(&hw->open_mutex); schedule(); mutex_lock(&hw->open_mutex); + if (hw->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -462,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) mutex_unlock(®ister_mutex); return -EINVAL; } + mutex_lock(&hwdep->open_mutex); + wake_up(&hwdep->open_wait); #ifdef CONFIG_SND_OSSEMUL if (hwdep->ossreg) snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); #endif snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); list_del_init(&hwdep->list); + mutex_unlock(&hwdep->open_mutex); mutex_unlock(®ister_mutex); return 0; } diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 2529e01538e9..f337b66a020b 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) mutex_unlock(&pcm->open_mutex); schedule(); mutex_lock(&pcm->open_mutex); + if (pcm->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 099f3fdd120a..e30e1be30a21 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1087,12 +1087,16 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) goto unlock; mutex_lock(&pcm->open_mutex); + wake_up(&pcm->open_wait); list_del_init(&pcm->list); for (cidx = 0; cidx < 2; cidx++) for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { snd_pcm_stream_lock_irq(substream); - if (substream->runtime) + if (substream->runtime) { substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; + wake_up(&substream->runtime->sleep); + wake_up(&substream->runtime->tsleep); + } snd_pcm_stream_unlock_irq(substream); } list_for_each_entry(notify, &snd_pcm_notify_list, list) { diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 98e7591de6ea..0844444eb100 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1508,6 +1508,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, down_read(&snd_pcm_link_rwsem); snd_pcm_stream_lock_irq(substream); remove_wait_queue(&to_check->sleep, &wait); + if (card->shutdown) { + result = -ENODEV; + break; + } if (tout == 0) { if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) result = -ESTRPIPE; @@ -2158,6 +2162,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) mutex_unlock(&pcm->open_mutex); schedule(); mutex_lock(&pcm->open_mutex); + if (pcm->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 7d4f62ab6711..1bb95aeea084 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -424,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) mutex_unlock(&rmidi->open_mutex); schedule(); mutex_lock(&rmidi->open_mutex); + if (rmidi->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -995,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun spin_unlock_irq(&runtime->lock); schedule(); remove_wait_queue(&runtime->sleep, &wait); + if (rfile->rmidi->card->shutdown) + return -ENODEV; if (signal_pending(current)) return result > 0 ? result : -ERESTARTSYS; if (!runtime->avail) @@ -1238,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, spin_unlock_irq(&runtime->lock); timeout = schedule_timeout(30 * HZ); remove_wait_queue(&runtime->sleep, &wait); + if (rfile->rmidi->card->shutdown) + return -ENODEV; if (signal_pending(current)) return result > 0 ? result : -ERESTARTSYS; if (!runtime->avail && !timeout) @@ -1613,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device) static int snd_rawmidi_dev_disconnect(struct snd_device *device) { struct snd_rawmidi *rmidi = device->device_data; + int dir; mutex_lock(®ister_mutex); + mutex_lock(&rmidi->open_mutex); + wake_up(&rmidi->open_wait); list_del_init(&rmidi->list); + for (dir = 0; dir < 2; dir++) { + struct snd_rawmidi_substream *s; + list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { + if (s->runtime) + wake_up(&s->runtime->sleep); + } + } + #ifdef CONFIG_SND_OSSEMUL if (rmidi->ossreg) { if ((int)rmidi->device == midi_map[rmidi->card->number]) { @@ -1630,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) } #endif /* CONFIG_SND_OSSEMUL */ snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); + mutex_unlock(&rmidi->open_mutex); mutex_unlock(®ister_mutex); return 0; } -- GitLab From c2f5b7507ac5d808f29287d77ee6148358d7fbfe Mon Sep 17 00:00:00 2001 From: Zijie Pan Date: Mon, 15 Oct 2012 03:56:39 +0000 Subject: [PATCH 0957/1799] sctp: fix call to SCTP_CMD_PROCESS_SACK in sctp_cmd_interpreter() [ Upstream commit f6e80abeab928b7c47cc1fbf53df13b4398a2bec ] Bug introduced by commit edfee0339e681a784ebacec7e8c2dc97dc6d2839 (sctp: check src addr when processing SACK to update transport state) Signed-off-by: Zijie Pan Signed-off-by: Nicolas Dichtel Acked-by: Vlad Yasevich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/sm_sideeffect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 1ff51c9d18d5..2fdb05d8aac8 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1610,8 +1610,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, asoc->outqueue.outstanding_bytes; sackh.num_gap_ack_blocks = 0; sackh.num_dup_tsns = 0; + chunk->subh.sack_hdr = &sackh; sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, - SCTP_SACKH(&sackh)); + SCTP_CHUNK(chunk)); break; case SCTP_CMD_DISCARD_PACKET: -- GitLab From 0f04b9af7ce98a3db1c4401cced1fef321a9dd57 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 18 Oct 2012 03:21:55 +0000 Subject: [PATCH 0958/1799] netlink: use kfree_rcu() in netlink_release() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 6d772ac5578f711d1ce7b03535d1c95bffb21dff ] On some suspend/resume operations involving wimax device, we have noticed some intermittent memory corruptions in netlink code. Stéphane Marchesin tracked this corruption in netlink_update_listeners() and suggested a patch. It appears netlink_release() should use kfree_rcu() instead of kfree() for the listeners structure as it may be used by other cpus using RCU protection. netlink_release() must set to NULL the listeners pointer when it is about to be freed. Also have to protect netlink_update_listeners() and netlink_has_listeners() if listeners is NULL. Add a nl_deref_protected() lockdep helper to properly document which locks protects us. Reported-by: Jonathan Kliegman Signed-off-by: Eric Dumazet Cc: Stéphane Marchesin Cc: Sam Leffler Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/netlink/af_netlink.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index edce424048d8..9017e3ef8fee 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -137,6 +137,8 @@ static void netlink_destroy_callback(struct netlink_callback *cb); static DEFINE_RWLOCK(nl_table_lock); static atomic_t nl_table_users = ATOMIC_INIT(0); +#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock)); + static ATOMIC_NOTIFIER_HEAD(netlink_chain); static inline u32 netlink_group_mask(u32 group) @@ -332,6 +334,11 @@ netlink_update_listeners(struct sock *sk) struct hlist_node *node; unsigned long mask; unsigned int i; + struct listeners *listeners; + + listeners = nl_deref_protected(tbl->listeners); + if (!listeners) + return; for (i = 0; i < NLGRPLONGS(tbl->groups); i++) { mask = 0; @@ -339,7 +346,7 @@ netlink_update_listeners(struct sock *sk) if (i < NLGRPLONGS(nlk_sk(sk)->ngroups)) mask |= nlk_sk(sk)->groups[i]; } - tbl->listeners->masks[i] = mask; + listeners->masks[i] = mask; } /* this function is only called with the netlink table "grabbed", which * makes sure updates are visible before bind or setsockopt return. */ @@ -520,7 +527,11 @@ static int netlink_release(struct socket *sock) if (netlink_is_kernel(sk)) { BUG_ON(nl_table[sk->sk_protocol].registered == 0); if (--nl_table[sk->sk_protocol].registered == 0) { - kfree(nl_table[sk->sk_protocol].listeners); + struct listeners *old; + + old = nl_deref_protected(nl_table[sk->sk_protocol].listeners); + RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL); + kfree_rcu(old, rcu); nl_table[sk->sk_protocol].module = NULL; nl_table[sk->sk_protocol].registered = 0; } @@ -950,7 +961,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group) rcu_read_lock(); listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners); - if (group - 1 < nl_table[sk->sk_protocol].groups) + if (listeners && group - 1 < nl_table[sk->sk_protocol].groups) res = test_bit(group - 1, listeners->masks); rcu_read_unlock(); @@ -1582,7 +1593,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups) new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC); if (!new) return -ENOMEM; - old = rcu_dereference_protected(tbl->listeners, 1); + old = nl_deref_protected(tbl->listeners); memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups)); rcu_assign_pointer(tbl->listeners, new); -- GitLab From d1a94e022b36342cbdb156a9693bca95aab11ca4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 18 Oct 2012 09:14:12 +0000 Subject: [PATCH 0959/1799] tcp: fix FIONREAD/SIOCINQ [ Upstream commit a3374c42aa5f7237e87ff3b0622018636b0c847e ] tcp_ioctl() tries to take into account if tcp socket received a FIN to report correct number bytes in receive queue. But its flaky because if the application ate the last skb, we return 1 instead of 0. Correct way to detect that FIN was received is to test SOCK_DONE. Reported-by: Elliot Hughes Signed-off-by: Eric Dumazet Cc: Neal Cardwell Cc: Tom Herbert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 8fbe2e20e7cc..01870bd29193 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -481,14 +481,12 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) !tp->urg_data || before(tp->urg_seq, tp->copied_seq) || !before(tp->urg_seq, tp->rcv_nxt)) { - struct sk_buff *skb; answ = tp->rcv_nxt - tp->copied_seq; - /* Subtract 1, if FIN is in queue. */ - skb = skb_peek_tail(&sk->sk_receive_queue); - if (answ && skb) - answ -= tcp_hdr(skb)->fin; + /* Subtract 1, if FIN was received */ + if (answ && sock_flag(sk, SOCK_DONE)) + answ--; } else answ = tp->urg_seq - tp->copied_seq; release_sock(sk); -- GitLab From d707b52912bfa83176b75efd40da193c18eef1e0 Mon Sep 17 00:00:00 2001 From: Li RongQing Date: Wed, 24 Oct 2012 14:01:18 +0800 Subject: [PATCH 0960/1799] ipv6: Set default hoplimit as zero. [ Upstream commit 14edd87dc67311556f1254a8f29cf4dd6cb5b7d1 ] Commit a02e4b7dae4551(Demark default hoplimit as zero) only changes the hoplimit checking condition and default value in ip6_dst_hoplimit, not zeros all hoplimit default value. Keep the zeroing ip6_template_metrics[RTAX_HOPLIMIT - 1] to force it as const, cause as a37e6e344910(net: force dst_default_metrics to const section) Signed-off-by: Li RongQing Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/route.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 2796b374cb2b..b84cba195509 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -203,7 +203,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { }; static const u32 ip6_template_metrics[RTAX_MAX] = { - [RTAX_HOPLIMIT - 1] = 255, + [RTAX_HOPLIMIT - 1] = 0, }; static struct rt6_info ip6_null_entry_template = { @@ -1135,7 +1135,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, rt->rt6i_dst.addr = fl6->daddr; rt->rt6i_dst.plen = 128; rt->rt6i_idev = idev; - dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); + dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0); spin_lock_bh(&icmp6_dst_lock); rt->dst.next = icmp6_dst_gc_list; -- GitLab From 545bc464cb07b204fbfb387a7010f31352e03625 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Thu, 25 Oct 2012 18:17:54 +0000 Subject: [PATCH 0961/1799] net: usb: Fix memory leak on Tx data path [ Upstream commit 39707c2a3ba5011038b363f84d37c8a98d2d9db1 ] Driver anchors the tx urbs and defers the urb submission if a transmit request comes when the interface is suspended. Anchoring urb increments the urb reference count. These deferred urbs are later accessed by calling usb_get_from_anchor() for submission during interface resume. usb_get_from_anchor() unanchors the urb but urb reference count remains same. This causes the urb reference count to remain non-zero after usb_free_urb() gets called and urb never gets freed. Hence call usb_put_urb() after anchoring the urb to properly balance the reference count for these deferred urbs. Also, unanchor these deferred urbs during disconnect, to free them up. Signed-off-by: Hemant Kumar Acked-by: Oliver Neukum Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/usbnet.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index b38db48b1ce0..174aece3b90a 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1158,6 +1158,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, usb_anchor_urb(urb, &dev->deferred); /* no use to process more packets */ netif_stop_queue(net); + usb_put_urb(urb); spin_unlock_irqrestore(&dev->txq.lock, flags); netdev_dbg(dev->net, "Delaying transmission for resumption\n"); goto deferred; @@ -1299,6 +1300,8 @@ void usbnet_disconnect (struct usb_interface *intf) cancel_work_sync(&dev->kevent); + usb_scuttle_anchored_urbs(&dev->deferred); + if (dev->driver_info->unbind) dev->driver_info->unbind (dev, intf); -- GitLab From b97ecda6f44e089c4a25be7aaa44b3337c860d56 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Wed, 31 Oct 2012 02:45:32 +0000 Subject: [PATCH 0962/1799] net: fix divide by zero in tcp algorithm illinois [ Upstream commit 8f363b77ee4fbf7c3bbcf5ec2c5ca482d396d664 ] Reading TCP stats when using TCP Illinois congestion control algorithm can cause a divide by zero kernel oops. The division by zero occur in tcp_illinois_info() at: do_div(t, ca->cnt_rtt); where ca->cnt_rtt can become zero (when rtt_reset is called) Steps to Reproduce: 1. Register tcp_illinois: # sysctl -w net.ipv4.tcp_congestion_control=illinois 2. Monitor internal TCP information via command "ss -i" # watch -d ss -i 3. Establish new TCP conn to machine Either it fails at the initial conn, or else it needs to wait for a loss or a reset. This is only related to reading stats. The function avg_delay() also performs the same divide, but is guarded with a (ca->cnt_rtt > 0) at its calling point in update_params(). Thus, simply fix tcp_illinois_info(). Function tcp_illinois_info() / get_info() is called without socket lock. Thus, eliminate any race condition on ca->cnt_rtt by using a local stack variable. Simply reuse info.tcpv_rttcnt, as its already set to ca->cnt_rtt. Function avg_delay() is not affected by this race condition, as its called with the socket lock. Cc: Petr Matousek Signed-off-by: Jesper Dangaard Brouer Acked-by: Eric Dumazet Acked-by: Stephen Hemminger Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_illinois.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index 813b43a76fec..834857f3c871 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c @@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext, .tcpv_rttcnt = ca->cnt_rtt, .tcpv_minrtt = ca->base_rtt, }; - u64 t = ca->sum_rtt; - do_div(t, ca->cnt_rtt); - info.tcpv_rtt = t; + if (info.tcpv_rttcnt > 0) { + u64 t = ca->sum_rtt; + do_div(t, info.tcpv_rttcnt); + info.tcpv_rtt = t; + } nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); } } -- GitLab From 808235fefa3de34ff292cc86b0edfad17a6f056e Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Sun, 28 Oct 2012 06:12:00 +0000 Subject: [PATCH 0963/1799] drivers/net/ethernet/nxp/lpc_eth.c: Call mdiobus_unregister before mdiobus_free [ Upstream commit 57c10b61c84bfed68b1b317d6f507a392724b9c4 ] Based on commit b27393aecf66199f5ddad37c302d3e0cfadbe6c0 Calling mdiobus_free without calling mdiobus_unregister causes BUG_ON(). This patch fixes the issue. The semantic patch that found this issue(http://coccinelle.lip6.fr/): // @@ expression E; @@ ... when != mdiobus_unregister(E); + mdiobus_unregister(E); mdiobus_free(E); // Signed-off-by: Peter Senna Tschudin Tested-by: Roland Stigge Tested-by: Alexandre Pereira da Silva Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/nxp/lpc_eth.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 0c5edc17a1e0..077bb00cbac2 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1523,6 +1523,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev) pldat->dma_buff_base_p); free_irq(ndev->irq, ndev); iounmap(pldat->net_base); + mdiobus_unregister(pldat->mii_bus); mdiobus_free(pldat->mii_bus); clk_disable(pldat->clk); clk_put(pldat->clk); -- GitLab From 988aaa6d344cdd838db420919dc26b3c0248e65a Mon Sep 17 00:00:00 2001 From: Tom Parkin Date: Mon, 29 Oct 2012 23:41:48 +0000 Subject: [PATCH 0964/1799] l2tp: fix oops in l2tp_eth_create() error path [ Upstream commit 789336360e0a2aeb9750c16ab704a02cbe035e9e ] When creating an L2TPv3 Ethernet session, if register_netdev() should fail for any reason (for example, automatic naming for "l2tpeth%d" interfaces hits the 32k-interface limit), the netdev is freed in the error path. However, the l2tp_eth_sess structure's dev pointer is left uncleared, and this results in l2tp_eth_delete() then attempting to unregister the same netdev later in the session teardown. This results in an oops. To avoid this, clear the session dev pointer in the error path. Signed-off-by: Tom Parkin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/l2tp/l2tp_eth.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 5c829077b256..ab9a293ad034 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -269,6 +269,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p out_del_dev: free_netdev(dev); + spriv->dev = NULL; out_del_session: l2tp_session_delete(session); out: -- GitLab From ecdebbf0aedbedc96ee784046d06d0be8152d5a4 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 3 Nov 2012 09:30:34 +0000 Subject: [PATCH 0965/1799] net: inet_diag -- Return error code if protocol handler is missed [ Upstream commit cacb6ba0f36ab14a507f4ee7697e8332899015d2 ] We've observed that in case if UDP diag module is not supported in kernel the netlink returns NLMSG_DONE without notifying a caller that handler is missed. This patch makes __inet_diag_dump to return error code instead. So as example it become possible to detect such situation and handle it gracefully on userspace level. Signed-off-by: Cyrill Gorcunov CC: David Miller CC: Eric Dumazet CC: Pavel Emelyanov Acked-by: Pavel Emelyanov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/inet_diag.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 8f8db724bfaf..dda5383a6f0b 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -875,13 +875,16 @@ static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, struct inet_diag_req_v2 *r, struct nlattr *bc) { const struct inet_diag_handler *handler; + int err = 0; handler = inet_diag_lock_handler(r->sdiag_protocol); if (!IS_ERR(handler)) handler->dump(skb, cb, r, bc); + else + err = PTR_ERR(handler); inet_diag_unlock_handler(handler); - return skb->len; + return err ? : skb->len; } static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) -- GitLab From 0f2835b0b762391fb8e1d1da3bdb8f1d90a5d53e Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Tue, 6 Nov 2012 02:10:10 +0000 Subject: [PATCH 0966/1799] af-packet: fix oops when socket is not present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit a3d744e995d2b936c500585ae39d99ee251c89b4 ] Due to a NULL dereference, the following patch is causing oops in normal trafic condition: commit c0de08d04215031d68fa13af36f347a6cfa252ca Author: Eric Leblond Date:   Thu Aug 16 22:02:58 2012 +0000     af_packet: don't emit packet on orig fanout group This buggy patch was a feature fix and has reached most stable branches. When skb->sk is NULL and when packet fanout is used, there is a crash in match_fanout_group where skb->sk is accessed. This patch fixes the issue by returning false as soon as the socket is NULL: this correspond to the wanted behavior because the kernel as to resend the skb to all the listening socket in this case. Signed-off-by: Eric Leblond 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 82ca51bc29ed..24a21f36a477 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1643,7 +1643,7 @@ static inline int deliver_skb(struct sk_buff *skb, static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb) { - if (ptype->af_packet_priv == NULL) + if (!ptype->af_packet_priv || !skb->sk) return false; if (ptype->id_match) -- GitLab From f0d6767af2ece14b24064258dffbc816c4258ae5 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Tue, 6 Nov 2012 16:18:41 +0000 Subject: [PATCH 0967/1799] ipv6: send unsolicited neighbour advertisements to all-nodes [ Upstream commit 60713a0ca7fd6651b951cc1b4dbd528d1fc0281b ] As documented in RFC4861 (Neighbor Discovery for IP version 6) 7.2.6., unsolicited neighbour advertisements should be sent to the all-nodes multicast address. Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ndisc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 176b469322ac..843d6ebc525e 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -593,7 +593,7 @@ static void ndisc_send_unsol_na(struct net_device *dev) { struct inet6_dev *idev; struct inet6_ifaddr *ifa; - struct in6_addr mcaddr; + struct in6_addr mcaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT; idev = in6_dev_get(dev); if (!idev) @@ -601,7 +601,6 @@ static void ndisc_send_unsol_na(struct net_device *dev) read_lock_bh(&idev->lock); list_for_each_entry(ifa, &idev->addr_list, if_list) { - addrconf_addr_solict_mult(&ifa->addr, &mcaddr); ndisc_send_na(dev, NULL, &mcaddr, &ifa->addr, /*router=*/ !!idev->cnf.forwarding, /*solicited=*/ false, /*override=*/ true, -- GitLab From c4cbedfda2227df82126c9dd5e7593565bf45d21 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 23 Oct 2012 22:29:38 +0200 Subject: [PATCH 0968/1799] futex: Handle futex_pi OWNER_DIED take over correctly commit 59fa6245192159ab5e1e17b8e31f15afa9cff4bf upstream. Siddhesh analyzed a failure in the take over of pi futexes in case the owner died and provided a workaround. See: http://sourceware.org/bugzilla/show_bug.cgi?id=14076 The detailed problem analysis shows: Futex F is initialized with PTHREAD_PRIO_INHERIT and PTHREAD_MUTEX_ROBUST_NP attributes. T1 lock_futex_pi(F); T2 lock_futex_pi(F); --> T2 blocks on the futex and creates pi_state which is associated to T1. T1 exits --> exit_robust_list() runs --> Futex F userspace value TID field is set to 0 and FUTEX_OWNER_DIED bit is set. T3 lock_futex_pi(F); --> Succeeds due to the check for F's userspace TID field == 0 --> Claims ownership of the futex and sets its own TID into the userspace TID field of futex F --> returns to user space T1 --> exit_pi_state_list() --> Transfers pi_state to waiter T2 and wakes T2 via rt_mutex_unlock(&pi_state->mutex) T2 --> acquires pi_state->mutex and gains real ownership of the pi_state --> Claims ownership of the futex and sets its own TID into the userspace TID field of futex F --> returns to user space T3 --> observes inconsistent state This problem is independent of UP/SMP, preemptible/non preemptible kernels, or process shared vs. private. The only difference is that certain configurations are more likely to expose it. So as Siddhesh correctly analyzed the following check in futex_lock_pi_atomic() is the culprit: if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { We check the userspace value for a TID value of 0 and take over the futex unconditionally if that's true. AFAICT this check is there as it is correct for a different corner case of futexes: the WAITERS bit became stale. Now the proposed change - if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { + if (unlikely(ownerdied || + !(curval & (FUTEX_TID_MASK | FUTEX_WAITERS)))) { solves the problem, but it's not obvious why and it wreckages the "stale WAITERS bit" case. What happens is, that due to the WAITERS bit being set (T2 is blocked on that futex) it enforces T3 to go through lookup_pi_state(), which in the above case returns an existing pi_state and therefor forces T3 to legitimately fight with T2 over the ownership of the pi_state (via pi_state->mutex). Probelm solved! Though that does not work for the "WAITERS bit is stale" problem because if lookup_pi_state() does not find existing pi_state it returns -ERSCH (due to TID == 0) which causes futex_lock_pi() to return -ESRCH to user space because the OWNER_DIED bit is not set. Now there is a different solution to that problem. Do not look at the user space value at all and enforce a lookup of possibly available pi_state. If pi_state can be found, then the new incoming locker T3 blocks on that pi_state and legitimately races with T2 to acquire the rt_mutex and the pi_state and therefor the proper ownership of the user space futex. lookup_pi_state() has the correct order of checks. It first tries to find a pi_state associated with the user space futex and only if that fails it checks for futex TID value = 0. If no pi_state is available nothing can create new state at that point because this happens with the hash bucket lock held. So the above scenario changes to: T1 lock_futex_pi(F); T2 lock_futex_pi(F); --> T2 blocks on the futex and creates pi_state which is associated to T1. T1 exits --> exit_robust_list() runs --> Futex F userspace value TID field is set to 0 and FUTEX_OWNER_DIED bit is set. T3 lock_futex_pi(F); --> Finds pi_state and blocks on pi_state->rt_mutex T1 --> exit_pi_state_list() --> Transfers pi_state to waiter T2 and wakes it via rt_mutex_unlock(&pi_state->mutex) T2 --> acquires pi_state->mutex and gains ownership of the pi_state --> Claims ownership of the futex and sets its own TID into the userspace TID field of futex F --> returns to user space This covers all gazillion points on which T3 might come in between T1's exit_robust_list() clearing the TID field and T2 fixing it up. It also solves the "WAITERS bit stale" problem by forcing the take over. Another benefit of changing the code this way is that it makes it less dependent on untrusted user space values and therefor minimizes the possible wreckage which might be inflicted. As usual after staring for too long at the futex code my brain hurts so much that I really want to ditch that whole optimization of avoiding the syscall for the non contended case for PI futexes and rip out the maze of corner case handling code. Unfortunately we can't as user space relies on that existing behaviour, but at least thinking about it helps me to preserve my mental sanity. Maybe we should nevertheless :) Reported-and-tested-by: Siddhesh Poyarekar Link: http://lkml.kernel.org/r/alpine.LFD.2.02.1210232138540.2756@ionos Acked-by: Darren Hart Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index 3717e7b306e0..20ef219bbe9b 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -716,7 +716,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, struct futex_pi_state **ps, struct task_struct *task, int set_waiters) { - int lock_taken, ret, ownerdied = 0; + int lock_taken, ret, force_take = 0; u32 uval, newval, curval, vpid = task_pid_vnr(task); retry: @@ -755,17 +755,15 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, newval = curval | FUTEX_WAITERS; /* - * There are two cases, where a futex might have no owner (the - * owner TID is 0): OWNER_DIED. We take over the futex in this - * case. We also do an unconditional take over, when the owner - * of the futex died. - * - * This is safe as we are protected by the hash bucket lock ! + * Should we force take the futex? See below. */ - if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { - /* Keep the OWNER_DIED bit */ + if (unlikely(force_take)) { + /* + * Keep the OWNER_DIED and the WAITERS bit and set the + * new TID value. + */ newval = (curval & ~FUTEX_TID_MASK) | vpid; - ownerdied = 0; + force_take = 0; lock_taken = 1; } @@ -775,7 +773,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, goto retry; /* - * We took the lock due to owner died take over. + * We took the lock due to forced take over. */ if (unlikely(lock_taken)) return 1; @@ -790,20 +788,25 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, switch (ret) { case -ESRCH: /* - * No owner found for this futex. Check if the - * OWNER_DIED bit is set to figure out whether - * this is a robust futex or not. + * We failed to find an owner for this + * futex. So we have no pi_state to block + * on. This can happen in two cases: + * + * 1) The owner died + * 2) A stale FUTEX_WAITERS bit + * + * Re-read the futex value. */ if (get_futex_value_locked(&curval, uaddr)) return -EFAULT; /* - * We simply start over in case of a robust - * futex. The code above will take the futex - * and return happy. + * If the owner died or we have a stale + * WAITERS bit the owner TID in the user space + * futex is 0. */ - if (curval & FUTEX_OWNER_DIED) { - ownerdied = 1; + if (!(curval & FUTEX_TID_MASK)) { + force_take = 1; goto retry; } default: -- GitLab From f1e729c67400d3a766befa6f739f971021788878 Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Mon, 5 Nov 2012 14:29:49 -0500 Subject: [PATCH 0969/1799] mmc: sdhci: fix NULL dereference in sdhci_request() tuning commit 14efd957209461bbdf285bf0d67e931955d04a4c upstream. Commit 473b095a72a9 ("mmc: sdhci: fix incorrect command used in tuning") introduced a NULL dereference at resume-time if an SD 3.0 host controller raises the SDHCI_NEEDS_TUNING flag while no card is inserted. Seen on an OLPC XO-4 with sdhci-pxav3, but presumably affects other controllers too. Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sdhci.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 3c403aa8495f..1fe0ca9c10a3 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1294,16 +1294,19 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) */ if ((host->flags & SDHCI_NEEDS_RETUNING) && !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { - /* eMMC uses cmd21 while sd and sdio use cmd19 */ - tuning_opcode = mmc->card->type == MMC_TYPE_MMC ? - MMC_SEND_TUNING_BLOCK_HS200 : - MMC_SEND_TUNING_BLOCK; - spin_unlock_irqrestore(&host->lock, flags); - sdhci_execute_tuning(mmc, tuning_opcode); - spin_lock_irqsave(&host->lock, flags); - - /* Restore original mmc_request structure */ - host->mrq = mrq; + if (mmc->card) { + /* eMMC uses cmd21 but sd and sdio use cmd19 */ + tuning_opcode = + mmc->card->type == MMC_TYPE_MMC ? + MMC_SEND_TUNING_BLOCK_HS200 : + MMC_SEND_TUNING_BLOCK; + spin_unlock_irqrestore(&host->lock, flags); + sdhci_execute_tuning(mmc, tuning_opcode); + spin_lock_irqsave(&host->lock, flags); + + /* Restore original mmc_request structure */ + host->mrq = mrq; + } } if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) -- GitLab From 9feda1930e8fed6bb74d9375d00581f7c9ff2995 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 9 Nov 2012 10:05:57 +0100 Subject: [PATCH 0970/1799] drm/vmwgfx: Fix hibernation device reset commit 95e8f6a21996c4cc2c4574b231c6e858b749dce3 upstream. The device would not reset properly when resuming from hibernation. Signed-off-by: Thomas Hellstrom Reviewed-by: Brian Paul Reviewed-by: Dmitry Torokhov Cc: linux-graphics-maintainer@vmware.com Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 3a4b15acd763..db50604ac216 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1102,6 +1102,11 @@ static void vmw_pm_complete(struct device *kdev) struct drm_device *dev = pci_get_drvdata(pdev); struct vmw_private *dev_priv = vmw_priv(dev); + mutex_lock(&dev_priv->hw_mutex); + vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); + (void) vmw_read(dev_priv, SVGA_REG_ID); + mutex_unlock(&dev_priv->hw_mutex); + /** * Reclaim 3d reference held by fbdev and potentially * start fifo. -- GitLab From 4fa1f62322efae688e5412a6e483777553898cf6 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 9 Nov 2012 10:45:14 +0100 Subject: [PATCH 0971/1799] drm/vmwgfx: Fix a case where the code would BUG when trying to pin GMR memory commit afcc87aa6a233e52df73552dc1dc9ae3881b7cc8 upstream. Signed-off-by: Thomas Hellstrom Reviewed-by: Brian Paul Reviewed-by: Dmitry Torokhov Cc: linux-graphics-maintainer@vmware.com Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c index 3fa884db08ab..27151f74fec8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c @@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin) BUG_ON(!atomic_read(&bo->reserved)); BUG_ON(old_mem_type != TTM_PL_VRAM && - old_mem_type != VMW_PL_FLAG_GMR); + old_mem_type != VMW_PL_GMR); pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED; if (pin) -- GitLab From c436fd2bc1d4255f888dfd68a9f73098cebf30a7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 8 Nov 2012 10:08:04 -0500 Subject: [PATCH 0972/1799] drm/radeon/cayman: add some missing regs to the VM reg checker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 860fe2f05fa2eacac84368e23547ec8cf3cc6652 upstream. These regs were being wronly rejected leading to rendering issues. fixes: https://bugs.freedesktop.org/show_bug.cgi?id=56876 Signed-off-by: Alex Deucher Reviewed-by: Michel Dänzer Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen_cs.c | 3 +++ drivers/gpu/drm/radeon/evergreend.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 977b22d4f478..22c84bcfaebf 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -2671,6 +2671,9 @@ static bool evergreen_vm_reg_valid(u32 reg) /* check config regs */ switch (reg) { case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: + case CP_COHER_CNTL: + case CP_COHER_SIZE: case VGT_VTX_VECT_EJECT_REG: case VGT_CACHE_INVALIDATION: case VGT_GS_VERTEX_REUSE: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index f62ccd3555d8..2eaaea061d6c 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,10 @@ #define CONFIG_MEMSIZE 0x5428 +#define CP_STRMOUT_CNTL 0x84FC + +#define CP_COHER_CNTL 0x85F0 +#define CP_COHER_SIZE 0x85F4 #define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) -- GitLab From 511c41c7b657821172b6b1cde7f1f2ce7a73d43e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 8 Nov 2012 10:13:24 -0500 Subject: [PATCH 0973/1799] drm/radeon/si: add some missing regs to the VM reg checker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f418b88aad0c42b4caf4d79a0cf8d14a5d0a2284 upstream. This register is needed for streamout to work properly. Signed-off-by: Alex Deucher Reviewed-by: Michel Dänzer Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/si.c | 1 + drivers/gpu/drm/radeon/sid.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 2af1ce69e6e7..1197f2187d73 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2593,6 +2593,7 @@ static bool si_vm_reg_valid(u32 reg) /* check config regs */ switch (reg) { case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: case VGT_VTX_VECT_EJECT_REG: case VGT_CACHE_INVALIDATION: case VGT_ESGS_RING_SIZE: diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 53ea2c42dbd6..2c2bc63d6da6 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -413,6 +413,7 @@ # define RDERR_INT_ENABLE (1 << 0) # define GUI_IDLE_INT_ENABLE (1 << 19) +#define CP_STRMOUT_CNTL 0x84FC #define SCRATCH_REG0 0x8500 #define SCRATCH_REG1 0x8504 #define SCRATCH_REG2 0x8508 -- GitLab From c97430309917c78fd47def652ec1573f6e53c735 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 12 May 2012 20:22:00 +0200 Subject: [PATCH 0974/1799] drm/i915: fixup infoframe support for sdvo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 81014b9d0b55fb0b48f26cd2a943359750d532db upstream. At least the worst offenders: - SDVO specifies that the encoder should compute the ecc. Testing also shows that we must not send the ecc field, so copy the dip_infoframe struct to a temporay place and avoid the ecc field. This way the avi infoframe is exactly 17 bytes long, which agrees with what the spec mandates as a minimal storage capacity (with the ecc field it would be 18 bytes). - Only 17 when sending the avi infoframe. The SDVO spec explicitly says that sending more data than what the device announces results in undefined behaviour. - Add __attribute__((packed)) to the avi and spd infoframes, for otherwise they're wrongly aligned. Noticed because the avi infoframe ended up being 18 bytes large instead of 17. We haven't noticed this yet because we don't use the uint16_t fields yet (which are the only ones that would be wrongly aligned). This regression has been introduce by 3c17fe4b8f40a112a85758a9ab2aebf772bdd647 is the first bad commit commit 3c17fe4b8f40a112a85758a9ab2aebf772bdd647 Author: David Härdeman Date: Fri Sep 24 21:44:32 2010 +0200 i915: enable AVI infoframe for intel_hdmi.c [v4] Patch tested on my g33 with a sdvo hdmi adaptor. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=25732 Tested-by: Peter Ross (G35 SDVO-HDMI) Reviewed-by: Eugeni Dodonov Signed-Off-by: Daniel Vetter Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_drv.h | 4 ++-- drivers/gpu/drm/i915/intel_sdvo.c | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2cae72d17499..cd623e899f58 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -247,12 +247,12 @@ struct dip_infoframe { uint16_t bottom_bar_start; uint16_t left_bar_end; uint16_t right_bar_start; - } avi; + } __attribute__ ((packed)) avi; struct { uint8_t vn[8]; uint8_t pd[16]; uint8_t sdi; - } spd; + } __attribute__ ((packed)) spd; uint8_t payload[27]; } __attribute__ ((packed)) body; } __attribute__((packed)); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index eea58c6cb05b..d0c1d1e6b41c 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -877,17 +877,24 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) }; uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; uint8_t set_buf_index[2] = { 1, 0 }; - uint64_t *data = (uint64_t *)&avi_if; + uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; + uint64_t *data = (uint64_t *)sdvo_data; unsigned i; intel_dip_infoframe_csum(&avi_if); + /* sdvo spec says that the ecc is handled by the hw, and it looks like + * we must not send the ecc field, either. */ + memcpy(sdvo_data, &avi_if, 3); + sdvo_data[3] = avi_if.checksum; + memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); + if (!intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_HBUF_INDEX, set_buf_index, 2)) return false; - for (i = 0; i < sizeof(avi_if); i += 8) { + for (i = 0; i < sizeof(sdvo_data); i += 8) { if (!intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_HBUF_DATA, data, 8)) -- GitLab From 6903f0a9f2370fced066ad21c757b364a962bfea Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 21 Oct 2012 12:52:39 +0200 Subject: [PATCH 0975/1799] drm/i915: clear the entire sdvo infoframe buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b6e0e543f75729f207b9c72b0162ae61170635b2 upstream. Like in the case of native hdmi, which is fixed already in commit adf00b26d18e1b3570451296e03bcb20e4798cdd Author: Paulo Zanoni Date: Tue Sep 25 13:23:34 2012 -0300 drm/i915: make sure we write all the DIP data bytes we need to clear the entire sdvo buffer to avoid upsetting the display. Since infoframe buffer writing is now a bit more elaborate, extract it into it's own function. This will be useful if we ever get around to properly update the ELD for sdvo. Also #define proper names for the two buffer indexes with fixed usage. v2: Cite the right commit above, spotted by Paulo Zanoni. v3: I'm too stupid to paste the right commit. v4: Ben Hutchings noticed that I've failed to handle an underflow in my loop logic, breaking it for i >= length + 8. Since I've just lost C programmer license, use his solution. Also, make the frustrated 0-base buffer size a notch more clear. Reported-and-tested-by: Jürg Billeter Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=25732 Cc: Paulo Zanoni Cc: Ben Hutchings Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_sdvo.c | 62 +++++++++++++++++--------- drivers/gpu/drm/i915/intel_sdvo_regs.h | 2 + 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index d0c1d1e6b41c..b96e8c835c83 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -868,6 +868,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo) } #endif +static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, + unsigned if_index, uint8_t tx_rate, + uint8_t *data, unsigned length) +{ + uint8_t set_buf_index[2] = { if_index, 0 }; + uint8_t hbuf_size, tmp[8]; + int i; + + if (!intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_INDEX, + set_buf_index, 2)) + return false; + + if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO, + &hbuf_size, 1)) + return false; + + /* Buffer size is 0 based, hooray! */ + hbuf_size++; + + DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n", + if_index, length, hbuf_size); + + for (i = 0; i < hbuf_size; i += 8) { + memset(tmp, 0, 8); + if (i < length) + memcpy(tmp, data + i, min_t(unsigned, 8, length - i)); + + if (!intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_DATA, + tmp, 8)) + return false; + } + + return intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_TXRATE, + &tx_rate, 1); +} + static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) { struct dip_infoframe avi_if = { @@ -875,11 +914,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) .ver = DIP_VERSION_AVI, .len = DIP_LEN_AVI, }; - uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; - uint8_t set_buf_index[2] = { 1, 0 }; uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; - uint64_t *data = (uint64_t *)sdvo_data; - unsigned i; intel_dip_infoframe_csum(&avi_if); @@ -889,22 +924,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) sdvo_data[3] = avi_if.checksum; memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); - if (!intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_INDEX, - set_buf_index, 2)) - return false; - - for (i = 0; i < sizeof(sdvo_data); i += 8) { - if (!intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_DATA, - data, 8)) - return false; - data++; - } - - return intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_TXRATE, - &tx_rate, 1); + return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF, + SDVO_HBUF_TX_VSYNC, + sdvo_data, sizeof(sdvo_data)); } static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 9d030142ee43..770bdd6ecd9f 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg { #define SDVO_CMD_SET_AUDIO_STAT 0x91 #define SDVO_CMD_GET_AUDIO_STAT 0x92 #define SDVO_CMD_SET_HBUF_INDEX 0x93 + #define SDVO_HBUF_INDEX_ELD 0 + #define SDVO_HBUF_INDEX_AVI_IF 1 #define SDVO_CMD_GET_HBUF_INDEX 0x94 #define SDVO_CMD_GET_HBUF_INFO 0x95 #define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 -- GitLab From 2834bc7007eb6e8e375f8edbf7f6f52b2a14db13 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 8 Nov 2012 18:28:59 +0100 Subject: [PATCH 0976/1799] USB: mos7840: remove unused variable Fix warning about unused variable introduced by commit e681b66f2e19fa ("USB: mos7840: remove invalid disconnect handling") upstream. A subsequent fix which removed the disconnect function got rid of the warning but that one was only backported to v3.6. Reported-by: Jiri Slaby Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 0179d348c260..c8542356898b 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2581,7 +2581,6 @@ static int mos7840_startup(struct usb_serial *serial) static void mos7840_disconnect(struct usb_serial *serial) { int i; - unsigned long flags; struct moschip_port *mos7840_port; dbg("%s", " disconnect :entering.........."); -- GitLab From 13ec0431e7523a5a2d45dd6513b12b5f6b4ddec9 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Fri, 2 Nov 2012 11:38:44 +1100 Subject: [PATCH 0977/1799] xfs: fix reading of wrapped log data commit 6ce377afd1755eae5c93410ca9a1121dfead7b87 upstream. Commit 4439647 ("xfs: reset buffer pointers before freeing them") in 3.0-rc1 introduced a regression when recovering log buffers that wrapped around the end of log. The second part of the log buffer at the start of the physical log was being read into the header buffer rather than the data buffer, and hence recovery was seeing garbage in the data buffer when it got to the region of the log buffer that was incorrectly read. Reported-by: Torsten Kaiser Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_log_recover.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 8ecad5bad66c..0abb1623a7cb 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -3514,7 +3514,7 @@ xlog_do_recovery_pass( * - order is important. */ error = xlog_bread_offset(log, 0, - bblks - split_bblks, hbp, + bblks - split_bblks, dbp, offset + BBTOB(split_bblks)); if (error) goto bread_err2; -- GitLab From 32896690903c576809f21724115612a82a102a52 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Nov 2012 14:36:18 +0100 Subject: [PATCH 0978/1799] ALSA: Fix card refcount unbalance commit 8bb4d9ce08b0a92ca174e41d92c180328f86173f upstream. There are uncovered cases whether the card refcount introduced by the commit a0830dbd isn't properly increased or decreased: - OSS PCM and mixer success paths - When lookup function gets NULL This patch fixes these places. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=50251 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/oss/mixer_oss.c | 1 + sound/core/oss/pcm_oss.c | 1 + sound/core/pcm_native.c | 6 ++++-- sound/core/sound.c | 2 +- sound/core/sound_oss.c | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 05395aaeaa32..c353768854e6 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -76,6 +76,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) snd_card_unref(card); return -EFAULT; } + snd_card_unref(card); return 0; } diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index f337b66a020b..4c1cc51772e6 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2454,6 +2454,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) mutex_unlock(&pcm->open_mutex); if (err < 0) goto __error; + snd_card_unref(pcm->card); return err; __error: diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 0844444eb100..d535b341aa82 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2111,7 +2111,8 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file) pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_PLAYBACK); err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); - snd_card_unref(pcm->card); + if (pcm) + snd_card_unref(pcm->card); return err; } @@ -2124,7 +2125,8 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_CAPTURE); err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); - snd_card_unref(pcm->card); + if (pcm) + snd_card_unref(pcm->card); return err; } diff --git a/sound/core/sound.c b/sound/core/sound.c index 7c0640eeee52..3700d96fb3fb 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -115,7 +115,7 @@ void *snd_lookup_minor_data(unsigned int minor, int type) mreg = snd_minors[minor]; if (mreg && mreg->type == type) { private_data = mreg->private_data; - if (mreg->card_ptr) + if (private_data && mreg->card_ptr) atomic_inc(&mreg->card_ptr->refcount); } else private_data = NULL; diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 7442c7ac2469..ec86009141d0 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -54,7 +54,7 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) mreg = snd_oss_minors[minor]; if (mreg && mreg->type == type) { private_data = mreg->private_data; - if (mreg->card_ptr) + if (private_data && mreg->card_ptr) atomic_inc(&mreg->card_ptr->refcount); } else private_data = NULL; -- GitLab From 2ce3809e3420701b66bb4a6bebc69ddaf850394f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 13 Nov 2012 11:22:48 +0100 Subject: [PATCH 0979/1799] ALSA: usb-audio: Fix mutex deadlock at disconnection commit 10e44239f67d0b6fb74006e61a7e883b8075247a upstream. The recent change for USB-audio disconnection race fixes introduced a mutex deadlock again. There is a circular dependency between chip->shutdown_rwsem and pcm->open_mutex, depicted like below, when a device is opened during the disconnection operation: A. snd_usb_audio_disconnect() -> card.c::register_mutex -> chip->shutdown_rwsem (write) -> snd_card_disconnect() -> pcm.c::register_mutex -> pcm->open_mutex B. snd_pcm_open() -> pcm->open_mutex -> snd_usb_pcm_open() -> chip->shutdown_rwsem (read) Since the chip->shutdown_rwsem protection in the case A is required only for turning on the chip->shutdown flag and it doesn't have to be taken for the whole operation, we can reduce its window in snd_usb_audio_disconnect(). Reported-by: Jiri Slaby Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/card.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 147a5c42b95d..388460d27311 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -555,9 +555,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, return; card = chip->card; - mutex_lock(®ister_mutex); down_write(&chip->shutdown_rwsem); chip->shutdown = 1; + up_write(&chip->shutdown_rwsem); + + mutex_lock(®ister_mutex); chip->num_interfaces--; if (chip->num_interfaces <= 0) { snd_card_disconnect(card); @@ -574,11 +576,9 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, snd_usb_mixer_disconnect(p); } usb_chip[chip->index] = NULL; - up_write(&chip->shutdown_rwsem); mutex_unlock(®ister_mutex); snd_card_free_when_closed(card); } else { - up_write(&chip->shutdown_rwsem); mutex_unlock(®ister_mutex); } } -- GitLab From 16286083befef95045f84ecc10f19b1a14fc7283 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 17 Nov 2012 13:16:56 -0800 Subject: [PATCH 0980/1799] Linux 3.4.19 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 95de44764c4d..e264929291ec 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 18 +SUBLEVEL = 19 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 3f874ecc49208f3635e29c3a08ade01778ad85e4 Mon Sep 17 00:00:00 2001 From: Takamori Yamaguchi Date: Thu, 8 Nov 2012 15:53:39 -0800 Subject: [PATCH 0981/1799] mm: bugfix: set current->reclaim_state to NULL while returning from kswapd() commit b0a8cc58e6b9aaae3045752059e5e6260c0b94bc upstream. In kswapd(), set current->reclaim_state to NULL before returning, as current->reclaim_state holds reference to variable on kswapd()'s stack. In rare cases, while returning from kswapd() during memory offlining, __free_slab() and freepages() can access the dangling pointer of current->reclaim_state. Signed-off-by: Takamori Yamaguchi Signed-off-by: Aaditya Kumar Acked-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/vmscan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/vmscan.c b/mm/vmscan.c index e989ee22f100..e6ca5051c021 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -3128,6 +3128,8 @@ static int kswapd(void *p) &balanced_classzone_idx); } } + + current->reclaim_state = NULL; return 0; } -- GitLab From 0244d2ed647d788233ad72d32986bc0ee9a71d5b Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 12 Nov 2012 22:09:46 +1100 Subject: [PATCH 0982/1799] xfs: drop buffer io reference when a bad bio is built commit d69043c42d8c6414fa28ad18d99973aa6c1c2e24 upstream. Error handling in xfs_buf_ioapply_map() does not handle IO reference counts correctly. We increment the b_io_remaining count before building the bio, but then fail to decrement it in the failure case. This leads to the buffer never running IO completion and releasing the reference that the IO holds, so at unmount we can leak the buffer. This leak is captured by this assert failure during unmount: XFS: Assertion failed: atomic_read(&pag->pag_ref) == 0, file: fs/xfs/xfs_mount.c, line: 273 This is not a new bug - the b_io_remaining accounting has had this problem for a long, long time - it's just very hard to get a zero length bio being built by this code... Further, the buffer IO error can be overwritten on a multi-segment buffer by subsequent bio completions for partial sections of the buffer. Hence we should only set the buffer error status if the buffer is not already carrying an error status. This ensures that a partial IO error on a multi-segment buffer will not be lost. This part of the problem is a regression, however. Signed-off-by: Dave Chinner Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_buf.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 6819b5163e33..bb76128b5f47 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1165,9 +1165,14 @@ xfs_buf_bio_end_io( { xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private; - xfs_buf_ioerror(bp, -error); + /* + * don't overwrite existing errors - otherwise we can lose errors on + * buffers that require multiple bios to complete. + */ + if (!bp->b_error) + xfs_buf_ioerror(bp, -error); - if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) + if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp)); _xfs_buf_ioend(bp, 1); @@ -1243,6 +1248,11 @@ _xfs_buf_ioapply( if (size) goto next_chunk; } else { + /* + * This is guaranteed not to be the last io reference count + * because the caller (xfs_buf_iorequest) holds a count itself. + */ + atomic_dec(&bp->b_io_remaining); xfs_buf_ioerror(bp, EIO); bio_put(bio); } -- GitLab From 1cbc74e7edf24ac527c502e3e936bc4350ec4622 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 5 Nov 2012 10:27:52 +0200 Subject: [PATCH 0983/1799] mac80211: sync acccess to tx_filtered/ps_tx_buf queues commit 987c285c2ae2e4e32aca3a9b3252d28171c75711 upstream. These are accessed without a lock when ending STA PSM. If the sta_cleanup timer accesses these lists at the same time, we might crash. This may fix some mysterious crashes we had during ieee80211_sta_ps_deliver_wakeup. Signed-off-by: Arik Nemtsov Signed-off-by: Ido Yariv Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/sta_info.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d93d39b84344..6e36aafbf5e0 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -959,6 +959,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) struct ieee80211_local *local = sdata->local; struct sk_buff_head pending; int filtered = 0, buffered = 0, ac; + unsigned long flags; clear_sta_flag(sta, WLAN_STA_SP); @@ -974,12 +975,16 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { int count = skb_queue_len(&pending), tmp; + spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags); skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending); + spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags); tmp = skb_queue_len(&pending); filtered += tmp - count; count = tmp; + spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags); skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending); + spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags); tmp = skb_queue_len(&pending); buffered += tmp - count; } -- GitLab From ab4e547760de676be22d61c5d73230356b383a31 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 8 Nov 2012 14:06:28 +0100 Subject: [PATCH 0984/1799] mac80211: don't send null data packet when not associated commit 20f544eea03db4b498942558b882d463ce575c3e upstream. On resume or firmware recovery, mac80211 sends a null data packet to see if the AP is still around and hasn't disconnected us. However, it always does this even if it wasn't even connected before, leading to a warning in the new channel context code. Fix this by checking that it's associated. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 266d0925ba28..73ef163a0391 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1341,6 +1341,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_STATION) continue; + if (!sdata->u.mgd.associated) + continue; ieee80211_send_nullfunc(local, sdata, 0); } -- GitLab From bb1d6871282e191752d4d8396808ed25ac3500fb Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 10 Nov 2012 03:44:14 +0100 Subject: [PATCH 0985/1799] mac80211: call skb_dequeue/ieee80211_free_txskb instead of __skb_queue_purge commit 1f98ab7fef48a2968f37f422c256c9fbd978c3f0 upstream. Fixes more wifi status skb leaks, leading to hostapd/wpa_supplicant hangs. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/sta_info.c | 6 +++--- net/mac80211/status.c | 9 +++++++++ net/mac80211/tx.c | 9 ++++++--- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index db8fae51714c..498e87bcb3eb 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1297,6 +1297,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); +void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, + struct sk_buff_head *skbs); /* HT */ bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 6e36aafbf5e0..6d25d7796fc6 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -738,8 +738,8 @@ int __must_check __sta_info_destroy(struct sta_info *sta) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); - __skb_queue_purge(&sta->ps_tx_buf[ac]); - __skb_queue_purge(&sta->tx_filtered[ac]); + ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]); + ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]); } #ifdef CONFIG_MAC80211_MESH @@ -774,7 +774,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); if (!tid_tx) continue; - __skb_queue_purge(&tid_tx->pending); + ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); kfree(tid_tx); } diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 5f8f89e89d6b..47b117f3f567 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -660,3 +660,12 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) dev_kfree_skb_any(skb); } EXPORT_SYMBOL(ieee80211_free_txskb); + +void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, + struct sk_buff_head *skbs) +{ + struct sk_buff *skb; + + while ((skb = __skb_dequeue(skbs))) + ieee80211_free_txskb(hw, skb); +} diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e76facc69e95..eace7664c805 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1357,7 +1357,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) if (tx->skb) dev_kfree_skb(tx->skb); else - __skb_queue_purge(&tx->skbs); + ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs); return -1; } else if (unlikely(res == TX_QUEUED)) { I802_DEBUG_INC(tx->local->tx_handlers_queued); @@ -2126,10 +2126,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, */ void ieee80211_clear_tx_pending(struct ieee80211_local *local) { + struct sk_buff *skb; int i; - for (i = 0; i < local->hw.queues; i++) - skb_queue_purge(&local->pending[i]); + for (i = 0; i < local->hw.queues; i++) { + while ((skb = skb_dequeue(&local->pending[i])) != NULL) + ieee80211_free_txskb(&local->hw, skb); + } } /* -- GitLab From a6a19e36b35fcb17d6c2bf9a49014e9461dfcef2 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 8 Nov 2012 15:53:37 -0800 Subject: [PATCH 0986/1799] fanotify: fix missing break commit 848561d368751a1c0f679b9f045a02944506a801 upstream. Anders Blomdell noted in 2010 that Fanotify lost events and provided a test case. Eric Paris confirmed it was a bug and posted a fix to the list https://groups.google.com/forum/?fromgroups=#!topic/linux.kernel/RrJfTfyW2BE but never applied it. Repeated attempts over time to actually get him to apply it have never had a reply from anyone who has raised it So apply it anyway Signed-off-by: Alan Cox Reported-by: Anders Blomdell Cc: Eric Paris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/notify/fanotify/fanotify.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index f35794b97e8e..a50636025364 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -21,6 +21,7 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new) if ((old->path.mnt == new->path.mnt) && (old->path.dentry == new->path.dentry)) return true; + break; case (FSNOTIFY_EVENT_NONE): return true; default: -- GitLab From 0de578d014506a662b239708f4a0ded7e083292c Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 25 Oct 2012 10:49:25 +1030 Subject: [PATCH 0987/1799] module: fix out-by-one error in kallsyms commit 59ef28b1f14899b10d6b2682c7057ca00a9a3f47 upstream. Masaki found and patched a kallsyms issue: the last symbol in a module's symtab wasn't transferred. This is because we manually copy the zero'th entry (which is always empty) then copy the rest in a loop starting at 1, though from src[0]. His fix was minimal, I prefer to rewrite the loops in more standard form. There are two loops: one to get the size, and one to copy. Make these identical: always count entry 0 and any defined symbol in an allocated non-init section. This bug exists since the following commit was introduced. module: reduce symbol table for loaded modules (v2) commit: 4a4962263f07d14660849ec134ee42b63e95ea9a LKML: http://lkml.org/lkml/2012/10/24/27 Reported-by: Masaki Kimura Signed-off-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- kernel/module.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index 61ea75eaeec6..85972171ecd3 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2273,12 +2273,17 @@ static void layout_symtab(struct module *mod, struct load_info *info) src = (void *)info->hdr + symsect->sh_offset; nsrc = symsect->sh_size / sizeof(*src); + /* strtab always starts with a nul, so offset 0 is the empty string. */ + strtab_size = 1; + /* Compute total space required for the core symbols' strtab. */ - for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src) - if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) { - strtab_size += strlen(&info->strtab[src->st_name]) + 1; + for (ndst = i = 0; i < nsrc; i++) { + if (i == 0 || + is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { + strtab_size += strlen(&info->strtab[src[i].st_name])+1; ndst++; } + } /* Append room for core symbols at end of core part. */ info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); @@ -2312,15 +2317,15 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) mod->core_symtab = dst = mod->module_core + info->symoffs; mod->core_strtab = s = mod->module_core + info->stroffs; src = mod->symtab; - *dst = *src; *s++ = 0; - for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { - if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) - continue; - - dst[ndst] = *src; - dst[ndst++].st_name = s - mod->core_strtab; - s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1; + for (ndst = i = 0; i < mod->num_symtab; i++) { + if (i == 0 || + is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { + dst[ndst] = src[i]; + dst[ndst++].st_name = s - mod->core_strtab; + s += strlcpy(s, &mod->strtab[src[i].st_name], + KSYM_NAME_LEN) + 1; + } } mod->core_num_syms = ndst; } -- GitLab From bb60c07c75a9087303779324be4e5de771a7687b Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sat, 3 Nov 2012 09:37:28 -0400 Subject: [PATCH 0988/1799] cifs: fix potential buffer overrun in cifs.idmap handling code commit 36960e440ccf94349c09fb944930d3bfe4bc473f upstream. The userspace cifs.idmap program generally works with the wbclient libs to generate binary SIDs in userspace. That program defines the struct that holds these values as having a max of 15 subauthorities. The kernel idmapping code however limits that value to 5. When the kernel copies those values around though, it doesn't sanity check the num_subauths value handed back from userspace or from the server. It's possible therefore for userspace to hand us back a bogus num_subauths value (or one that's valid, but greater than 5) that could cause the kernel to walk off the end of the cifs_sid->sub_auths array. Fix this by defining a new routine for copying sids and using that in all of the places that copy it. If we end up with a sid that's longer than expected then this approach will just lop off the "extra" subauths, but that's basically what the code does today already. Better approaches might be to fix this code to reject SIDs with >5 subauths, or fix it to handle the subauths array dynamically. At the same time, change the kernel to check the length of the data returned by userspace. If it's shorter than struct cifs_sid, reject it and return -EIO. If that happens we'll end up with fields that are basically uninitialized. Long term, it might make sense to redefine cifs_sid using a flexarray at the end, to allow for variable-length subauth lists, and teach the code to handle the case where the subauths array being passed in from userspace is shorter than 5 elements. Note too, that I don't consider this a security issue since you'd need a compromised cifs.idmap program. If you have that, you can do all sorts of nefarious stuff. Still, this is probably reasonable for stable. Reviewed-by: Shirish Pargaonkar Signed-off-by: Jeff Layton Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifsacl.c | 49 +++++++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 3cc1b251ca08..6ccf176427f0 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -224,6 +224,13 @@ sid_to_str(struct cifs_sid *sidptr, char *sidstr) } } +static void +cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src) +{ + memcpy(dst, src, sizeof(*dst)); + dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS); +} + static void id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, struct cifs_sid_id **psidid, char *typestr) @@ -248,7 +255,7 @@ id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, } } - memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid)); + cifs_copy_sid(&(*psidid)->sid, sidptr); (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); (*psidid)->refcount = 0; @@ -354,7 +361,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) * any fields of the node after a reference is put . */ if (test_bit(SID_ID_MAPPED, &psidid->state)) { - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); + cifs_copy_sid(ssid, &psidid->sid); psidid->time = jiffies; /* update ts for accessing */ goto id_sid_out; } @@ -370,14 +377,14 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) if (IS_ERR(sidkey)) { rc = -EINVAL; cFYI(1, "%s: Can't map and id to a SID", __func__); + } else if (sidkey->datalen < sizeof(struct cifs_sid)) { + rc = -EIO; + cFYI(1, "%s: Downcall contained malformed key " + "(datalen=%hu)", __func__, sidkey->datalen); } else { lsid = (struct cifs_sid *)sidkey->payload.data; - memcpy(&psidid->sid, lsid, - sidkey->datalen < sizeof(struct cifs_sid) ? - sidkey->datalen : sizeof(struct cifs_sid)); - memcpy(ssid, &psidid->sid, - sidkey->datalen < sizeof(struct cifs_sid) ? - sidkey->datalen : sizeof(struct cifs_sid)); + cifs_copy_sid(&psidid->sid, lsid); + cifs_copy_sid(ssid, &psidid->sid); set_bit(SID_ID_MAPPED, &psidid->state); key_put(sidkey); kfree(psidid->sidstr); @@ -396,7 +403,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) return rc; } if (test_bit(SID_ID_MAPPED, &psidid->state)) - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); + cifs_copy_sid(ssid, &psidid->sid); else rc = -EINVAL; } @@ -675,8 +682,6 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) static void copy_sec_desc(const struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, __u32 sidsoffset) { - int i; - struct cifs_sid *owner_sid_ptr, *group_sid_ptr; struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr; @@ -692,26 +697,14 @@ static void copy_sec_desc(const struct cifs_ntsd *pntsd, owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + le32_to_cpu(pntsd->osidoffset)); nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset); - - nowner_sid_ptr->revision = owner_sid_ptr->revision; - nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth; - for (i = 0; i < 6; i++) - nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i]; - for (i = 0; i < 5; i++) - nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i]; + cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr); /* copy group sid */ group_sid_ptr = (struct cifs_sid *)((char *)pntsd + le32_to_cpu(pntsd->gsidoffset)); ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset + sizeof(struct cifs_sid)); - - ngroup_sid_ptr->revision = group_sid_ptr->revision; - ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth; - for (i = 0; i < 6; i++) - ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i]; - for (i = 0; i < 5; i++) - ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i]; + cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr); return; } @@ -1120,8 +1113,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, kfree(nowner_sid_ptr); return rc; } - memcpy(owner_sid_ptr, nowner_sid_ptr, - sizeof(struct cifs_sid)); + cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr); kfree(nowner_sid_ptr); *aclflag = CIFS_ACL_OWNER; } @@ -1139,8 +1131,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, kfree(ngroup_sid_ptr); return rc; } - memcpy(group_sid_ptr, ngroup_sid_ptr, - sizeof(struct cifs_sid)); + cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr); kfree(ngroup_sid_ptr); *aclflag = CIFS_ACL_GROUP; } -- GitLab From 30966dbf8217223b017514ca684c633e5c31a13a Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Sun, 21 Oct 2012 20:42:28 +0300 Subject: [PATCH 0989/1799] crypto: cryptd - disable softirqs in cryptd_queue_worker to prevent data corruption commit 9efade1b3e981f5064f9db9ca971b4dc7557ae42 upstream. cryptd_queue_worker attempts to prevent simultaneous accesses to crypto workqueue by cryptd_enqueue_request using preempt_disable/preempt_enable. However cryptd_enqueue_request might be called from softirq context, so add local_bh_disable/local_bh_enable to prevent data corruption and panics. Bug report at http://marc.info/?l=linux-crypto-vger&m=134858649616319&w=2 v2: - Disable software interrupts instead of hardware interrupts Reported-by: Gurucharan Shetty Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- crypto/cryptd.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crypto/cryptd.c b/crypto/cryptd.c index 671d4d6d14df..7bdd61b867c8 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct work_struct *work) struct crypto_async_request *req, *backlog; cpu_queue = container_of(work, struct cryptd_cpu_queue, work); - /* Only handle one request at a time to avoid hogging crypto - * workqueue. preempt_disable/enable is used to prevent - * being preempted by cryptd_enqueue_request() */ + /* + * Only handle one request at a time to avoid hogging crypto workqueue. + * preempt_disable/enable is used to prevent being preempted by + * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent + * cryptd_enqueue_request() being accessed from software interrupts. + */ + local_bh_disable(); preempt_disable(); backlog = crypto_get_backlog(&cpu_queue->queue); req = crypto_dequeue_request(&cpu_queue->queue); preempt_enable(); + local_bh_enable(); if (!req) return; -- GitLab From 2a1d20c8d31dd4d2b83838e4de3e15ebbb442806 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 1 Nov 2012 13:42:37 +0100 Subject: [PATCH 0990/1799] ALSA: hda: Cirrus: Fix coefficient index for beep configuration commit 5a83b4b5a391f07141b157ac9daa51c409e71ab5 upstream. Signed-off-by: Alexander Stein Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_cirrus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 2bc6c51f58e7..d7ba0f124d56 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -1112,7 +1112,7 @@ static const struct hda_verb cs_coef_init_verbs[] = { | 0x0400 /* Disable Coefficient Auto increment */ )}, /* Beep */ - {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG}, + {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG}, {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */ {} /* terminator */ -- GitLab From 1289a3ebfb5de7d1eb093352e977fd5dbb414946 Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Sun, 4 Nov 2012 13:19:03 +0800 Subject: [PATCH 0991/1799] ALSA: HDA: Fix digital microphone on CS420x commit 16337e028a6dae9fbdd718c0d42161540a668ff3 upstream. Correctly enable the digital microphones with the right bits in the right coeffecient registers on Cirrus CS4206/7 codecs. It also prevents misconfiguring ADC1/2. This fixes the digital mic on the Macbook Pro 10,1/Retina. Based-on-patch-by: Alexander Stein Signed-off-by: Daniel J Blueman Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_cirrus.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index d7ba0f124d56..057f95a2bbb0 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -95,8 +95,8 @@ enum { #define CS420X_VENDOR_NID 0x11 #define CS_DIG_OUT1_PIN_NID 0x10 #define CS_DIG_OUT2_PIN_NID 0x15 -#define CS_DMIC1_PIN_NID 0x12 -#define CS_DMIC2_PIN_NID 0x0e +#define CS_DMIC1_PIN_NID 0x0e +#define CS_DMIC2_PIN_NID 0x12 /* coef indices */ #define IDX_SPDIF_STAT 0x0000 @@ -1084,14 +1084,18 @@ static void init_input(struct hda_codec *codec) cs_automic(codec); coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ + cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); + + coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG); if (is_active_pin(codec, CS_DMIC2_PIN_NID)) - coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */ + coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */ if (is_active_pin(codec, CS_DMIC1_PIN_NID)) - coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off + coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off * No effect if SPDIF_OUT2 is * selected in IDX_SPDIF_CTL. */ - cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); + + cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef); } else { if (spec->mic_detect) cs_automic(codec); -- GitLab From f283494905eb2aab38911af461563c985c1a1115 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 5 Nov 2012 12:32:46 +0100 Subject: [PATCH 0992/1799] ALSA: hda - Force to reset IEC958 status bits for AD codecs commit ae24c3191ba2ab03ec6b4be323e730e00404b4b6 upstream. Several bug reports suggest that the forcibly resetting IEC958 status bits is required for AD codecs to get the SPDIF output working properly after changing streams. Original fix credit to Javeed Shaikh. BugLink: https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/359361 Reported-by: Robin Kreis 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 7143393927da..e23ad3f045fc 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -544,6 +544,7 @@ static int ad198x_build_pcms(struct hda_codec *codec) if (spec->multiout.dig_out_nid) { info++; codec->num_pcms++; + codec->spdif_status_reset = 1; info->name = "AD198x Digital"; info->pcm_type = HDA_PCM_TYPE_SPDIF; info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; -- GitLab From 9562c79dcc0f30e353b52936b0408114c269d350 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 10:32:47 +0100 Subject: [PATCH 0993/1799] ALSA: hda - Fix empty DAC filling in patch_via.c commit 5b3761954dac2d1393beef8210eb8cee81d16b8d upstream. In via_auto_fill_adc_nids(), the parser tries to fill dac_nids[] at the point of the current line-out (i). When no valid path is found for this output, this results in dac = 0, thus it creates a hole in dac_nids[]. This confuses is_empty_dac() and trims the detected DAC in later reference. This patch fixes the bug by appending DAC properly to dac_nids[] in via_auto_fill_adc_nids(). Reported-by: Massimo Del Fedele Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_via.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 3998d09bf241..c63c3be0fd0b 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1868,11 +1868,11 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec) { struct via_spec *spec = codec->spec; const struct auto_pin_cfg *cfg = &spec->autocfg; - int i, dac_num; + int i; hda_nid_t nid; + spec->multiout.num_dacs = 0; spec->multiout.dac_nids = spec->private_dac_nids; - dac_num = 0; for (i = 0; i < cfg->line_outs; i++) { hda_nid_t dac = 0; nid = cfg->line_out_pins[i]; @@ -1883,16 +1883,13 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec) if (!i && parse_output_path(codec, nid, dac, 1, &spec->out_mix_path)) dac = spec->out_mix_path.path[0]; - if (dac) { - spec->private_dac_nids[i] = dac; - dac_num++; - } + if (dac) + spec->private_dac_nids[spec->multiout.num_dacs++] = dac; } if (!spec->out_path[0].depth && spec->out_mix_path.depth) { spec->out_path[0] = spec->out_mix_path; spec->out_mix_path.depth = 0; } - spec->multiout.num_dacs = dac_num; return 0; } -- GitLab From d2d0adce41aacfe4b08dee4fd32daad490c8ed3e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Nov 2012 10:37:48 +0100 Subject: [PATCH 0994/1799] ALSA: hda - Fix invalid connections in VT1802 codec commit ef4da45828603df57e5e21b8aa21a66ce309f79b upstream. VT1802 codec provides the invalid connection lists of NID 0x24 and 0x33 containing the routes to a non-exist widget 0x3e. This confuses the auto-parser. Fix it up in the driver by overriding these connections. Reported-by: Massimo Del Fedele Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_via.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index c63c3be0fd0b..9dafacdb5195 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -3665,6 +3665,18 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec) update_power_state(codec, 0x21, AC_PWRST_D3); } +/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e + * Replace this with mixer NID 0x1c + */ +static void fix_vt1802_connections(struct hda_codec *codec) +{ + static hda_nid_t conn_24[] = { 0x14, 0x1c }; + static hda_nid_t conn_33[] = { 0x1c }; + + snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24); + snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33); +} + /* patch for vt2002P */ static int patch_vt2002P(struct hda_codec *codec) { @@ -3679,6 +3691,8 @@ static int patch_vt2002P(struct hda_codec *codec) spec->aa_mix_nid = 0x21; override_mic_boost(codec, 0x2b, 0, 3, 40); override_mic_boost(codec, 0x29, 0, 3, 40); + if (spec->codec_type == VT1802) + fix_vt1802_connections(codec); add_secret_dac_path(codec); /* automatic parse from the BIOS config */ -- GitLab From 2302f5e1a612ada83bb179203736008bac383fc7 Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Thu, 8 Nov 2012 10:25:37 +0100 Subject: [PATCH 0995/1799] ALSA: hda - Add new codec ALC668 and ALC900 (default name ALC1150) commit 19a62823eae453619604636082085812c14ee391 upstream. Signed-off-by: Kailang Yang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6ecf1d4fa8a3..5430a6de7426 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7047,6 +7047,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { .patch = patch_alc662 }, { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, + { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 }, { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, @@ -7064,6 +7065,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 }, { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 }, { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 }, + { .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 }, {} /* terminator */ }; -- GitLab From c2628a3b472500b59def16491041e6b13bd5309e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Nov 2012 10:07:36 +0100 Subject: [PATCH 0996/1799] ALSA: hda - Add a missing quirk entry for iMac 9,1 commit 05193639ca977cc889668718adb38db6d585045b upstream. This is another variant of iMac 9,1 with a different codec SSID. Reported-and-tested-by: Everaldo Canuto 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 5430a6de7426..257fe87c4c0f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5458,6 +5458,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO), + SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF), -- GitLab From b6d806539cdf76b1d0ad2411dff4cae227de4942 Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Fri, 2 Nov 2012 17:05:44 -0400 Subject: [PATCH 0997/1799] ASoC: wm8978: pll incorrectly configured when codec is master commit 55c6f4cb6ef49afbb86222c6a3ff85329199c729 upstream. When MCLK is supplied externally and BCLK and LRC are configured as outputs (codec is master), the PLL values are only calculated correctly on the first transmission. On subsequent transmissions, at differenct sample rates, the wrong PLL values are used. Test for f_opclk instead of f_pllout to determine if the PLL values are needed. Signed-off-by: Eric Millbrandt Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8978.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 72d5fdcd3cc2..6c37c7c2327e 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -783,7 +783,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, wm8978->mclk_idx = -1; f_sel = wm8978->f_mclk; } else { - if (!wm8978->f_pllout) { + if (!wm8978->f_opclk) { /* We only enter here, if OPCLK is not used */ int ret = wm8978_configure_pll(codec); if (ret < 0) -- GitLab From 647a9dbec6ab9bf9789b2dcfb589cf4dbb13e379 Mon Sep 17 00:00:00 2001 From: Misael Lopez Cruz Date: Thu, 8 Nov 2012 12:03:12 -0600 Subject: [PATCH 0998/1799] ASoC: dapm: Use card_list during DAPM shutdown commit 445632ad6dda42f4d3f9df2569a852ca0d4ea608 upstream. DAPM shutdown incorrectly uses "list" field of codec struct while iterating over probed components (codec_dev_list). "list" field refers to codecs registered in the system, "card_list" field is used for probed components. Signed-off-by: Misael Lopez Cruz Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/soc-dapm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c41efe01a819..9ae82a4eb71e 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3253,7 +3253,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card) { struct snd_soc_codec *codec; - list_for_each_entry(codec, &card->codec_dev_list, list) { + list_for_each_entry(codec, &card->codec_dev_list, card_list) { soc_dapm_shutdown_codec(&codec->dapm); if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) snd_soc_dapm_set_bias_level(&codec->dapm, -- GitLab From 151de639411e60bbf9d8fbb5e7b78bb2c5eb0972 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 9 Oct 2012 16:20:15 +0300 Subject: [PATCH 0999/1799] UBIFS: fix mounting problems after power cuts commit a28ad42a4a0c6f302f488f26488b8b37c9b30024 upstream. This is a bugfix for a problem with the following symptoms: 1. A power cut happens 2. After reboot, we try to mount UBIFS 3. Mount fails with "No space left on device" error message UBIFS complains like this: UBIFS error (pid 28225): grab_empty_leb: could not find an empty LEB The root cause of this problem is that when we mount, not all LEBs are categorized. Only those which were read are. However, the 'ubifs_find_free_leb_for_idx()' function assumes that all LEBs were categorized and 'c->freeable_cnt' is valid, which is a false assumption. This patch fixes the problem by teaching 'ubifs_find_free_leb_for_idx()' to always fall back to LPT scanning if no freeable LEBs were found. This problem was reported by few people in the past, but Brent Taylor was able to reproduce it and send me a flash image which cannot be mounted, which made it easy to hunt the bug. Kudos to Brent. Reported-by: Brent Taylor Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- fs/ubifs/find.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index 2559d174e004..5dc48cacb5a0 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c @@ -681,8 +681,16 @@ int ubifs_find_free_leb_for_idx(struct ubifs_info *c) if (!lprops) { lprops = ubifs_fast_find_freeable(c); if (!lprops) { - ubifs_assert(c->freeable_cnt == 0); - if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) { + /* + * The first condition means the following: go scan the + * LPT if there are uncategorized lprops, which means + * there may be freeable LEBs there (UBIFS does not + * store the information about freeable LEBs in the + * master node). + */ + if (c->in_a_category_cnt != c->main_lebs || + c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) { + ubifs_assert(c->freeable_cnt == 0); lprops = scan_for_leb_for_idx(c); if (IS_ERR(lprops)) { err = PTR_ERR(lprops); -- GitLab From 07126218d445ea1fea9952c6f801e5d05117e223 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 10 Oct 2012 10:55:28 +0300 Subject: [PATCH 1000/1799] UBIFS: introduce categorized lprops counter commit 98a1eebda3cb2a84ecf1f219bb3a95769033d1bf upstream. This commit is a preparation for a subsequent bugfix. We introduce a counter for categorized lprops. Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- fs/ubifs/lprops.c | 6 ++++++ fs/ubifs/ubifs.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c index f8a181e647cc..ea9d49164ffa 100644 --- a/fs/ubifs/lprops.c +++ b/fs/ubifs/lprops.c @@ -300,8 +300,11 @@ void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops, default: ubifs_assert(0); } + lprops->flags &= ~LPROPS_CAT_MASK; lprops->flags |= cat; + c->in_a_category_cnt += 1; + ubifs_assert(c->in_a_category_cnt <= c->main_lebs); } /** @@ -334,6 +337,9 @@ static void ubifs_remove_from_cat(struct ubifs_info *c, default: ubifs_assert(0); } + + c->in_a_category_cnt -= 1; + ubifs_assert(c->in_a_category_cnt >= 0); } /** diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 93d59aceaaef..4971cb23b6c8 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1184,6 +1184,8 @@ struct ubifs_debug_info; * @freeable_list: list of freeable non-index LEBs (free + dirty == @leb_size) * @frdi_idx_list: list of freeable index LEBs (free + dirty == @leb_size) * @freeable_cnt: number of freeable LEBs in @freeable_list + * @in_a_category_cnt: count of lprops which are in a certain category, which + * basically meants that they were loaded from the flash * * @ltab_lnum: LEB number of LPT's own lprops table * @ltab_offs: offset of LPT's own lprops table @@ -1413,6 +1415,7 @@ struct ubifs_info { struct list_head freeable_list; struct list_head frdi_idx_list; int freeable_cnt; + int in_a_category_cnt; int ltab_lnum; int ltab_offs; -- GitLab From 87dd2c484ae11e2e0a34996d96bfbfaf20f57b45 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 7 Nov 2012 18:21:51 -0800 Subject: [PATCH 1001/1799] Revert "Staging: Android alarm: IOCTL command encoding fix" commit d38e0e3fed4f58bcddef4dc93a591dfe2f651cb0 upstream. Commit 6bd4a5d96c08dc2380f8053b1bd4f879f55cd3c9 changed the ANDROID_ALARM_GET_TIME ioctls from IOW to IOR. While technically correct, the _IOC_DIR bits are ignored by alarm_ioctl, so the commit breaks a userspace ABI used by all existing Android devices for a purely cosmetic reason. Revert it. Cc: Dae S. Kim Signed-off-by: Colin Cross Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/android_alarm.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h index 66b6e3decc64..6eecbde2ef6f 100644 --- a/drivers/staging/android/android_alarm.h +++ b/drivers/staging/android/android_alarm.h @@ -110,12 +110,10 @@ enum android_alarm_return_flags { #define ANDROID_ALARM_WAIT _IO('a', 1) #define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size) -#define ALARM_IOR(c, type, size) _IOR('a', (c) | ((type) << 4), size) - /* Set alarm */ #define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) #define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec) -#define ANDROID_ALARM_GET_TIME(type) ALARM_IOR(4, type, struct timespec) +#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec) #define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) #define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0))) #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4) -- GitLab From 3e31ee155e0963e42bb02d33a2a9e44d5b91a45b Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 22 Oct 2012 15:49:02 +0200 Subject: [PATCH 1002/1799] s390/gup: add missing TASK_SIZE check to get_user_pages_fast() commit d55c4c613fc4d4ad2ba0fc6fa2b57176d420f7e4 upstream. When walking page tables we need to make sure that everything is within bounds of the ASCE limit of the task's address space. Otherwise we might calculate e.g. a pud pointer which is not within a pud and dereference it. So check against TASK_SIZE (which is the ASCE limit) before walking page tables. Reviewed-by: Gerald Schaefer Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/mm/gup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index 65cb06e2af4e..4ccf9f54355e 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c @@ -183,7 +183,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, addr = start; len = (unsigned long) nr_pages << PAGE_SHIFT; end = start + len; - if (end < start) + if ((end < start) || (end > TASK_SIZE)) goto slow_irqon; /* -- GitLab From 47ccee3020fc998e27dbdd04cc575bfb6b927886 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 8 Nov 2012 11:56:42 -0600 Subject: [PATCH 1003/1799] USB: option: add Novatel E362 and Dell Wireless 5800 USB IDs commit fcb21645f1bd86d2be29baf48aa1b298de52ccc7 upstream. The Dell 5800 appears to be a simple rebrand of the Novatel E362. Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- 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 17ec21ee7d07..e26bd428a466 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -157,6 +157,7 @@ static void option_instat_callback(struct urb *urb); #define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0x8001 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 +#define NOVATELWIRELESS_PRODUCT_E362 0x9010 #define NOVATELWIRELESS_PRODUCT_G1 0xA001 #define NOVATELWIRELESS_PRODUCT_G1_M 0xA002 #define NOVATELWIRELESS_PRODUCT_G2 0xA010 @@ -192,6 +193,9 @@ static void option_instat_callback(struct urb *urb); #define DELL_PRODUCT_5730_MINICARD_TELUS 0x8181 #define DELL_PRODUCT_5730_MINICARD_VZW 0x8182 +#define DELL_PRODUCT_5800_MINICARD_VZW 0x8195 /* Novatel E362 */ +#define DELL_PRODUCT_5800_V2_MINICARD_VZW 0x8196 /* Novatel E362 */ + #define KYOCERA_VENDOR_ID 0x0c88 #define KYOCERA_PRODUCT_KPC650 0x17da #define KYOCERA_PRODUCT_KPC680 0x180a @@ -705,6 +709,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, /* Novatel Ovation MC551 a.k.a. Verizon USB551L */ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, @@ -727,6 +732,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ + { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, -- GitLab From 3bf0d107e137043aa3c6a872ee542b3f0e85a30a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 8 Nov 2012 11:56:53 -0600 Subject: [PATCH 1004/1799] USB: option: add Alcatel X220/X500D USB IDs commit c0bc3098871dd9b964f6b45ec1e4d70d87811744 upstream. Signed-off-by: Dan Williams 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 e26bd428a466..43aa36bcd396 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -286,6 +286,7 @@ static void option_instat_callback(struct urb *urb); /* ALCATEL PRODUCTS */ #define ALCATEL_VENDOR_ID 0x1bbb #define ALCATEL_PRODUCT_X060S_X200 0x0000 +#define ALCATEL_PRODUCT_X220_X500D 0x0017 #define PIRELLI_VENDOR_ID 0x1266 #define PIRELLI_PRODUCT_C100_1 0x1002 @@ -1163,6 +1164,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), -- GitLab From cfb62e2f3c407c91a4c4707006ad47183baf4ff1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 14 Nov 2012 09:10:39 -0500 Subject: [PATCH 1005/1799] drm/radeon: fix logic error in atombios_encoders.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b9196395c905edec512dfd6690428084228c16ec upstream. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=50431 Reported-by: David Binderman Signed-off-by: Alex Deucher Reviewed-by: Michel Dänzer Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_encoders.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 2d07fbf2c27c..f6176bc90f12 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1421,7 +1421,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730)) + if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { -- GitLab From 9098e8785685bd245027447b5628fa872babd3b8 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 13 Nov 2012 18:31:55 +0000 Subject: [PATCH 1006/1799] ttm: Clear the ttm page allocated from high memory zone correctly commit ac207ed2471150e06af0afc76e4becc701fa2733 upstream. The TTM page can be allocated from high memory. In such case it is wrong to use the page_address(page) as the virtual address for the high memory page. bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=50241 Signed-off-by: Zhao Yakui Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/ttm/ttm_page_alloc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index ebc6fac96e36..578207ecc43f 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -749,7 +749,10 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags, /* clear the pages coming from the pool if requested */ if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) { list_for_each_entry(p, &plist, lru) { - clear_page(page_address(p)); + if (PageHighMem(p)) + clear_highpage(p); + else + clear_page(page_address(p)); } } -- GitLab From e5c4ee6a081ec04e8ba54b00a4385391ab77e2f8 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Fri, 16 Nov 2012 14:14:49 -0800 Subject: [PATCH 1007/1799] memcg: oom: fix totalpages calculation for memory.swappiness==0 commit 9a5a8f19b43430752067ecaee62fc59e11e88fa6 upstream. oom_badness() takes a totalpages argument which says how many pages are available and it uses it as a base for the score calculation. The value is calculated by mem_cgroup_get_limit which considers both limit and total_swap_pages (resp. memsw portion of it). This is usually correct but since fe35004fbf9e ("mm: avoid swapping out with swappiness==0") we do not swap when swappiness is 0 which means that we cannot really use up all the totalpages pages. This in turn confuses oom score calculation if the memcg limit is much smaller than the available swap because the used memory (capped by the limit) is negligible comparing to totalpages so the resulting score is too small if adj!=0 (typically task with CAP_SYS_ADMIN or non zero oom_score_adj). A wrong process might be selected as result. The problem can be worked around by checking mem_cgroup_swappiness==0 and not considering swap at all in such a case. Signed-off-by: Michal Hocko Acked-by: David Rientjes Acked-by: Johannes Weiner Acked-by: KOSAKI Motohiro Acked-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- Documentation/cgroups/memory.txt | 4 ++++ mm/memcontrol.c | 21 +++++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 9b1067afb224..68c5411d70a2 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -466,6 +466,10 @@ Note: 5.3 swappiness Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only. +Please note that unlike the global swappiness, memcg knob set to 0 +really prevents from any swapping even if there is a swap storage +available. This might lead to memcg OOM killer if there are no file +pages to reclaim. Following cgroups' swappiness can't be changed. - root cgroup (uses /proc/sys/vm/swappiness). diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 7685d4a0b3ce..81c275b3afed 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1489,17 +1489,26 @@ static int mem_cgroup_count_children(struct mem_cgroup *memcg) u64 mem_cgroup_get_limit(struct mem_cgroup *memcg) { u64 limit; - u64 memsw; limit = res_counter_read_u64(&memcg->res, RES_LIMIT); - limit += total_swap_pages << PAGE_SHIFT; - memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT); /* - * If memsw is finite and limits the amount of swap space available - * to this memcg, return that limit. + * Do not consider swap space if we cannot swap due to swappiness */ - return min(limit, memsw); + if (mem_cgroup_swappiness(memcg)) { + u64 memsw; + + limit += total_swap_pages << PAGE_SHIFT; + memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT); + + /* + * If memsw is finite and limits the amount of swap space + * available to this memcg, return that limit. + */ + limit = min(limit, memsw); + } + + return limit; } static unsigned long mem_cgroup_reclaim(struct mem_cgroup *memcg, -- GitLab From dd361b498741bd9b23a2f2238cf1c6af6cd49b67 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 12 Nov 2012 10:51:34 +0100 Subject: [PATCH 1008/1799] wireless: allow 40 MHz on world roaming channels 12/13 commit 43c771a1963ab461a2f194e3c97fded1d5fe262f upstream. When in world roaming mode, allow 40 MHz to be used on channels 12 and 13 so that an AP that is, e.g., using HT40+ on channel 9 (in the UK) can be used. Reported-by: Eddie Chapman Tested-by: Eddie Chapman Acked-by: Luis R. Rodriguez Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/wireless/reg.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index b01449f01bbd..4dc83474db2e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -134,9 +134,8 @@ static const struct ieee80211_regdomain world_regdom = { .reg_rules = { /* IEEE 802.11b/g, channels 1..11 */ REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), - /* IEEE 802.11b/g, channels 12..13. No HT40 - * channel fits here. */ - REG_RULE(2467-10, 2472+10, 20, 6, 20, + /* IEEE 802.11b/g, channels 12..13. */ + REG_RULE(2467-10, 2472+10, 40, 6, 20, NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), /* IEEE 802.11 channel 14 - Only JP enables -- GitLab From 999d6a5194c9707b081869f40306ac5e1727edf4 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Sat, 17 Nov 2012 22:27:04 +0100 Subject: [PATCH 1009/1799] m68k: fix sigset_t accessor functions commit 34fa78b59c52d1db3513db4c1a999db26b2e9ac2 upstream. The sigaddset/sigdelset/sigismember functions that are implemented with bitfield insn cannot allow the sigset argument to be placed in a data register since the sigset is wider than 32 bits. Remove the "d" constraint from the asm statements. The effect of the bug is that sending RT signals does not work, the signal number is truncated modulo 32. Signed-off-by: Andreas Schwab Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- arch/m68k/include/asm/signal.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h index 60e88660169c..93fe83e7ffb5 100644 --- a/arch/m68k/include/asm/signal.h +++ b/arch/m68k/include/asm/signal.h @@ -156,7 +156,7 @@ typedef struct sigaltstack { static inline void sigaddset(sigset_t *set, int _sig) { asm ("bfset %0{%1,#1}" - : "+od" (*set) + : "+o" (*set) : "id" ((_sig - 1) ^ 31) : "cc"); } @@ -164,7 +164,7 @@ static inline void sigaddset(sigset_t *set, int _sig) static inline void sigdelset(sigset_t *set, int _sig) { asm ("bfclr %0{%1,#1}" - : "+od" (*set) + : "+o" (*set) : "id" ((_sig - 1) ^ 31) : "cc"); } @@ -180,7 +180,7 @@ static inline int __gen_sigismember(sigset_t *set, int _sig) int ret; asm ("bfextu %1{%2,#1},%0" : "=d" (ret) - : "od" (*set), "id" ((_sig-1) ^ 31) + : "o" (*set), "id" ((_sig-1) ^ 31) : "cc"); return ret; } -- GitLab From 0fa89335e494872552e8e1d4e594c18559922e5c Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Sun, 11 Nov 2012 11:20:01 +0000 Subject: [PATCH 1010/1799] ipv4: avoid undefined behavior in do_ip_setsockopt() [ Upstream commit 0c9f79be295c99ac7e4b569ca493d75fdcc19e4e ] (1< Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ip_sockglue.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 2fd0fba77124..59ef40abf500 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -456,19 +456,28 @@ static int do_ip_setsockopt(struct sock *sk, int level, struct inet_sock *inet = inet_sk(sk); int val = 0, err; - if (((1<= sizeof(int)) { if (get_user(val, (int __user *) optval)) return -EFAULT; -- GitLab From 798f49e632f38abcb51dea6014b078798c1cc6ee Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Sat, 10 Nov 2012 19:52:34 +0000 Subject: [PATCH 1011/1799] ipv6: setsockopt(IPIPPROTO_IPV6, IPV6_MINHOPCOUNT) forgot to set return value [ Upstream commit d4596bad2a713fcd0def492b1960e6d899d5baa8 ] Cc: Stephen Hemminger Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ipv6_sockglue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 63dd1f89ed7d..34c1109d3468 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -828,6 +828,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, if (val < 0 || val > 255) goto e_inval; np->min_hopcount = val; + retv = 0; break; case IPV6_DONTFRAG: np->dontfrag = valbool; -- GitLab From 4e95708469b3b36b123c9ebfe4fed2b9de601e7a Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 14 Nov 2012 02:51:04 +0000 Subject: [PATCH 1012/1799] net: correct check in dev_addr_del() [ Upstream commit a652208e0b52c190e57f2a075ffb5e897fe31c3b ] Check (ha->addr == dev->dev_addr) is always true because dev_addr_init() sets this. Correct the check to behave properly on addr removal. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev_addr_lists.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 626698f0db8b..76f6d0b02f28 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -308,7 +308,8 @@ int dev_addr_del(struct net_device *dev, unsigned char *addr, */ ha = list_first_entry(&dev->dev_addrs.list, struct netdev_hw_addr, list); - if (ha->addr == dev->dev_addr && ha->refcount == 1) + if (!memcmp(ha->addr, addr, dev->addr_len) && + ha->type == addr_type && ha->refcount == 1) return -ENOENT; err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len, -- GitLab From f86c309e326f800e8fb028df35051aac5a26ef8d Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Fri, 16 Nov 2012 09:04:15 +0000 Subject: [PATCH 1013/1799] net-rps: Fix brokeness causing OOO packets [ Upstream commit baefa31db2f2b13a05d1b81bdf2d20d487f58b0a ] In commit c445477d74ab3779 which adds aRFS to the kernel, the CPU selected for RFS is not set correctly when CPU is changing. This is causing OOO packets and probably other issues. Signed-off-by: Tom Herbert Acked-by: Eric Dumazet Acked-by: Ben Hutchings Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 24a21f36a477..eb858dc6ab86 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2763,8 +2763,10 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, if (unlikely(tcpu != next_cpu) && (tcpu == RPS_NO_CPU || !cpu_online(tcpu) || ((int)(per_cpu(softnet_data, tcpu).input_queue_head - - rflow->last_qtail)) >= 0)) + rflow->last_qtail)) >= 0)) { + tcpu = next_cpu; rflow = set_rps_cpu(dev, skb, rflow, next_cpu); + } if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) { *rflowp = rflow; -- GitLab From ec5924204b7fa09a679c4456ac8e2176a2950ce6 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Fri, 16 Nov 2012 14:15:04 -0800 Subject: [PATCH 1014/1799] tmpfs: change final i_blocks BUG to WARNING commit 0f3c42f522dc1ad7e27affc0a4aa8c790bce0a66 upstream. Under a particular load on one machine, I have hit shmem_evict_inode()'s BUG_ON(inode->i_blocks), enough times to narrow it down to a particular race between swapout and eviction. It comes from the "if (freed > 0)" asymmetry in shmem_recalc_inode(), and the lack of coherent locking between mapping's nrpages and shmem's swapped count. There's a window in shmem_writepage(), between lowering nrpages in shmem_delete_from_page_cache() and then raising swapped count, when the freed count appears to be +1 when it should be 0, and then the asymmetry stops it from being corrected with -1 before hitting the BUG. One answer is coherent locking: using tree_lock throughout, without info->lock; reasonable, but the raw_spin_lock in percpu_counter_add() on used_blocks makes that messier than expected. Another answer may be a further effort to eliminate the weird shmem_recalc_inode() altogether, but previous attempts at that failed. So far undecided, but for now change the BUG_ON to WARN_ON: in usual circumstances it remains a useful consistency check. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/shmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/shmem.c b/mm/shmem.c index 40383cddc916..a859b06d573f 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -595,7 +595,7 @@ static void shmem_evict_inode(struct inode *inode) kfree(xattr->name); kfree(xattr); } - BUG_ON(inode->i_blocks); + WARN_ON(inode->i_blocks); shmem_free_inode(inode->i_sb); end_writeback(inode); } -- GitLab From 56cb8f7e4324410e9acb0b307efd2f846c06cf69 Mon Sep 17 00:00:00 2001 From: Michal Schmidt Date: Sun, 9 Sep 2012 13:55:26 +0000 Subject: [PATCH 1015/1799] r8169: use unlimited DMA burst for TX commit aee77e4accbeb2c86b1d294cd84fec4a12dde3bd upstream. The r8169 driver currently limits the DMA burst for TX to 1024 bytes. I have a box where this prevents the interface from using the gigabit line to its full potential. This patch solves the problem by setting TX_DMA_BURST to unlimited. The box has an ASRock B75M motherboard with on-board RTL8168evl/8111evl (XID 0c900880). TSO is enabled. I used netperf (TCP_STREAM test) to measure the dependency of TX throughput on MTU. I did it for three different values of TX_DMA_BURST ('5'=512, '6'=1024, '7'=unlimited). This chart shows the results: http://michich.fedorapeople.org/r8169/r8169-effects-of-TX_DMA_BURST.png Interesting points: - With the current DMA burst limit (1024): - at the default MTU=1500 I get only 842 Mbit/s. - when going from small MTU, the performance rises monotonically with increasing MTU only up to a peak at MTU=1076 (908 MBit/s). Then there's a sudden drop to 762 MBit/s from which the throughput rises monotonically again with further MTU increases. - With a smaller DMA burst limit (512): - there's a similar peak at MTU=1076 and another one at MTU=564. - With unlimited DMA burst: - at the default MTU=1500 I get nice 940 Mbit/s. - the throughput rises monotonically with increasing MTU with no strange peaks. Notice that the peaks occur at MTU sizes that are multiples of the DMA burst limit plus 52. Why 52? Because: 20 (IP header) + 20 (TCP header) + 12 (TCP options) = 52 The Realtek-provided r8168 driver (v8.032.00) uses unlimited TX DMA burst too, except for CFG_METHOD_1 where the TX DMA burst is set to 512 bytes. CFG_METHOD_1 appears to be the oldest MAC version of "RTL8168B/8111B", i.e. RTL_GIGA_MAC_VER_11 in r8169. Not sure if this MAC version really needs the smaller burst limit, or if any other versions have similar requirements. Signed-off-by: Michal Schmidt Acked-by: Francois Romieu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/realtek/r8169.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 482dcd3a7ad0..3fd8cdeeccdf 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -73,7 +73,7 @@ static const int multicast_filter_limit = 32; #define MAX_READ_REQUEST_SHIFT 12 -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ +#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */ #define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ -- GitLab From f5a93eaffacc75908abcb9b94e2367a824d5953f Mon Sep 17 00:00:00 2001 From: Mojiong Qiu Date: Tue, 6 Nov 2012 16:08:15 +0800 Subject: [PATCH 1016/1799] xen/events: fix RCU warning, or Call idle notifier after irq_enter() commit 772aebcefeff310f80e32b874988af0076cb799d upstream. exit_idle() should be called after irq_enter(), otherwise it throws: [ INFO: suspicious RCU usage. ] 3.6.5 #1 Not tainted ------------------------------- include/linux/rcupdate.h:725 rcu_read_lock() used illegally while idle! other info that might help us debug this: RCU used illegally from idle CPU! rcu_scheduler_active = 1, debug_locks = 1 RCU used illegally from extended quiescent state! 1 lock held by swapper/0/0: #0: (rcu_read_lock){......}, at: [] __atomic_notifier_call_chain+0x0/0x140 stack backtrace: Pid: 0, comm: swapper/0 Not tainted 3.6.5 #1 Call Trace: [] lockdep_rcu_suspicious+0xe2/0x130 [] __atomic_notifier_call_chain+0x12c/0x140 [] ? atomic_notifier_chain_unregister+0x90/0x90 [] ? trace_hardirqs_off+0xd/0x10 [] atomic_notifier_call_chain+0x16/0x20 [] exit_idle+0x43/0x50 [] xen_evtchn_do_upcall+0x25/0x50 [] xen_do_hypervisor_callback+0x1e/0x30 [] ? hypercall_page+0x3aa/0x1000 [] ? hypercall_page+0x3aa/0x1000 [] ? xen_safe_halt+0x10/0x20 [] ? default_idle+0xba/0x570 [] ? cpu_idle+0xdf/0x140 [] ? rest_init+0x135/0x144 [] ? csum_partial_copy_generic+0x16c/0x16c [] ? start_kernel+0x3db/0x3e8 [] ? repair_env_string+0x5a/0x5a [] ? x86_64_start_reservations+0x131/0x135 [] ? xen_start_kernel+0x465/0x46 Git commit 98ad1cc14a5c4fd658f9d72c6ba5c86dfd3ce0d5 Author: Frederic Weisbecker Date: Fri Oct 7 18:22:09 2011 +0200 x86: Call idle notifier after irq_enter() did this, but it missed the Xen code. Signed-off-by: Mojiong Qiu Signed-off-by: Konrad Rzeszutek Wilk 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 6908e4ce2a0d..26c47a4c4269 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -1365,8 +1365,8 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); - exit_idle(); irq_enter(); + exit_idle(); __xen_evtchn_do_upcall(); -- GitLab From cfc2c996141d487273c63af8954a3f3f03b16229 Mon Sep 17 00:00:00 2001 From: Cyril Brulebois Date: Wed, 31 Oct 2012 14:00:46 +0000 Subject: [PATCH 1017/1799] r8169: Fix WoL on RTL8168d/8111d. commit b00e69dee4ccbb3a19989e3d4f1385bc2e3406cd upstream. This regression was spotted between Debian squeeze and Debian wheezy kernels (respectively based on 2.6.32 and 3.2). More info about Wake-on-LAN issues with Realtek's 816x chipsets can be found in the following thread: http://marc.info/?t=132079219400004 Probable regression from d4ed95d796e5126bba51466dc07e287cebc8bd19; more chipsets are likely affected. Tested on top of a 3.2.23 kernel. Reported-by: Florent Fourcot Tested-by: Florent Fourcot Hinted-by: Francois Romieu Signed-off-by: Cyril Brulebois Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/realtek/r8169.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 3fd8cdeeccdf..74a516c72130 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -3488,6 +3488,8 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) void __iomem *ioaddr = tp->mmio_addr; switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_25: + case RTL_GIGA_MAC_VER_26: case RTL_GIGA_MAC_VER_29: case RTL_GIGA_MAC_VER_30: case RTL_GIGA_MAC_VER_32: -- GitLab From 1b10e0be50067689f53e566d5e1cfad6170e89c3 Mon Sep 17 00:00:00 2001 From: Nathan Walp Date: Thu, 1 Nov 2012 12:08:47 +0000 Subject: [PATCH 1018/1799] r8169: allow multicast packets on sub-8168f chipset. commit 0481776b7a70f09acf7d9d97c288c3a8403fbfe4 upstream. RTL_GIGA_MAC_VER_35 includes no multicast hardware filter. Signed-off-by: Nathan Walp Suggested-by: Hayes Wang Acked-by: Francois Romieu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/realtek/r8169.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 74a516c72130..0dc70c21767e 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -4131,6 +4131,9 @@ static void rtl_set_rx_mode(struct net_device *dev) mc_filter[1] = swab32(data); } + if (tp->mac_version == RTL_GIGA_MAC_VER_35) + mc_filter[1] = mc_filter[0] = 0xffffffff; + RTL_W32(MAR0 + 4, mc_filter[1]); RTL_W32(MAR0 + 0, mc_filter[0]); -- GitLab From c581c7c77d5685829bf620dc6e194e2aa2afae00 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Fri, 31 Aug 2012 09:55:54 +0000 Subject: [PATCH 1019/1799] netfilter: Validate the sequence number of dataless ACK packets as well commit 4a70bbfaef0361d27272629d1a250a937edcafe4 upstream. We spare nothing by not validating the sequence number of dataless ACK packets and enabling it makes harder off-path attacks. See: "Reflection scan: an Off-Path Attack on TCP" by Jan Wrobel, http://arxiv.org/abs/1201.2074 Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_conntrack_proto_tcp.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 0d07a1dcf605..5644c8468d0e 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -627,15 +627,9 @@ static bool tcp_in_window(const struct nf_conn *ct, ack = sack = receiver->td_end; } - if (seq == end - && (!tcph->rst - || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT))) + if (tcph->rst && seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT) /* - * Packets contains no data: we assume it is valid - * and check the ack value only. - * However RST segments are always validated by their - * SEQ number, except when seq == 0 (reset sent answering - * SYN. + * RST sent answering SYN. */ seq = end = sender->td_end; -- GitLab From b3e991ea9222c3ec71d74b37d105cea115055c4d Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Fri, 31 Aug 2012 09:55:53 +0000 Subject: [PATCH 1020/1799] netfilter: Mark SYN/ACK packets as invalid from original direction commit 64f509ce71b08d037998e93dd51180c19b2f464c upstream. Clients should not send such packets. By accepting them, we open up a hole by wich ephemeral ports can be discovered in an off-path attack. See: "Reflection scan: an Off-Path Attack on TCP" by Jan Wrobel, http://arxiv.org/abs/1201.2074 Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_conntrack_proto_tcp.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 5644c8468d0e..e0221238e749 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -158,21 +158,18 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { * sCL -> sSS */ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ -/*synack*/ { sIV, sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR }, +/*synack*/ { sIV, sIV, sSR, sIV, sIV, sIV, sIV, sIV, sIV, sSR }, /* * sNO -> sIV Too late and no reason to do anything * sSS -> sIV Client can't send SYN and then SYN/ACK * sS2 -> sSR SYN/ACK sent to SYN2 in simultaneous open - * sSR -> sIG - * sES -> sIG Error: SYNs in window outside the SYN_SENT state - * are errors. Receiver will reply with RST - * and close the connection. - * Or we are not in sync and hold a dead connection. - * sFW -> sIG - * sCW -> sIG - * sLA -> sIG - * sTW -> sIG - * sCL -> sIG + * sSR -> sSR Late retransmitted SYN/ACK in simultaneous open + * sES -> sIV Invalid SYN/ACK packets sent by the client + * sFW -> sIV + * sCW -> sIV + * sLA -> sIV + * sTW -> sIV + * sCL -> sIV */ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ /*fin*/ { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV }, -- GitLab From a39bdce2f2a9aebda1b9438c4b2e91c0dd507a34 Mon Sep 17 00:00:00 2001 From: Ulrich Weber Date: Thu, 25 Oct 2012 05:34:45 +0000 Subject: [PATCH 1021/1799] netfilter: nf_nat: don't check for port change on ICMP tuples commit 38fe36a248ec3228f8e6507955d7ceb0432d2000 upstream. ICMP tuples have id in src and type/code in dst. So comparing src.u.all with dst.u.all will always fail here and ip_xfrm_me_harder() is called for every ICMP packet, even if there was no NAT. Signed-off-by: Ulrich Weber Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/ipv4/netfilter/nf_nat_standalone.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 3828a4229822..da4098f08784 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -194,7 +194,8 @@ nf_nat_out(unsigned int hooknum, if ((ct->tuplehash[dir].tuple.src.u3.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) || - (ct->tuplehash[dir].tuple.src.u.all != + (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && + ct->tuplehash[dir].tuple.src.u.all != ct->tuplehash[!dir].tuple.dst.u.all) ) return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP; @@ -230,7 +231,8 @@ nf_nat_local_fn(unsigned int hooknum, ret = NF_DROP; } #ifdef CONFIG_XFRM - else if (ct->tuplehash[dir].tuple.dst.u.all != + else if (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && + ct->tuplehash[dir].tuple.dst.u.all != ct->tuplehash[!dir].tuple.src.u.all) if (ip_xfrm_me_harder(skb)) ret = NF_DROP; -- GitLab From 9dbd3418ff461025e904e65326aeeb5389f65799 Mon Sep 17 00:00:00 2001 From: Jan Safrata Date: Tue, 22 May 2012 14:04:50 +0200 Subject: [PATCH 1022/1799] usb: use usb_serial_put in usb_serial_probe errors commit 0658a3366db7e27fa32c12e886230bb58c414c92 upstream. The use of kfree(serial) in error cases of usb_serial_probe was invalid - usb_serial structure allocated in create_serial() gets reference of usb_device that needs to be put, so we need to use usb_serial_put() instead of simple kfree(). Signed-off-by: Jan Safrata Acked-by: Johan Hovold Cc: Richard Retanubun Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index bcf261778d07..c627ba21b1e8 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -768,7 +768,7 @@ int usb_serial_probe(struct usb_interface *interface, if (retval) { dbg("sub driver rejected device"); - kfree(serial); + usb_serial_put(serial); module_put(type->driver.owner); return retval; } @@ -840,7 +840,7 @@ int usb_serial_probe(struct usb_interface *interface, */ if (num_bulk_in == 0 || num_bulk_out == 0) { dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); - kfree(serial); + usb_serial_put(serial); module_put(type->driver.owner); return -ENODEV; } @@ -854,7 +854,7 @@ int usb_serial_probe(struct usb_interface *interface, if (num_ports == 0) { dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n"); - kfree(serial); + usb_serial_put(serial); module_put(type->driver.owner); return -EIO; } -- GitLab From c8a1ae7c0030e936470a4701a46f775a2bc7012b Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Mon, 11 Jun 2012 15:42:32 -0700 Subject: [PATCH 1023/1799] eCryptfs: Copy up POSIX ACL and read-only flags from lower mount commit 069ddcda37b2cf5bb4b6031a944c0e9359213262 upstream. When the eCryptfs mount options do not include '-o acl', but the lower filesystem's mount options do include 'acl', the MS_POSIXACL flag is not flipped on in the eCryptfs super block flags. This flag is what the VFS checks in do_last() when deciding if the current umask should be applied to a newly created inode's mode or not. When a default POSIX ACL mask is set on a directory, the current umask is incorrectly applied to new inodes created in the directory. This patch ignores the MS_POSIXACL flag passed into ecryptfs_mount() and sets the flag on the eCryptfs super block depending on the flag's presence on the lower super block. Additionally, it is incorrect to allow a writeable eCryptfs mount on top of a read-only lower mount. This missing check did not allow writes to the read-only lower mount because permissions checks are still performed on the lower filesystem's objects but it is best to simply not allow a rw mount on top of ro mount. However, a ro eCryptfs mount on top of a rw mount is valid and still allowed. https://launchpad.net/bugs/1009207 Signed-off-by: Tyler Hicks Reported-by: Stefan Beller Cc: John Johansen Cc: Herton Ronaldo Krzesinski Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 0f04d2eb9a6a..c2a9c39300c4 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -506,7 +506,6 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags goto out; } - s->s_flags = flags; rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY); if (rc) goto out1; @@ -542,6 +541,15 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags } ecryptfs_set_superblock_lower(s, path.dentry->d_sb); + + /** + * Set the POSIX ACL flag based on whether they're enabled in the lower + * mount. Force a read-only eCryptfs mount if the lower mount is ro. + * Allow a ro eCryptfs mount even when the lower mount is rw. + */ + s->s_flags = flags & ~MS_POSIXACL; + s->s_flags |= path.dentry->d_sb->s_flags & (MS_RDONLY | MS_POSIXACL); + s->s_maxbytes = path.dentry->d_sb->s_maxbytes; s->s_blocksize = path.dentry->d_sb->s_blocksize; s->s_magic = ECRYPTFS_SUPER_MAGIC; -- GitLab From 122fd46fccafa6d839118815141179f1a90cfb48 Mon Sep 17 00:00:00 2001 From: Tim Sally Date: Thu, 12 Jul 2012 19:10:24 -0400 Subject: [PATCH 1024/1799] eCryptfs: check for eCryptfs cipher support at mount commit 5f5b331d5c21228a6519dcb793fc1629646c51a6 upstream. The issue occurs when eCryptfs is mounted with a cipher supported by the crypto subsystem but not by eCryptfs. The mount succeeds and an error does not occur until a write. This change checks for eCryptfs cipher support at mount time. Resolves Launchpad issue #338914, reported by Tyler Hicks in 03/2009. https://bugs.launchpad.net/ecryptfs/+bug/338914 Signed-off-by: Tim Sally Signed-off-by: Tyler Hicks Cc: Herton Ronaldo Krzesinski Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index c2a9c39300c4..240832e8b289 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -280,6 +280,7 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, char *fnek_src; char *cipher_key_bytes_src; char *fn_cipher_key_bytes_src; + u8 cipher_code; *check_ruid = 0; @@ -421,6 +422,18 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, && !fn_cipher_key_bytes_set) mount_crypt_stat->global_default_fn_cipher_key_bytes = mount_crypt_stat->global_default_cipher_key_size; + + cipher_code = ecryptfs_code_for_cipher_string( + mount_crypt_stat->global_default_cipher_name, + mount_crypt_stat->global_default_cipher_key_size); + if (!cipher_code) { + ecryptfs_printk(KERN_ERR, + "eCryptfs doesn't support cipher: %s", + mount_crypt_stat->global_default_cipher_name); + rc = -EINVAL; + goto out; + } + mutex_lock(&key_tfm_list_mutex); if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name, NULL)) { -- GitLab From 39220c9e67cbfbc1a7ac17a51afd77eb06b62fa9 Mon Sep 17 00:00:00 2001 From: Mirko Lindner Date: Tue, 3 Jul 2012 23:38:46 +0000 Subject: [PATCH 1025/1799] sky2: Fix for interrupt handler commit d663d181b9e92d80c2455e460e932d34e7a2a7ae upstream. Re-enable interrupts if it is not our interrupt Signed-off-by: Mirko Lindner Signed-off-by: David S. Miller Cc: Jonathan Nieder Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/marvell/sky2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 589753fb673b..2b78ddd5d631 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -3079,8 +3079,10 @@ static irqreturn_t sky2_intr(int irq, void *dev_id) /* Reading this mask interrupts as side effect */ status = sky2_read32(hw, B0_Y2_SP_ISRC2); - if (status == 0 || status == ~0) + if (status == 0 || status == ~0) { + sky2_write32(hw, B0_Y2_SP_ICR, 2); return IRQ_NONE; + } prefetch(&hw->st_le[hw->st_idx]); -- GitLab From 37a42f991f36aae9b064bc3f39b760006bd17131 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 7 Nov 2012 10:44:08 +0100 Subject: [PATCH 1026/1799] s390/signal: set correct address space control commit fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2f upstream. If user space is running in primary mode it can switch to secondary or access register mode, this is used e.g. in the clock_gettime code of the vdso. If a signal is delivered to the user space process while it has been running in access register mode the signal handler is executed in access register mode as well which will result in a crash most of the time. Set the address space control bits in the PSW to the default for the execution of the signal handler and make sure that the previous address space control is restored on signal return. Take care that user space can not switch to the kernel address space by modifying the registers in the signal frame. Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/include/asm/compat.h | 2 +- arch/s390/include/asm/ptrace.h | 4 ++-- arch/s390/kernel/compat_signal.c | 14 ++++++++++++-- arch/s390/kernel/signal.c | 14 ++++++++++++-- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 234f1d859cea..2e0a15b4359c 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h @@ -20,7 +20,7 @@ #define PSW32_MASK_CC 0x00003000UL #define PSW32_MASK_PM 0x00000f00UL -#define PSW32_MASK_USER 0x00003F00UL +#define PSW32_MASK_USER 0x0000FF00UL #define PSW32_ADDR_AMODE 0x80000000UL #define PSW32_ADDR_INSN 0x7FFFFFFFUL diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index aeb77f017985..d3750e79fcc2 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -240,7 +240,7 @@ typedef struct #define PSW_MASK_EA 0x00000000UL #define PSW_MASK_BA 0x00000000UL -#define PSW_MASK_USER 0x00003F00UL +#define PSW_MASK_USER 0x0000FF00UL #define PSW_ADDR_AMODE 0x80000000UL #define PSW_ADDR_INSN 0x7FFFFFFFUL @@ -269,7 +269,7 @@ typedef struct #define PSW_MASK_EA 0x0000000100000000UL #define PSW_MASK_BA 0x0000000080000000UL -#define PSW_MASK_USER 0x00003F0180000000UL +#define PSW_MASK_USER 0x0000FF0180000000UL #define PSW_ADDR_AMODE 0x0000000000000000UL #define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 28040fd5e8a2..0bdca3ac9a61 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -313,6 +313,10 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 | (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE); + /* Check for invalid user address space control. */ + if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) + regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN); for (i = 0; i < NUM_GPRS; i++) regs->gprs[i] = (__u64) regs32.gprs[i]; @@ -494,7 +498,10 @@ static int setup_frame32(int sig, struct k_sigaction *ka, /* Set up registers for signal handler */ regs->gprs[15] = (__force __u64) frame; - regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */ + /* Force 31 bit amode and default user address space control. */ + regs->psw.mask = PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__force __u64) ka->sa.sa_handler; regs->gprs[2] = map_signal(sig); @@ -562,7 +569,10 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->gprs[15] = (__force __u64) frame; - regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */ + /* Force 31 bit amode and default user address space control. */ + regs->psw.mask = PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__u64) ka->sa.sa_handler; regs->gprs[2] = map_signal(sig); diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index f7582b27f600..74f58e211ac2 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -148,6 +148,10 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */ regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | (user_sregs.regs.psw.mask & PSW_MASK_USER); + /* Check for invalid user address space control. */ + if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) + regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); /* Check for invalid amode */ if (regs->psw.mask & PSW_MASK_EA) regs->psw.mask |= PSW_MASK_BA; @@ -294,7 +298,10 @@ static int setup_frame(int sig, struct k_sigaction *ka, /* Set up registers for signal handler */ regs->gprs[15] = (unsigned long) frame; - regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */ + /* Force default amode and default user address space control. */ + regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; regs->gprs[2] = map_signal(sig); @@ -367,7 +374,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->gprs[15] = (unsigned long) frame; - regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */ + /* Force default amode and default user address space control. */ + regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; regs->gprs[2] = map_signal(sig); -- GitLab From d1b28a26ed24cec32801bfddb48796f914f48d47 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 22 Oct 2012 12:55:55 +0200 Subject: [PATCH 1027/1799] drm/i915: fix overlay on i830M MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a9193983f4f292a82a00c72971c17ec0ee8c6c15 upstream. The overlay on the i830M has a peculiar failure mode: It works the first time around after boot-up, but consistenly hangs the second time it's used. Chris Wilson has dug out a nice errata: "1.5.12 Clock Gating Disable for Display Register Address Offset: 06200h–06203h "Bit 3 Ovrunit Clock Gating Disable. 0 = Clock gating controlled by unit enabling logic 1 = Disable clock gating function DevALM Errata ALM049: Overlay Clock Gating Must be Disabled: Overlay & L2 Cache clock gating must be disabled in order to prevent device hangs when turning off overlay.SW must turn off Ovrunit clock gating (6200h) and L2 Cache clock gating (C8h)." Now I've nowhere found that 0xc8 register and hence couldn't apply the l2 cache workaround. But I've remembered that part of the magic that the OVERLAY_ON/OFF commands are supposed to do is to rearrange cache allocations so that the overlay scaler has some scratch space. And while pondering how that could explain the hang the 2nd time we enable the overlay, I've remembered that the old ums overlay code did _not_ issue the OVERLAY_OFF cmd. And indeed, disabling the OFF cmd results in the overlay working flawlessly, so I guess we can workaround the lack of the above workaround by simply never disabling the overlay engine once it's enabled. Note that we have the first part of the above w/a already implemented in i830_init_clock_gating - leave that as-is to avoid surprises. v2: Add a comment in the code. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47827 Tested-by: Rhys Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter [bwh: Backported to 3.2: - Adjust context - s/intel_ring_emit(ring, /OUT_RING(/] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_overlay.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 80b331c322fb..5ba5e66fa070 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -427,9 +427,17 @@ static int intel_overlay_off(struct intel_overlay *overlay) OUT_RING(flip_addr); OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); /* turn overlay off */ - OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); - OUT_RING(flip_addr); - OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + if (IS_I830(dev)) { + /* Workaround: Don't disable the overlay fully, since otherwise + * it dies on the next OVERLAY_ON cmd. */ + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + } else { + OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); + OUT_RING(flip_addr); + OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + } ADVANCE_LP_RING(); return intel_overlay_do_wait_request(overlay, request, -- GitLab From 824904ce9efd5665024b03217372ca82170687d2 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Tue, 30 Oct 2012 16:06:35 -0400 Subject: [PATCH 1028/1799] NFS: Wait for session recovery to finish before returning commit 399f11c3d872bd748e1575574de265a6304c7c43 upstream. Currently, we will schedule session recovery and then return to the caller of nfs4_handle_exception. This works for most cases, but causes a hang on the following test case: Client Server ------ ------ Open file over NFS v4.1 Write to file Expire client Try to lock file The server will return NFS4ERR_BADSESSION, prompting the client to schedule recovery. However, the client will continue placing lock attempts and the open recovery never seems to be scheduled. The simplest solution is to wait for session recovery to run before retrying the lock. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 5e801803072b..8955e3642000 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -307,8 +307,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc dprintk("%s ERROR: %d Reset session\n", __func__, errorcode); nfs4_schedule_session_recovery(clp->cl_session); - exception->retry = 1; - break; + goto wait_on_recovery; #endif /* defined(CONFIG_NFS_V4_1) */ case -NFS4ERR_FILE_OPEN: if (exception->timeout > HZ) { -- GitLab From 394cbbc4417c009f2831122e9d64c975c8249123 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 13 Nov 2012 14:55:52 +0100 Subject: [PATCH 1029/1799] reiserfs: Fix lock ordering during remount commit 3bb3e1fc47aca554e7e2cc4deeddc24750987ac2 upstream. When remounting reiserfs dquot_suspend() or dquot_resume() can be called. These functions take dqonoff_mutex which ranks above write lock so we have to drop it before calling into quota code. Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/super.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 8b7616ef06d8..f4f83bfc5719 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -1292,7 +1292,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) kfree(qf_names[i]); #endif err = -EINVAL; - goto out_err; + goto out_unlock; } #ifdef CONFIG_QUOTA handle_quota_files(s, qf_names, &qfmt); @@ -1336,7 +1336,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) if (blocks) { err = reiserfs_resize(s, blocks); if (err != 0) - goto out_err; + goto out_unlock; } if (*mount_flags & MS_RDONLY) { @@ -1346,9 +1346,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) /* it is read-only already */ goto out_ok; + /* + * Drop write lock. Quota will retake it when needed and lock + * ordering requires calling dquot_suspend() without it. + */ + reiserfs_write_unlock(s); err = dquot_suspend(s, -1); if (err < 0) goto out_err; + reiserfs_write_lock(s); /* try to remount file system with read-only permissions */ if (sb_umount_state(rs) == REISERFS_VALID_FS @@ -1358,7 +1364,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) err = journal_begin(&th, s, 10); if (err) - goto out_err; + goto out_unlock; /* Mounting a rw partition read-only. */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); @@ -1373,7 +1379,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) if (reiserfs_is_journal_aborted(journal)) { err = journal->j_errno; - goto out_err; + goto out_unlock; } handle_data_mode(s, mount_options); @@ -1382,7 +1388,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */ err = journal_begin(&th, s, 10); if (err) - goto out_err; + goto out_unlock; /* Mount a partition which is read-only, read-write */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); @@ -1399,11 +1405,17 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) SB_JOURNAL(s)->j_must_wait = 1; err = journal_end(&th, s, 10); if (err) - goto out_err; + goto out_unlock; s->s_dirt = 0; if (!(*mount_flags & MS_RDONLY)) { + /* + * Drop write lock. Quota will retake it when needed and lock + * ordering requires calling dquot_resume() without it. + */ + reiserfs_write_unlock(s); dquot_resume(s, -1); + reiserfs_write_lock(s); finish_unfinished(s); reiserfs_xattr_init(s, *mount_flags); } @@ -1413,9 +1425,10 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) reiserfs_write_unlock(s); return 0; +out_unlock: + reiserfs_write_unlock(s); out_err: kfree(new_opts); - reiserfs_write_unlock(s); return err; } -- GitLab From 8ed4d1ceb26e7f1011314a4f2db93897fb8949e2 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 13 Nov 2012 16:34:17 +0100 Subject: [PATCH 1030/1799] reiserfs: Protect reiserfs_quota_on() with write lock commit b9e06ef2e8706fe669b51f4364e3aeed58639eb2 upstream. In reiserfs_quota_on() we do quite some work - for example unpacking tail of a quota file. Thus we have to hold write lock until a moment we call back into the quota code. Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/super.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index f4f83bfc5719..107f7bd75e98 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -2170,8 +2170,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, struct reiserfs_transaction_handle th; int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA; - if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) - return -EINVAL; + reiserfs_write_lock(sb); + if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) { + err = -EINVAL; + goto out; + } /* Quotafile not on the same filesystem? */ if (path->dentry->d_sb != sb) { @@ -2213,8 +2216,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, if (err) goto out; } - err = dquot_quota_on(sb, type, format_id, path); + reiserfs_write_unlock(sb); + return dquot_quota_on(sb, type, format_id, path); out: + reiserfs_write_unlock(sb); return err; } -- GitLab From 8c7dcc4819098b0166e4559fbfd6fa661fbb5755 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 13 Nov 2012 17:05:14 +0100 Subject: [PATCH 1031/1799] reiserfs: Move quota calls out of write lock commit 7af11686933726e99af22901d622f9e161404e6b upstream. Calls into highlevel quota code cannot happen under the write lock. These calls take dqio_mutex which ranks above write lock. So drop write lock before calling back into quota code. Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/inode.c | 10 +++++++--- fs/reiserfs/stree.c | 4 ++++ fs/reiserfs/super.c | 18 ++++++++++++++---- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index f99c1b4fa5fd..c11db5134b72 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1788,8 +1788,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, BUG_ON(!th->t_trans_id); - dquot_initialize(inode); + reiserfs_write_unlock(inode->i_sb); err = dquot_alloc_inode(inode); + reiserfs_write_lock(inode->i_sb); if (err) goto out_end_trans; if (!dir->i_nlink) { @@ -1985,8 +1986,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, out_end_trans: journal_end(th, th->t_super, th->t_blocks_allocated); + reiserfs_write_unlock(inode->i_sb); /* Drop can be outside and it needs more credits so it's better to have it outside */ dquot_drop(inode); + reiserfs_write_lock(inode->i_sb); inode->i_flags |= S_NOQUOTA; make_bad_inode(inode); @@ -3109,10 +3112,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) /* must be turned off for recursive notify_change calls */ ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); - depth = reiserfs_write_lock_once(inode->i_sb); if (is_quota_modification(inode, attr)) dquot_initialize(inode); - + depth = reiserfs_write_lock_once(inode->i_sb); if (attr->ia_valid & ATTR_SIZE) { /* version 2 items will be caught by the s_maxbytes check ** done for us in vmtruncate @@ -3176,7 +3178,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) error = journal_begin(&th, inode->i_sb, jbegin_count); if (error) goto out; + reiserfs_write_unlock_once(inode->i_sb, depth); error = dquot_transfer(inode, attr); + depth = reiserfs_write_lock_once(inode->i_sb); if (error) { journal_end(&th, inode->i_sb, jbegin_count); goto out; diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index f8afa4b162b8..2f40a4c70a4d 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree key2type(&(key->on_disk_key))); #endif + reiserfs_write_unlock(inode->i_sb); retval = dquot_alloc_space_nodirty(inode, pasted_size); + reiserfs_write_lock(inode->i_sb); if (retval) { pathrelse(search_path); return retval; @@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, "reiserquota insert_item(): allocating %u id=%u type=%c", quota_bytes, inode->i_uid, head2type(ih)); #endif + reiserfs_write_unlock(inode->i_sb); /* We can't dirty inode here. It would be immediately written but * appropriate stat item isn't inserted yet... */ retval = dquot_alloc_space_nodirty(inode, quota_bytes); + reiserfs_write_lock(inode->i_sb); if (retval) { pathrelse(path); return retval; diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 107f7bd75e98..72a06365e9dc 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -256,7 +256,9 @@ static int finish_unfinished(struct super_block *s) retval = remove_save_link_only(s, &save_link_key, 0); continue; } + reiserfs_write_unlock(s); dquot_initialize(inode); + reiserfs_write_lock(s); if (truncate && S_ISDIR(inode->i_mode)) { /* We got a truncate request for a dir which is impossible. @@ -2062,13 +2064,15 @@ static int reiserfs_write_dquot(struct dquot *dquot) REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); if (ret) goto out; + reiserfs_write_unlock(dquot->dq_sb); ret = dquot_commit(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(dquot->dq_sb); return ret; } @@ -2084,13 +2088,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot) REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); if (ret) goto out; + reiserfs_write_unlock(dquot->dq_sb); ret = dquot_acquire(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(dquot->dq_sb); return ret; } @@ -2104,19 +2110,21 @@ static int reiserfs_release_dquot(struct dquot *dquot) ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); + reiserfs_write_unlock(dquot->dq_sb); if (ret) { /* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release(dquot); goto out; } ret = dquot_release(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: reiserfs_write_unlock(dquot->dq_sb); +out: return ret; } @@ -2141,11 +2149,13 @@ static int reiserfs_write_info(struct super_block *sb, int type) ret = journal_begin(&th, sb, 2); if (ret) goto out; + reiserfs_write_unlock(sb); ret = dquot_commit_info(sb, type); + reiserfs_write_lock(sb); err = journal_end(&th, sb, 2); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(sb); return ret; } -- GitLab From a23d6310a6fbe4a2a1d3a40251a6d5b8ae39ec22 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 13 Nov 2012 18:25:38 +0100 Subject: [PATCH 1032/1799] reiserfs: Protect reiserfs_quota_write() with write lock commit 361d94a338a3fd0cee6a4ea32bbc427ba228e628 upstream. Calls into reiserfs journalling code and reiserfs_get_block() need to be protected with write lock. We remove write lock around calls to high level quota code in the next patch so these paths would suddently become unprotected. Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/super.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 72a06365e9dc..8169be93ac0f 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -2303,7 +2303,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, tocopy = sb->s_blocksize - offset < towrite ? sb->s_blocksize - offset : towrite; tmp_bh.b_state = 0; + reiserfs_write_lock(sb); err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE); + reiserfs_write_unlock(sb); if (err) goto out; if (offset || tocopy != sb->s_blocksize) @@ -2319,10 +2321,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, flush_dcache_page(bh->b_page); set_buffer_uptodate(bh); unlock_buffer(bh); + reiserfs_write_lock(sb); reiserfs_prepare_for_journal(sb, bh, 1); journal_mark_dirty(current->journal_info, sb, bh); if (!journal_quota) reiserfs_add_ordered_list(inode, bh); + reiserfs_write_unlock(sb); brelse(bh); offset = 0; towrite -= tocopy; -- GitLab From 55649211861616c26aa25c9e710c5691837975e4 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 8 Nov 2012 16:09:27 -0800 Subject: [PATCH 1033/1799] selinux: fix sel_netnode_insert() suspicious rcu dereference commit 88a693b5c1287be4da937699cb82068ce9db0135 upstream. =============================== [ INFO: suspicious RCU usage. ] 3.5.0-rc1+ #63 Not tainted ------------------------------- security/selinux/netnode.c:178 suspicious rcu_dereference_check() usage! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 0 1 lock held by trinity-child1/8750: #0: (sel_netnode_lock){+.....}, at: [] sel_netnode_sid+0x16a/0x3e0 stack backtrace: Pid: 8750, comm: trinity-child1 Not tainted 3.5.0-rc1+ #63 Call Trace: [] lockdep_rcu_suspicious+0xfd/0x130 [] sel_netnode_sid+0x3b1/0x3e0 [] ? sel_netnode_find+0x1a0/0x1a0 [] selinux_socket_bind+0xf6/0x2c0 [] ? trace_hardirqs_off+0xd/0x10 [] ? lock_release_holdtime.part.9+0x15/0x1a0 [] ? lock_hrtimer_base+0x31/0x60 [] security_socket_bind+0x16/0x20 [] sys_bind+0x7a/0x100 [] ? sysret_check+0x22/0x5d [] ? trace_hardirqs_on_caller+0x10d/0x1a0 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x16/0x1b This patch below does what Paul McKenney suggested in the previous thread. Signed-off-by: Dave Jones Reviewed-by: Paul E. McKenney Acked-by: Paul Moore Cc: Eric Paris Signed-off-by: Andrew Morton Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman --- security/selinux/netnode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 86365857c088..04aa5c8adf74 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c @@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node) if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) { struct sel_netnode *tail; tail = list_entry( - rcu_dereference(sel_netnode_hash[idx].list.prev), + rcu_dereference_protected(sel_netnode_hash[idx].list.prev, + lockdep_is_held(&sel_netnode_lock)), struct sel_netnode, list); list_del_rcu(&tail->list); kfree_rcu(tail, rcu); -- GitLab From 506b4672ace55889c16d4e9d5515e0c1ae7832d5 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 7 May 2012 15:38:35 -0700 Subject: [PATCH 1034/1799] crush: clean up types, const-ness (cherry picked from commit 8b12d47b80c7a34dffdd98244d99316db490ec58) Move various types from int -> __u32 (or similar), and add const as appropriate. This reflects changes that have been present in the userland implementation for some time. Reviewed-by: Alex Elder Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/crush/crush.h | 2 +- include/linux/crush/mapper.h | 6 +++--- net/ceph/crush/crush.c | 8 ++++---- net/ceph/crush/mapper.c | 31 ++++++++++++++++--------------- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/include/linux/crush/crush.h b/include/linux/crush/crush.h index 97e435b191f4..3f50369a50e8 100644 --- a/include/linux/crush/crush.h +++ b/include/linux/crush/crush.h @@ -168,7 +168,7 @@ struct crush_map { /* crush.c */ -extern int crush_get_bucket_item_weight(struct crush_bucket *b, int pos); +extern int crush_get_bucket_item_weight(const struct crush_bucket *b, int pos); extern void crush_calc_parents(struct crush_map *map); extern void crush_destroy_bucket_uniform(struct crush_bucket_uniform *b); extern void crush_destroy_bucket_list(struct crush_bucket_list *b); diff --git a/include/linux/crush/mapper.h b/include/linux/crush/mapper.h index c46b99c18bb0..9322ab8bccd8 100644 --- a/include/linux/crush/mapper.h +++ b/include/linux/crush/mapper.h @@ -10,11 +10,11 @@ #include "crush.h" -extern int crush_find_rule(struct crush_map *map, int pool, int type, int size); -extern int crush_do_rule(struct crush_map *map, +extern int crush_find_rule(const struct crush_map *map, int ruleset, int type, int size); +extern int crush_do_rule(const struct crush_map *map, int ruleno, int x, int *result, int result_max, int forcefeed, /* -1 for none */ - __u32 *weights); + const __u32 *weights); #endif diff --git a/net/ceph/crush/crush.c b/net/ceph/crush/crush.c index d6ebb13a18a4..8dd19a0deedc 100644 --- a/net/ceph/crush/crush.c +++ b/net/ceph/crush/crush.c @@ -26,9 +26,9 @@ const char *crush_bucket_alg_name(int alg) * @b: bucket pointer * @p: item index in bucket */ -int crush_get_bucket_item_weight(struct crush_bucket *b, int p) +int crush_get_bucket_item_weight(const struct crush_bucket *b, int p) { - if (p >= b->size) + if ((__u32)p >= b->size) return 0; switch (b->alg) { @@ -124,10 +124,9 @@ void crush_destroy_bucket(struct crush_bucket *b) */ void crush_destroy(struct crush_map *map) { - int b; - /* buckets */ if (map->buckets) { + __s32 b; for (b = 0; b < map->max_buckets; b++) { if (map->buckets[b] == NULL) continue; @@ -138,6 +137,7 @@ void crush_destroy(struct crush_map *map) /* rules */ if (map->rules) { + __u32 b; for (b = 0; b < map->max_rules; b++) kfree(map->rules[b]); kfree(map->rules); diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c index b79747c4b645..436102a8a461 100644 --- a/net/ceph/crush/mapper.c +++ b/net/ceph/crush/mapper.c @@ -32,9 +32,9 @@ * @type: storage ruleset type (user defined) * @size: output set size */ -int crush_find_rule(struct crush_map *map, int ruleset, int type, int size) +int crush_find_rule(const struct crush_map *map, int ruleset, int type, int size) { - int i; + __u32 i; for (i = 0; i < map->max_rules; i++) { if (map->rules[i] && @@ -72,7 +72,7 @@ static int bucket_perm_choose(struct crush_bucket *bucket, unsigned i, s; /* start a new permutation if @x has changed */ - if (bucket->perm_x != x || bucket->perm_n == 0) { + if (bucket->perm_x != (__u32)x || bucket->perm_n == 0) { dprintk("bucket %d new x=%d\n", bucket->id, x); bucket->perm_x = x; @@ -219,7 +219,7 @@ static int bucket_tree_choose(struct crush_bucket_tree *bucket, static int bucket_straw_choose(struct crush_bucket_straw *bucket, int x, int r) { - int i; + __u32 i; int high = 0; __u64 high_draw = 0; __u64 draw; @@ -262,7 +262,7 @@ static int crush_bucket_choose(struct crush_bucket *in, int x, int r) * true if device is marked "out" (failed, fully offloaded) * of the cluster */ -static int is_out(struct crush_map *map, __u32 *weight, int item, int x) +static int is_out(const struct crush_map *map, const __u32 *weight, int item, int x) { if (weight[item] >= 0x10000) return 0; @@ -287,16 +287,16 @@ static int is_out(struct crush_map *map, __u32 *weight, int item, int x) * @recurse_to_leaf: true if we want one device under each item of given type * @out2: second output vector for leaf items (if @recurse_to_leaf) */ -static int crush_choose(struct crush_map *map, +static int crush_choose(const struct crush_map *map, struct crush_bucket *bucket, - __u32 *weight, + const __u32 *weight, int x, int numrep, int type, int *out, int outpos, int firstn, int recurse_to_leaf, int *out2) { int rep; - int ftotal, flocal; + unsigned int ftotal, flocal; int retry_descent, retry_bucket, skip_rep; struct crush_bucket *in = bucket; int r; @@ -304,7 +304,7 @@ static int crush_choose(struct crush_map *map, int item = 0; int itemtype; int collide, reject; - const int orig_tries = 5; /* attempts before we fall back to search */ + const unsigned int orig_tries = 5; /* attempts before we fall back to search */ dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "", bucket->id, x, outpos, numrep); @@ -325,7 +325,7 @@ static int crush_choose(struct crush_map *map, r = rep; if (in->alg == CRUSH_BUCKET_UNIFORM) { /* be careful */ - if (firstn || numrep >= in->size) + if (firstn || (__u32)numrep >= in->size) /* r' = r + f_total */ r += ftotal; else if (in->size % numrep == 0) @@ -425,7 +425,7 @@ static int crush_choose(struct crush_map *map, /* else give up */ skip_rep = 1; dprintk(" reject %d collide %d " - "ftotal %d flocal %d\n", + "ftotal %u flocal %u\n", reject, collide, ftotal, flocal); } @@ -456,9 +456,9 @@ static int crush_choose(struct crush_map *map, * @result_max: maximum result size * @force: force initial replica choice; -1 for none */ -int crush_do_rule(struct crush_map *map, +int crush_do_rule(const struct crush_map *map, int ruleno, int x, int *result, int result_max, - int force, __u32 *weight) + int force, const __u32 *weight) { int result_len; int force_context[CRUSH_MAX_DEPTH]; @@ -473,7 +473,7 @@ int crush_do_rule(struct crush_map *map, int osize; int *tmp; struct crush_rule *rule; - int step; + __u32 step; int i, j; int numrep; int firstn; @@ -488,7 +488,8 @@ int crush_do_rule(struct crush_map *map, /* * determine hierarchical context of force, if any. note * that this may or may not correspond to the specific types - * referenced by the crush rule. + * referenced by the crush rule. it will also only affect + * the first descent (TAKE). */ if (force >= 0 && force < map->max_devices && -- GitLab From 9926776ca573b23914d5265457202307a3715748 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 7 May 2012 15:35:09 -0700 Subject: [PATCH 1035/1799] crush: adjust local retry threshold (cherry picked from commit c90f95ed46393e29d843686e21947d1c6fcb1164) This small adjustment reflects a change that was made in ceph.git commit af6a9f30696c900a2a8bd7ae24e8ed15fb4964bb, about 6 months ago. An N-1 search is not exhaustive. Fixed ceph.git bug #1594. Reviewed-by: Alex Elder Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/crush/mapper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c index 436102a8a461..583f644b0e28 100644 --- a/net/ceph/crush/mapper.c +++ b/net/ceph/crush/mapper.c @@ -415,7 +415,7 @@ static int crush_choose(const struct crush_map *map, if (collide && flocal < 3) /* retry locally a few times */ retry_bucket = 1; - else if (flocal < in->size + orig_tries) + else if (flocal <= in->size + orig_tries) /* exhaustive bucket search */ retry_bucket = 1; else if (ftotal < 20) -- GitLab From 20501b9e6e1db8e7ab6668ef15d697b1c057a50a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 7 May 2012 15:35:24 -0700 Subject: [PATCH 1036/1799] crush: be more tolerant of nonsensical crush maps (cherry picked from commit a1f4895be8bf1ba56c2306b058f51619e9b0e8f8) If we get a map that doesn't make sense, error out or ignore the badness instead of BUGging out. This reflects the ceph.git commits 9895f0bff7dc68e9b49b572613d242315fb11b6c and 8ded26472058d5205803f244c2f33cb6cb10de79. Reviewed-by: Alex Elder Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/crush/mapper.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c index 583f644b0e28..00baad5d3bde 100644 --- a/net/ceph/crush/mapper.c +++ b/net/ceph/crush/mapper.c @@ -152,8 +152,8 @@ static int bucket_list_choose(struct crush_bucket_list *bucket, return bucket->h.items[i]; } - BUG_ON(1); - return 0; + dprintk("bad list sums for bucket %d\n", bucket->h.id); + return bucket->h.items[0]; } @@ -239,6 +239,7 @@ static int bucket_straw_choose(struct crush_bucket_straw *bucket, static int crush_bucket_choose(struct crush_bucket *in, int x, int r) { dprintk(" crush_bucket_choose %d x=%d r=%d\n", in->id, x, r); + BUG_ON(in->size == 0); switch (in->alg) { case CRUSH_BUCKET_UNIFORM: return bucket_uniform_choose((struct crush_bucket_uniform *)in, @@ -253,7 +254,7 @@ static int crush_bucket_choose(struct crush_bucket *in, int x, int r) return bucket_straw_choose((struct crush_bucket_straw *)in, x, r); default: - BUG_ON(1); + dprintk("unknown bucket %d alg %d\n", in->id, in->alg); return in->items[0]; } } @@ -354,7 +355,11 @@ static int crush_choose(const struct crush_map *map, item = bucket_perm_choose(in, x, r); else item = crush_bucket_choose(in, x, r); - BUG_ON(item >= map->max_devices); + if (item >= map->max_devices) { + dprintk(" bad item %d\n", item); + skip_rep = 1; + break; + } /* desired type? */ if (item < 0) @@ -365,8 +370,12 @@ static int crush_choose(const struct crush_map *map, /* keep going? */ if (itemtype != type) { - BUG_ON(item >= 0 || - (-1-item) >= map->max_buckets); + if (item >= 0 || + (-1-item) >= map->max_buckets) { + dprintk(" bad item type %d\n", type); + skip_rep = 1; + break; + } in = map->buckets[-1-item]; retry_bucket = 1; continue; @@ -478,7 +487,10 @@ int crush_do_rule(const struct crush_map *map, int numrep; int firstn; - BUG_ON(ruleno >= map->max_rules); + if ((__u32)ruleno >= map->max_rules) { + dprintk(" bad ruleno %d\n", ruleno); + return 0; + } rule = map->rules[ruleno]; result_len = 0; @@ -528,7 +540,8 @@ int crush_do_rule(const struct crush_map *map, firstn = 1; case CRUSH_RULE_CHOOSE_LEAF_INDEP: case CRUSH_RULE_CHOOSE_INDEP: - BUG_ON(wsize == 0); + if (wsize == 0) + break; recurse_to_leaf = rule->steps[step].op == @@ -597,7 +610,9 @@ int crush_do_rule(const struct crush_map *map, break; default: - BUG_ON(1); + dprintk(" unknown op %d at step %d\n", + curstep->op, step); + break; } } return result_len; -- GitLab From 9a0117ae53308d0d8284ba5664ed4c1d0ec54176 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 7 May 2012 15:36:49 -0700 Subject: [PATCH 1037/1799] crush: fix tree node weight lookup (cherry picked from commit f671d4cd9b36691ac4ef42cde44c1b7a84e13631) Fix the node weight lookup for tree buckets by using a correct accessor. Reflects ceph.git commit d287ade5bcbdca82a3aef145b92924cf1e856733. Reviewed-by: Alex Elder Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/crush/crush.h | 5 +++++ net/ceph/crush/crush.c | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/linux/crush/crush.h b/include/linux/crush/crush.h index 3f50369a50e8..e7a8c9055cb2 100644 --- a/include/linux/crush/crush.h +++ b/include/linux/crush/crush.h @@ -177,4 +177,9 @@ extern void crush_destroy_bucket_straw(struct crush_bucket_straw *b); extern void crush_destroy_bucket(struct crush_bucket *b); extern void crush_destroy(struct crush_map *map); +static inline int crush_calc_tree_node(int i) +{ + return ((i+1) << 1)-1; +} + #endif diff --git a/net/ceph/crush/crush.c b/net/ceph/crush/crush.c index 8dd19a0deedc..f23611d0cdee 100644 --- a/net/ceph/crush/crush.c +++ b/net/ceph/crush/crush.c @@ -37,9 +37,7 @@ int crush_get_bucket_item_weight(const struct crush_bucket *b, int p) case CRUSH_BUCKET_LIST: return ((struct crush_bucket_list *)b)->item_weights[p]; case CRUSH_BUCKET_TREE: - if (p & 1) - return ((struct crush_bucket_tree *)b)->node_weights[p]; - return 0; + return ((struct crush_bucket_tree *)b)->node_weights[crush_calc_tree_node(p)]; case CRUSH_BUCKET_STRAW: return ((struct crush_bucket_straw *)b)->item_weights[p]; } -- GitLab From cf34fc7d48d9600665e570b5c8a297a52bbe5fc5 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 7 May 2012 15:37:05 -0700 Subject: [PATCH 1038/1799] crush: fix memory leak when destroying tree buckets (cherry picked from commit 6eb43f4b5a2a74599b4ff17a97c03a342327ca65) Reflects ceph.git commit 46d63d98434b3bc9dad2fc9ab23cbaedc3bcb0e4. Reported-by: Alexander Lyakas Reviewed-by: Alex Elder Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/crush/crush.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ceph/crush/crush.c b/net/ceph/crush/crush.c index f23611d0cdee..fbda0521a006 100644 --- a/net/ceph/crush/crush.c +++ b/net/ceph/crush/crush.c @@ -85,6 +85,8 @@ void crush_destroy_bucket_list(struct crush_bucket_list *b) void crush_destroy_bucket_tree(struct crush_bucket_tree *b) { + kfree(b->h.perm); + kfree(b->h.items); kfree(b->node_weights); kfree(b); } -- GitLab From f77637d9f603dd74cf1b4366d7bb1938a6715ab2 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 20 Apr 2012 15:49:43 -0500 Subject: [PATCH 1039/1799] ceph: osd_client: fix endianness bug in osd_req_encode_op() (cherry picked from commit 065a68f9167e20f321a62d044cb2c3024393d455) From Al Viro Al Viro noticed that we were using a non-cpu-encoded value in a switch statement in osd_req_encode_op(). The result would clearly not work correctly on a big-endian machine. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/osd_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 5e254055c910..daa2716a0c30 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -278,7 +278,7 @@ static void osd_req_encode_op(struct ceph_osd_request *req, { dst->op = cpu_to_le16(src->op); - switch (dst->op) { + switch (src->op) { case CEPH_OSD_OP_READ: case CEPH_OSD_OP_WRITE: dst->extent.offset = -- GitLab From d0d7af68e9da4d8ad24052151d5d4add6464f505 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 10 May 2012 10:29:50 -0500 Subject: [PATCH 1040/1799] ceph: messenger: use read_partial() in read_partial_message() (cherry picked from commit 57dac9d1620942608306d8c17c98a9d1568ffdf4) There are two blocks of code in read_partial_message()--those that read the header and footer of the message--that can be replaced by a call to read_partial(). Do that. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index f0993af2ae4d..673133ee3181 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1628,7 +1628,7 @@ static int read_partial_message(struct ceph_connection *con) { struct ceph_msg *m = con->in_msg; int ret; - int to, left; + int to; unsigned front_len, middle_len, data_len; bool do_datacrc = !con->msgr->nocrc; int skip; @@ -1638,15 +1638,10 @@ static int read_partial_message(struct ceph_connection *con) dout("read_partial_message con %p msg %p\n", con, m); /* header */ - while (con->in_base_pos < sizeof(con->in_hdr)) { - left = sizeof(con->in_hdr) - con->in_base_pos; - ret = ceph_tcp_recvmsg(con->sock, - (char *)&con->in_hdr + con->in_base_pos, - left); - if (ret <= 0) - return ret; - con->in_base_pos += ret; - } + to = 0; + ret = read_partial(con, &to, sizeof (con->in_hdr), &con->in_hdr); + if (ret <= 0) + return ret; crc = crc32c(0, &con->in_hdr, offsetof(struct ceph_msg_header, crc)); if (cpu_to_le32(crc) != con->in_hdr.crc) { @@ -1759,16 +1754,11 @@ static int read_partial_message(struct ceph_connection *con) } /* footer */ - to = sizeof(m->hdr) + sizeof(m->footer); - while (con->in_base_pos < to) { - left = to - con->in_base_pos; - ret = ceph_tcp_recvmsg(con->sock, (char *)&m->footer + - (con->in_base_pos - sizeof(m->hdr)), - left); - if (ret <= 0) - return ret; - con->in_base_pos += ret; - } + to = sizeof (m->hdr); + ret = read_partial(con, &to, sizeof (m->footer), &m->footer); + if (ret <= 0) + return ret; + dout("read_partial_message got msg %p %d (%u) + %d (%u) + %d (%u)\n", m, front_len, m->footer.front_crc, middle_len, m->footer.middle_crc, data_len, m->footer.data_crc); -- GitLab From dd22ce515dc6f8a69957473f1ce0d0d8f043b06a Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 10 May 2012 10:29:50 -0500 Subject: [PATCH 1041/1799] ceph: messenger: update "to" in read_partial() caller (cherry picked from commit e6cee71fac27c946a0bbad754dd076e66c4e9dbd) read_partial() always increases whatever "to" value is supplied by adding the requested size to it, and that's the only thing it does with that pointed-to value. Do that pointer advance in the caller (and then only when the updated value will be subsequently used), and change the "to" parameter to be an in-only and non-pointer value. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 673133ee3181..37fd2aece232 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -992,11 +992,12 @@ static int prepare_read_message(struct ceph_connection *con) static int read_partial(struct ceph_connection *con, - int *to, int size, void *object) + int to, int size, void *object) { - *to += size; - while (con->in_base_pos < *to) { - int left = *to - con->in_base_pos; + int end = to + size; + + while (con->in_base_pos < end) { + int left = end - con->in_base_pos; int have = size - left; int ret = ceph_tcp_recvmsg(con->sock, object + have, left); if (ret <= 0) @@ -1017,14 +1018,16 @@ static int read_partial_banner(struct ceph_connection *con) dout("read_partial_banner %p at %d\n", con, con->in_base_pos); /* peer's banner */ - ret = read_partial(con, &to, strlen(CEPH_BANNER), con->in_banner); + ret = read_partial(con, to, strlen(CEPH_BANNER), con->in_banner); if (ret <= 0) goto out; - ret = read_partial(con, &to, sizeof(con->actual_peer_addr), + to += strlen(CEPH_BANNER); + ret = read_partial(con, to, sizeof(con->actual_peer_addr), &con->actual_peer_addr); if (ret <= 0) goto out; - ret = read_partial(con, &to, sizeof(con->peer_addr_for_me), + to += sizeof(con->actual_peer_addr); + ret = read_partial(con, to, sizeof(con->peer_addr_for_me), &con->peer_addr_for_me); if (ret <= 0) goto out; @@ -1038,10 +1041,11 @@ static int read_partial_connect(struct ceph_connection *con) dout("read_partial_connect %p at %d\n", con, con->in_base_pos); - ret = read_partial(con, &to, sizeof(con->in_reply), &con->in_reply); + ret = read_partial(con, to, sizeof(con->in_reply), &con->in_reply); if (ret <= 0) goto out; - ret = read_partial(con, &to, le32_to_cpu(con->in_reply.authorizer_len), + to += sizeof(con->in_reply); + ret = read_partial(con, to, le32_to_cpu(con->in_reply.authorizer_len), con->auth_reply_buf); if (ret <= 0) goto out; @@ -1491,9 +1495,7 @@ static int process_connect(struct ceph_connection *con) */ static int read_partial_ack(struct ceph_connection *con) { - int to = 0; - - return read_partial(con, &to, sizeof(con->in_temp_ack), + return read_partial(con, 0, sizeof(con->in_temp_ack), &con->in_temp_ack); } @@ -1638,8 +1640,7 @@ static int read_partial_message(struct ceph_connection *con) dout("read_partial_message con %p msg %p\n", con, m); /* header */ - to = 0; - ret = read_partial(con, &to, sizeof (con->in_hdr), &con->in_hdr); + ret = read_partial(con, 0, sizeof (con->in_hdr), &con->in_hdr); if (ret <= 0) return ret; @@ -1755,7 +1756,7 @@ static int read_partial_message(struct ceph_connection *con) /* footer */ to = sizeof (m->hdr); - ret = read_partial(con, &to, sizeof (m->footer), &m->footer); + ret = read_partial(con, to, sizeof (m->footer), &m->footer); if (ret <= 0) return ret; -- GitLab From 1f7631fba2a763f45bfec34bdf731e2089ca3d87 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 10 May 2012 10:29:50 -0500 Subject: [PATCH 1042/1799] ceph: messenger: change read_partial() to take "end" arg (cherry picked from commit fd51653f78cf40a0516e521b6de22f329c5bad8d) Make the second argument to read_partial() be the ending input byte position rather than the beginning offset it now represents. This amounts to moving the addition "to + size" into the caller. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 60 ++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 37fd2aece232..a659b4de64aa 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -992,10 +992,8 @@ static int prepare_read_message(struct ceph_connection *con) static int read_partial(struct ceph_connection *con, - int to, int size, void *object) + int end, int size, void *object) { - int end = to + size; - while (con->in_base_pos < end) { int left = end - con->in_base_pos; int have = size - left; @@ -1013,40 +1011,52 @@ static int read_partial(struct ceph_connection *con, */ static int read_partial_banner(struct ceph_connection *con) { - int ret, to = 0; + int size; + int end; + int ret; dout("read_partial_banner %p at %d\n", con, con->in_base_pos); /* peer's banner */ - ret = read_partial(con, to, strlen(CEPH_BANNER), con->in_banner); + size = strlen(CEPH_BANNER); + end = size; + ret = read_partial(con, end, size, con->in_banner); if (ret <= 0) goto out; - to += strlen(CEPH_BANNER); - ret = read_partial(con, to, sizeof(con->actual_peer_addr), - &con->actual_peer_addr); + + size = sizeof (con->actual_peer_addr); + end += size; + ret = read_partial(con, end, size, &con->actual_peer_addr); if (ret <= 0) goto out; - to += sizeof(con->actual_peer_addr); - ret = read_partial(con, to, sizeof(con->peer_addr_for_me), - &con->peer_addr_for_me); + + size = sizeof (con->peer_addr_for_me); + end += size; + ret = read_partial(con, end, size, &con->peer_addr_for_me); if (ret <= 0) goto out; + out: return ret; } static int read_partial_connect(struct ceph_connection *con) { - int ret, to = 0; + int size; + int end; + int ret; dout("read_partial_connect %p at %d\n", con, con->in_base_pos); - ret = read_partial(con, to, sizeof(con->in_reply), &con->in_reply); + size = sizeof (con->in_reply); + end = size; + ret = read_partial(con, end, size, &con->in_reply); if (ret <= 0) goto out; - to += sizeof(con->in_reply); - ret = read_partial(con, to, le32_to_cpu(con->in_reply.authorizer_len), - con->auth_reply_buf); + + size = le32_to_cpu(con->in_reply.authorizer_len); + end += size; + ret = read_partial(con, end, size, con->auth_reply_buf); if (ret <= 0) goto out; @@ -1495,8 +1505,10 @@ static int process_connect(struct ceph_connection *con) */ static int read_partial_ack(struct ceph_connection *con) { - return read_partial(con, 0, sizeof(con->in_temp_ack), - &con->in_temp_ack); + int size = sizeof (con->in_temp_ack); + int end = size; + + return read_partial(con, end, size, &con->in_temp_ack); } @@ -1629,8 +1641,9 @@ static int read_partial_message_bio(struct ceph_connection *con, static int read_partial_message(struct ceph_connection *con) { struct ceph_msg *m = con->in_msg; + int size; + int end; int ret; - int to; unsigned front_len, middle_len, data_len; bool do_datacrc = !con->msgr->nocrc; int skip; @@ -1640,7 +1653,9 @@ static int read_partial_message(struct ceph_connection *con) dout("read_partial_message con %p msg %p\n", con, m); /* header */ - ret = read_partial(con, 0, sizeof (con->in_hdr), &con->in_hdr); + size = sizeof (con->in_hdr); + end = size; + ret = read_partial(con, end, size, &con->in_hdr); if (ret <= 0) return ret; @@ -1755,8 +1770,9 @@ static int read_partial_message(struct ceph_connection *con) } /* footer */ - to = sizeof (m->hdr); - ret = read_partial(con, to, sizeof (m->footer), &m->footer); + size = sizeof (m->footer); + end += size; + ret = read_partial(con, end, size, &m->footer); if (ret <= 0) return ret; -- GitLab From 6b7cc02849d47abf3077e27aec841dbd140b8b35 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:38 -0500 Subject: [PATCH 1043/1799] libceph: don't reset kvec in prepare_write_banner() (cherry picked from commit d329156f16306449c273002486c28de3ddddfd89) Move the kvec reset for a connection out of prepare_write_banner and into its only caller. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index a659b4de64aa..bcbd409b5ca7 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -686,7 +686,6 @@ static int prepare_connect_authorizer(struct ceph_connection *con) static void prepare_write_banner(struct ceph_messenger *msgr, struct ceph_connection *con) { - ceph_con_out_kvec_reset(con); ceph_con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER); ceph_con_out_kvec_add(con, sizeof (msgr->my_enc_addr), &msgr->my_enc_addr); @@ -726,10 +725,9 @@ static int prepare_write_connect(struct ceph_messenger *msgr, con->out_connect.protocol_version = cpu_to_le32(proto); con->out_connect.flags = 0; + ceph_con_out_kvec_reset(con); if (include_banner) prepare_write_banner(msgr, con); - else - ceph_con_out_kvec_reset(con); ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); con->out_more = 0; -- GitLab From 726644c635924f48f1bc9f64087e92915bc61fc7 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:38 -0500 Subject: [PATCH 1044/1799] ceph: messenger: reset connection kvec caller (cherry picked from commit 84fb3adf6413862cff51d8af3fce5f0b655586a2) Reset a connection's kvec fields in the caller rather than in prepare_write_connect(). This ends up repeating a few lines of code but it's improving the separation between distinct operations on the connection, which we can take advantage of later. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index bcbd409b5ca7..cca3cf341d70 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -725,7 +725,6 @@ static int prepare_write_connect(struct ceph_messenger *msgr, con->out_connect.protocol_version = cpu_to_le32(proto); con->out_connect.flags = 0; - ceph_con_out_kvec_reset(con); if (include_banner) prepare_write_banner(msgr, con); ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); @@ -1389,6 +1388,7 @@ static int process_connect(struct ceph_connection *con) return -1; } con->auth_retry = 1; + ceph_con_out_kvec_reset(con); ret = prepare_write_connect(con->msgr, con, 0); if (ret < 0) return ret; @@ -1409,6 +1409,7 @@ static int process_connect(struct ceph_connection *con) ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr)); reset_connection(con); + ceph_con_out_kvec_reset(con); prepare_write_connect(con->msgr, con, 0); prepare_read_connect(con); @@ -1432,6 +1433,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->out_connect.connect_seq), le32_to_cpu(con->in_connect.connect_seq)); con->connect_seq = le32_to_cpu(con->in_connect.connect_seq); + ceph_con_out_kvec_reset(con); prepare_write_connect(con->msgr, con, 0); prepare_read_connect(con); break; @@ -1446,6 +1448,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_connect.global_seq)); get_global_seq(con->msgr, le32_to_cpu(con->in_connect.global_seq)); + ceph_con_out_kvec_reset(con); prepare_write_connect(con->msgr, con, 0); prepare_read_connect(con); break; @@ -1851,6 +1854,7 @@ static int try_write(struct ceph_connection *con) /* open the socket first? */ if (con->sock == NULL) { + ceph_con_out_kvec_reset(con); prepare_write_connect(msgr, con, 1); prepare_read_banner(con); set_bit(CONNECTING, &con->state); -- GitLab From d4ac74c3222ae545e62bb1ab2bd7306d71ba5379 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:38 -0500 Subject: [PATCH 1045/1799] ceph: messenger: send banner in process_connect() (cherry picked from commit 41b90c00858129f52d08e6a05c9cfdb0f2bd074d) prepare_write_connect() has an argument indicating whether a banner should be sent out before sending out a connection message. It's only ever set in one of its callers, so move the code that arranges to send the banner into that caller and drop the "include_banner" argument from prepare_write_connect(). Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index cca3cf341d70..6b38b6fbb25f 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -695,8 +695,7 @@ static void prepare_write_banner(struct ceph_messenger *msgr, } static int prepare_write_connect(struct ceph_messenger *msgr, - struct ceph_connection *con, - int include_banner) + struct ceph_connection *con) { unsigned global_seq = get_global_seq(con->msgr, 0); int proto; @@ -725,8 +724,6 @@ static int prepare_write_connect(struct ceph_messenger *msgr, con->out_connect.protocol_version = cpu_to_le32(proto); con->out_connect.flags = 0; - if (include_banner) - prepare_write_banner(msgr, con); ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); con->out_more = 0; @@ -1389,7 +1386,7 @@ static int process_connect(struct ceph_connection *con) } con->auth_retry = 1; ceph_con_out_kvec_reset(con); - ret = prepare_write_connect(con->msgr, con, 0); + ret = prepare_write_connect(con->msgr, con); if (ret < 0) return ret; prepare_read_connect(con); @@ -1410,7 +1407,7 @@ static int process_connect(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr)); reset_connection(con); ceph_con_out_kvec_reset(con); - prepare_write_connect(con->msgr, con, 0); + prepare_write_connect(con->msgr, con); prepare_read_connect(con); /* Tell ceph about it. */ @@ -1434,7 +1431,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_connect.connect_seq)); con->connect_seq = le32_to_cpu(con->in_connect.connect_seq); ceph_con_out_kvec_reset(con); - prepare_write_connect(con->msgr, con, 0); + prepare_write_connect(con->msgr, con); prepare_read_connect(con); break; @@ -1449,7 +1446,7 @@ static int process_connect(struct ceph_connection *con) get_global_seq(con->msgr, le32_to_cpu(con->in_connect.global_seq)); ceph_con_out_kvec_reset(con); - prepare_write_connect(con->msgr, con, 0); + prepare_write_connect(con->msgr, con); prepare_read_connect(con); break; @@ -1855,7 +1852,8 @@ static int try_write(struct ceph_connection *con) /* open the socket first? */ if (con->sock == NULL) { ceph_con_out_kvec_reset(con); - prepare_write_connect(msgr, con, 1); + prepare_write_banner(msgr, con); + prepare_write_connect(msgr, con); prepare_read_banner(con); set_bit(CONNECTING, &con->state); clear_bit(NEGOTIATING, &con->state); -- GitLab From 7dd07ab6bdc7634e99747557d6ba342b639b13d9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:38 -0500 Subject: [PATCH 1046/1799] ceph: drop msgr argument from prepare_write_connect() (cherry picked from commit e825a66df97776d30a48a187e3a986736af43945) In all cases, the value passed as the msgr argument to prepare_write_connect() is just con->msgr. Just get the msgr value from the ceph connection and drop the unneeded argument. The only msgr passed to prepare_write_banner() is also therefore just the one from con->msgr, so change that function to drop the msgr argument as well. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 6b38b6fbb25f..47499dc0e413 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -683,19 +683,17 @@ static int prepare_connect_authorizer(struct ceph_connection *con) /* * We connected to a peer and are saying hello. */ -static void prepare_write_banner(struct ceph_messenger *msgr, - struct ceph_connection *con) +static void prepare_write_banner(struct ceph_connection *con) { ceph_con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER); - ceph_con_out_kvec_add(con, sizeof (msgr->my_enc_addr), - &msgr->my_enc_addr); + ceph_con_out_kvec_add(con, sizeof (con->msgr->my_enc_addr), + &con->msgr->my_enc_addr); con->out_more = 0; set_bit(WRITE_PENDING, &con->state); } -static int prepare_write_connect(struct ceph_messenger *msgr, - struct ceph_connection *con) +static int prepare_write_connect(struct ceph_connection *con) { unsigned global_seq = get_global_seq(con->msgr, 0); int proto; @@ -717,7 +715,7 @@ static int prepare_write_connect(struct ceph_messenger *msgr, dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con, con->connect_seq, global_seq, proto); - con->out_connect.features = cpu_to_le64(msgr->supported_features); + con->out_connect.features = cpu_to_le64(con->msgr->supported_features); con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT); con->out_connect.connect_seq = cpu_to_le32(con->connect_seq); con->out_connect.global_seq = cpu_to_le32(global_seq); @@ -1386,7 +1384,7 @@ static int process_connect(struct ceph_connection *con) } con->auth_retry = 1; ceph_con_out_kvec_reset(con); - ret = prepare_write_connect(con->msgr, con); + ret = prepare_write_connect(con); if (ret < 0) return ret; prepare_read_connect(con); @@ -1407,7 +1405,7 @@ static int process_connect(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr)); reset_connection(con); ceph_con_out_kvec_reset(con); - prepare_write_connect(con->msgr, con); + prepare_write_connect(con); prepare_read_connect(con); /* Tell ceph about it. */ @@ -1431,7 +1429,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_connect.connect_seq)); con->connect_seq = le32_to_cpu(con->in_connect.connect_seq); ceph_con_out_kvec_reset(con); - prepare_write_connect(con->msgr, con); + prepare_write_connect(con); prepare_read_connect(con); break; @@ -1446,7 +1444,7 @@ static int process_connect(struct ceph_connection *con) get_global_seq(con->msgr, le32_to_cpu(con->in_connect.global_seq)); ceph_con_out_kvec_reset(con); - prepare_write_connect(con->msgr, con); + prepare_write_connect(con); prepare_read_connect(con); break; @@ -1840,7 +1838,6 @@ static void process_message(struct ceph_connection *con) */ static int try_write(struct ceph_connection *con) { - struct ceph_messenger *msgr = con->msgr; int ret = 1; dout("try_write start %p state %lu nref %d\n", con, con->state, @@ -1852,8 +1849,8 @@ static int try_write(struct ceph_connection *con) /* open the socket first? */ if (con->sock == NULL) { ceph_con_out_kvec_reset(con); - prepare_write_banner(msgr, con); - prepare_write_connect(msgr, con); + prepare_write_banner(con); + prepare_write_connect(con); prepare_read_banner(con); set_bit(CONNECTING, &con->state); clear_bit(NEGOTIATING, &con->state); -- GitLab From 59a521ebc05d2bd826d19c4a9a6fb00c313f6a52 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:38 -0500 Subject: [PATCH 1047/1799] ceph: don't set WRITE_PENDING too early (cherry picked from commit e10c758e4031a801ea4d2f8fb39bf14c2658d74b) prepare_write_connect() prepares a connect message, then sets WRITE_PENDING on the connection. Then *after* this, it calls prepare_connect_authorizer(), which updates the content of the connection buffer already queued for sending. It's also possible it will result in prepare_write_connect() returning -EAGAIN despite the WRITE_PENDING big getting set. Fix this by preparing the connect authorizer first, setting the WRITE_PENDING bit only after that is done. Partially addresses http://tracker.newdream.net/issues/2424 Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 47499dc0e413..cf292939dd1e 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -697,6 +697,7 @@ static int prepare_write_connect(struct ceph_connection *con) { unsigned global_seq = get_global_seq(con->msgr, 0); int proto; + int ret; switch (con->peer_name.type) { case CEPH_ENTITY_TYPE_MON: @@ -723,11 +724,14 @@ static int prepare_write_connect(struct ceph_connection *con) con->out_connect.flags = 0; ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); + ret = prepare_connect_authorizer(con); + if (ret) + return ret; con->out_more = 0; set_bit(WRITE_PENDING, &con->state); - return prepare_connect_authorizer(con); + return 0; } /* -- GitLab From 59336e08468a9485e499b1449ebc3d68331233db Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 21:51:59 -0500 Subject: [PATCH 1048/1799] ceph: messenger: check prepare_write_connect() result (cherry picked from commit 5a0f8fdd8a0ebe320952a388331dc043d7e14ced) prepare_write_connect() can return an error, but only one of its callers checks for it. All the rest are in functions that already return errors, so it should be fine to return the error if one gets returned. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index cf292939dd1e..8e76936a8c13 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1409,7 +1409,9 @@ static int process_connect(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr)); reset_connection(con); ceph_con_out_kvec_reset(con); - prepare_write_connect(con); + ret = prepare_write_connect(con); + if (ret < 0) + return ret; prepare_read_connect(con); /* Tell ceph about it. */ @@ -1433,7 +1435,9 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_connect.connect_seq)); con->connect_seq = le32_to_cpu(con->in_connect.connect_seq); ceph_con_out_kvec_reset(con); - prepare_write_connect(con); + ret = prepare_write_connect(con); + if (ret < 0) + return ret; prepare_read_connect(con); break; @@ -1448,7 +1452,9 @@ static int process_connect(struct ceph_connection *con) get_global_seq(con->msgr, le32_to_cpu(con->in_connect.global_seq)); ceph_con_out_kvec_reset(con); - prepare_write_connect(con); + ret = prepare_write_connect(con); + if (ret < 0) + return ret; prepare_read_connect(con); break; @@ -1854,7 +1860,9 @@ static int try_write(struct ceph_connection *con) if (con->sock == NULL) { ceph_con_out_kvec_reset(con); prepare_write_banner(con); - prepare_write_connect(con); + ret = prepare_write_connect(con); + if (ret < 0) + goto out; prepare_read_banner(con); set_bit(CONNECTING, &con->state); clear_bit(NEGOTIATING, &con->state); -- GitLab From 29e1a95eb5de3d6745e6eebb7d22dfaea437783c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:38 -0500 Subject: [PATCH 1049/1799] ceph: messenger: rework prepare_connect_authorizer() (cherry picked from commit b1c6b9803f5491e94041e6da96bc9dec3870e792) Change prepare_connect_authorizer() so it returns without dropping the connection mutex if the connection has no get_authorizer method. Use the symbolic CEPH_AUTH_UNKNOWN instead of 0 when assigning authorization protocols. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 8e76936a8c13..09409a3d9500 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -656,19 +656,29 @@ static void prepare_write_keepalive(struct ceph_connection *con) static int prepare_connect_authorizer(struct ceph_connection *con) { void *auth_buf; - int auth_len = 0; - int auth_protocol = 0; + int auth_len; + int auth_protocol; + + if (!con->ops->get_authorizer) { + con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN; + con->out_connect.authorizer_len = 0; + + return 0; + } + + /* Can't hold the mutex while getting authorizer */ mutex_unlock(&con->mutex); - if (con->ops->get_authorizer) - con->ops->get_authorizer(con, &auth_buf, &auth_len, - &auth_protocol, &con->auth_reply_buf, - &con->auth_reply_buf_len, - con->auth_retry); + + auth_buf = NULL; + auth_len = 0; + auth_protocol = CEPH_AUTH_UNKNOWN; + con->ops->get_authorizer(con, &auth_buf, &auth_len, &auth_protocol, + &con->auth_reply_buf, &con->auth_reply_buf_len, + con->auth_retry); mutex_lock(&con->mutex); - if (test_bit(CLOSED, &con->state) || - test_bit(OPENING, &con->state)) + if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state)) return -EAGAIN; con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol); -- GitLab From 33f0577a991d6d00805450ea29da5a91f6acd1a8 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:38 -0500 Subject: [PATCH 1050/1799] ceph: messenger: check return from get_authorizer (cherry picked from commit ed96af646011412c2bf1ffe860db170db355fae5) In prepare_connect_authorizer(), a connection's get_authorizer method is called but ignores its return value. This function can return an error, so check for it and return it if that ever occurs. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 09409a3d9500..e0532d5b22f5 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -658,6 +658,7 @@ static int prepare_connect_authorizer(struct ceph_connection *con) void *auth_buf; int auth_len; int auth_protocol; + int ret; if (!con->ops->get_authorizer) { con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN; @@ -673,11 +674,14 @@ static int prepare_connect_authorizer(struct ceph_connection *con) auth_buf = NULL; auth_len = 0; auth_protocol = CEPH_AUTH_UNKNOWN; - con->ops->get_authorizer(con, &auth_buf, &auth_len, &auth_protocol, - &con->auth_reply_buf, &con->auth_reply_buf_len, - con->auth_retry); + ret = con->ops->get_authorizer(con, &auth_buf, &auth_len, + &auth_protocol, &con->auth_reply_buf, + &con->auth_reply_buf_len, con->auth_retry); mutex_lock(&con->mutex); + if (ret) + return ret; + if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state)) return -EAGAIN; -- GitLab From 0f56a54fced6bee6e56a8b84f9adb65a41032866 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:38 -0500 Subject: [PATCH 1051/1799] ceph: define ceph_auth_handshake type (cherry picked from commit 6c4a19158b96ea1fb8acbe0c1d5493d9dcd2f147) The definitions for the ceph_mds_session and ceph_osd both contain five fields related only to "authorizers." Encapsulate those fields into their own struct type, allowing for better isolation in some upcoming patches. Fix the #includes in "linux/ceph/osd_client.h" to lay out their more complete canonical path. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/mds_client.c | 32 ++++++++++++++++---------------- fs/ceph/mds_client.h | 5 ++--- include/linux/ceph/auth.h | 8 ++++++++ include/linux/ceph/osd_client.h | 11 +++++------ net/ceph/osd_client.c | 32 ++++++++++++++++---------------- 5 files changed, 47 insertions(+), 41 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 89971e137aab..42013c620488 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -334,10 +334,10 @@ void ceph_put_mds_session(struct ceph_mds_session *s) dout("mdsc put_session %p %d -> %d\n", s, atomic_read(&s->s_ref), atomic_read(&s->s_ref)-1); if (atomic_dec_and_test(&s->s_ref)) { - if (s->s_authorizer) + if (s->s_auth.authorizer) s->s_mdsc->fsc->client->monc.auth->ops->destroy_authorizer( s->s_mdsc->fsc->client->monc.auth, - s->s_authorizer); + s->s_auth.authorizer); kfree(s); } } @@ -3404,29 +3404,29 @@ static int get_authorizer(struct ceph_connection *con, struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth; int ret = 0; - if (force_new && s->s_authorizer) { - ac->ops->destroy_authorizer(ac, s->s_authorizer); - s->s_authorizer = NULL; + if (force_new && s->s_auth.authorizer) { + ac->ops->destroy_authorizer(ac, s->s_auth.authorizer); + s->s_auth.authorizer = NULL; } - if (s->s_authorizer == NULL) { + if (s->s_auth.authorizer == NULL) { if (ac->ops->create_authorizer) { ret = ac->ops->create_authorizer( ac, CEPH_ENTITY_TYPE_MDS, - &s->s_authorizer, - &s->s_authorizer_buf, - &s->s_authorizer_buf_len, - &s->s_authorizer_reply_buf, - &s->s_authorizer_reply_buf_len); + &s->s_auth.authorizer, + &s->s_auth.authorizer_buf, + &s->s_auth.authorizer_buf_len, + &s->s_auth.authorizer_reply_buf, + &s->s_auth.authorizer_reply_buf_len); if (ret) return ret; } } *proto = ac->protocol; - *buf = s->s_authorizer_buf; - *len = s->s_authorizer_buf_len; - *reply_buf = s->s_authorizer_reply_buf; - *reply_len = s->s_authorizer_reply_buf_len; + *buf = s->s_auth.authorizer_buf; + *len = s->s_auth.authorizer_buf_len; + *reply_buf = s->s_auth.authorizer_reply_buf; + *reply_len = s->s_auth.authorizer_reply_buf_len; return 0; } @@ -3437,7 +3437,7 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len) struct ceph_mds_client *mdsc = s->s_mdsc; struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth; - return ac->ops->verify_authorizer_reply(ac, s->s_authorizer, len); + return ac->ops->verify_authorizer_reply(ac, s->s_auth.authorizer, len); } static int invalidate_authorizer(struct ceph_connection *con) diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 8c7c04ebb595..dd26846dd71d 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -11,6 +11,7 @@ #include #include #include +#include /* * Some lock dependencies: @@ -113,9 +114,7 @@ struct ceph_mds_session { struct ceph_connection s_con; - struct ceph_authorizer *s_authorizer; - void *s_authorizer_buf, *s_authorizer_reply_buf; - size_t s_authorizer_buf_len, s_authorizer_reply_buf_len; + struct ceph_auth_handshake s_auth; /* protected by s_gen_ttl_lock */ spinlock_t s_gen_ttl_lock; diff --git a/include/linux/ceph/auth.h b/include/linux/ceph/auth.h index aa13392a7efb..5b774d141e09 100644 --- a/include/linux/ceph/auth.h +++ b/include/linux/ceph/auth.h @@ -14,6 +14,14 @@ struct ceph_auth_client; struct ceph_authorizer; +struct ceph_auth_handshake { + struct ceph_authorizer *authorizer; + void *authorizer_buf; + size_t authorizer_buf_len; + void *authorizer_reply_buf; + size_t authorizer_reply_buf_len; +}; + struct ceph_auth_client_ops { const char *name; diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h index 7c05ac202d90..cedfb1a8434a 100644 --- a/include/linux/ceph/osd_client.h +++ b/include/linux/ceph/osd_client.h @@ -6,9 +6,10 @@ #include #include -#include "types.h" -#include "osdmap.h" -#include "messenger.h" +#include +#include +#include +#include /* * Maximum object name size @@ -40,9 +41,7 @@ struct ceph_osd { struct list_head o_requests; struct list_head o_linger_requests; struct list_head o_osd_lru; - struct ceph_authorizer *o_authorizer; - void *o_authorizer_buf, *o_authorizer_reply_buf; - size_t o_authorizer_buf_len, o_authorizer_reply_buf_len; + struct ceph_auth_handshake o_auth; unsigned long lru_ttl; int o_marked_for_keepalive; struct list_head o_keepalive_item; diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index daa2716a0c30..66b09d6a1531 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -667,8 +667,8 @@ static void put_osd(struct ceph_osd *osd) if (atomic_dec_and_test(&osd->o_ref)) { struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth; - if (osd->o_authorizer) - ac->ops->destroy_authorizer(ac, osd->o_authorizer); + if (osd->o_auth.authorizer) + ac->ops->destroy_authorizer(ac, osd->o_auth.authorizer); kfree(osd); } } @@ -2117,27 +2117,27 @@ static int get_authorizer(struct ceph_connection *con, struct ceph_auth_client *ac = osdc->client->monc.auth; int ret = 0; - if (force_new && o->o_authorizer) { - ac->ops->destroy_authorizer(ac, o->o_authorizer); - o->o_authorizer = NULL; + if (force_new && o->o_auth.authorizer) { + ac->ops->destroy_authorizer(ac, o->o_auth.authorizer); + o->o_auth.authorizer = NULL; } - if (o->o_authorizer == NULL) { + if (o->o_auth.authorizer == NULL) { ret = ac->ops->create_authorizer( ac, CEPH_ENTITY_TYPE_OSD, - &o->o_authorizer, - &o->o_authorizer_buf, - &o->o_authorizer_buf_len, - &o->o_authorizer_reply_buf, - &o->o_authorizer_reply_buf_len); + &o->o_auth.authorizer, + &o->o_auth.authorizer_buf, + &o->o_auth.authorizer_buf_len, + &o->o_auth.authorizer_reply_buf, + &o->o_auth.authorizer_reply_buf_len); if (ret) return ret; } *proto = ac->protocol; - *buf = o->o_authorizer_buf; - *len = o->o_authorizer_buf_len; - *reply_buf = o->o_authorizer_reply_buf; - *reply_len = o->o_authorizer_reply_buf_len; + *buf = o->o_auth.authorizer_buf; + *len = o->o_auth.authorizer_buf_len; + *reply_buf = o->o_auth.authorizer_reply_buf; + *reply_len = o->o_auth.authorizer_reply_buf_len; return 0; } @@ -2148,7 +2148,7 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len) struct ceph_osd_client *osdc = o->o_osdc; struct ceph_auth_client *ac = osdc->client->monc.auth; - return ac->ops->verify_authorizer_reply(ac, o->o_authorizer, len); + return ac->ops->verify_authorizer_reply(ac, o->o_auth.authorizer, len); } static int invalidate_authorizer(struct ceph_connection *con) -- GitLab From 018a2a13f3cb5e205618b1357124ff25eb3a8223 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:39 -0500 Subject: [PATCH 1052/1799] ceph: messenger: reduce args to create_authorizer (cherry picked from commit 74f1869f76d043bad12ec03b4d5f04a8c3d1f157) Make use of the new ceph_auth_handshake structure in order to reduce the number of arguments passed to the create_authorizor method in ceph_auth_client_ops. Use a local variable of that type as a shorthand in the get_authorizer method definitions. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/mds_client.c | 27 ++++++++++++--------------- include/linux/ceph/auth.h | 4 +--- net/ceph/auth_none.c | 15 +++++++-------- net/ceph/auth_x.c | 15 +++++++-------- net/ceph/osd_client.c | 28 ++++++++++++---------------- 5 files changed, 39 insertions(+), 50 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 42013c620488..b71ffd2c8094 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -3402,31 +3402,28 @@ static int get_authorizer(struct ceph_connection *con, struct ceph_mds_session *s = con->private; struct ceph_mds_client *mdsc = s->s_mdsc; struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth; + struct ceph_auth_handshake *auth = &s->s_auth; int ret = 0; - if (force_new && s->s_auth.authorizer) { - ac->ops->destroy_authorizer(ac, s->s_auth.authorizer); - s->s_auth.authorizer = NULL; + if (force_new && auth->authorizer) { + ac->ops->destroy_authorizer(ac, auth->authorizer); + auth->authorizer = NULL; } - if (s->s_auth.authorizer == NULL) { + if (auth->authorizer == NULL) { if (ac->ops->create_authorizer) { - ret = ac->ops->create_authorizer( - ac, CEPH_ENTITY_TYPE_MDS, - &s->s_auth.authorizer, - &s->s_auth.authorizer_buf, - &s->s_auth.authorizer_buf_len, - &s->s_auth.authorizer_reply_buf, - &s->s_auth.authorizer_reply_buf_len); + ret = ac->ops->create_authorizer(ac, + CEPH_ENTITY_TYPE_MDS, auth); if (ret) return ret; } } *proto = ac->protocol; - *buf = s->s_auth.authorizer_buf; - *len = s->s_auth.authorizer_buf_len; - *reply_buf = s->s_auth.authorizer_reply_buf; - *reply_len = s->s_auth.authorizer_reply_buf_len; + *buf = auth->authorizer_buf; + *len = auth->authorizer_buf_len; + *reply_buf = auth->authorizer_reply_buf; + *reply_len = auth->authorizer_reply_buf_len; + return 0; } diff --git a/include/linux/ceph/auth.h b/include/linux/ceph/auth.h index 5b774d141e09..d4080f309b56 100644 --- a/include/linux/ceph/auth.h +++ b/include/linux/ceph/auth.h @@ -51,9 +51,7 @@ struct ceph_auth_client_ops { * the response to authenticate the service. */ int (*create_authorizer)(struct ceph_auth_client *ac, int peer_type, - struct ceph_authorizer **a, - void **buf, size_t *len, - void **reply_buf, size_t *reply_len); + struct ceph_auth_handshake *auth); int (*verify_authorizer_reply)(struct ceph_auth_client *ac, struct ceph_authorizer *a, size_t len); void (*destroy_authorizer)(struct ceph_auth_client *ac, diff --git a/net/ceph/auth_none.c b/net/ceph/auth_none.c index 214c2bb43d62..925ca583c09c 100644 --- a/net/ceph/auth_none.c +++ b/net/ceph/auth_none.c @@ -59,9 +59,7 @@ static int handle_reply(struct ceph_auth_client *ac, int result, */ static int ceph_auth_none_create_authorizer( struct ceph_auth_client *ac, int peer_type, - struct ceph_authorizer **a, - void **buf, size_t *len, - void **reply_buf, size_t *reply_len) + struct ceph_auth_handshake *auth) { struct ceph_auth_none_info *ai = ac->private; struct ceph_none_authorizer *au = &ai->au; @@ -82,11 +80,12 @@ static int ceph_auth_none_create_authorizer( dout("built authorizer len %d\n", au->buf_len); } - *a = (struct ceph_authorizer *)au; - *buf = au->buf; - *len = au->buf_len; - *reply_buf = au->reply_buf; - *reply_len = sizeof(au->reply_buf); + auth->authorizer = (struct ceph_authorizer *) au; + auth->authorizer_buf = au->buf; + auth->authorizer_buf_len = au->buf_len; + auth->authorizer_reply_buf = au->reply_buf; + auth->authorizer_reply_buf_len = sizeof (au->reply_buf); + return 0; bad2: diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index 1587dc6010c6..a16bf14eb027 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c @@ -526,9 +526,7 @@ static int ceph_x_handle_reply(struct ceph_auth_client *ac, int result, static int ceph_x_create_authorizer( struct ceph_auth_client *ac, int peer_type, - struct ceph_authorizer **a, - void **buf, size_t *len, - void **reply_buf, size_t *reply_len) + struct ceph_auth_handshake *auth) { struct ceph_x_authorizer *au; struct ceph_x_ticket_handler *th; @@ -548,11 +546,12 @@ static int ceph_x_create_authorizer( return ret; } - *a = (struct ceph_authorizer *)au; - *buf = au->buf->vec.iov_base; - *len = au->buf->vec.iov_len; - *reply_buf = au->reply_buf; - *reply_len = sizeof(au->reply_buf); + auth->authorizer = (struct ceph_authorizer *) au; + auth->authorizer_buf = au->buf->vec.iov_base; + auth->authorizer_buf_len = au->buf->vec.iov_len; + auth->authorizer_reply_buf = au->reply_buf; + auth->authorizer_reply_buf_len = sizeof (au->reply_buf); + return 0; } diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 66b09d6a1531..2da4b9e97dc1 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -2115,29 +2115,25 @@ static int get_authorizer(struct ceph_connection *con, struct ceph_osd *o = con->private; struct ceph_osd_client *osdc = o->o_osdc; struct ceph_auth_client *ac = osdc->client->monc.auth; + struct ceph_auth_handshake *auth = &o->o_auth; int ret = 0; - if (force_new && o->o_auth.authorizer) { - ac->ops->destroy_authorizer(ac, o->o_auth.authorizer); - o->o_auth.authorizer = NULL; - } - if (o->o_auth.authorizer == NULL) { - ret = ac->ops->create_authorizer( - ac, CEPH_ENTITY_TYPE_OSD, - &o->o_auth.authorizer, - &o->o_auth.authorizer_buf, - &o->o_auth.authorizer_buf_len, - &o->o_auth.authorizer_reply_buf, - &o->o_auth.authorizer_reply_buf_len); + if (force_new && auth->authorizer) { + ac->ops->destroy_authorizer(ac, auth->authorizer); + auth->authorizer = NULL; + } + if (auth->authorizer == NULL) { + ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, auth); if (ret) return ret; } *proto = ac->protocol; - *buf = o->o_auth.authorizer_buf; - *len = o->o_auth.authorizer_buf_len; - *reply_buf = o->o_auth.authorizer_reply_buf; - *reply_len = o->o_auth.authorizer_reply_buf_len; + *buf = auth->authorizer_buf; + *len = auth->authorizer_buf_len; + *reply_buf = auth->authorizer_reply_buf; + *reply_len = auth->authorizer_reply_buf_len; + return 0; } -- GitLab From 83d28f7956228e0dd1774aed1096392d3bfc0597 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:39 -0500 Subject: [PATCH 1053/1799] ceph: ensure auth ops are defined before use (cherry picked from commit a255651d4cad89f1a606edd36135af892ada4f20) In the create_authorizer method for both the mds and osd clients, the auth_client->ops pointer is blindly dereferenced. There is no obvious guarantee that this pointer has been assigned. And furthermore, even if the ops pointer is non-null there is definitely no guarantee that the create_authorizer or destroy_authorizer methods are defined. Add checks in both routines to make sure they are defined (non-null) before use. Add similar checks in a few other spots in these files while we're at it. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/mds_client.c | 14 ++++++-------- net/ceph/osd_client.c | 15 ++++++++++----- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index b71ffd2c8094..462281742aef 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -3406,16 +3406,14 @@ static int get_authorizer(struct ceph_connection *con, int ret = 0; if (force_new && auth->authorizer) { - ac->ops->destroy_authorizer(ac, auth->authorizer); + if (ac->ops && ac->ops->destroy_authorizer) + ac->ops->destroy_authorizer(ac, auth->authorizer); auth->authorizer = NULL; } - if (auth->authorizer == NULL) { - if (ac->ops->create_authorizer) { - ret = ac->ops->create_authorizer(ac, - CEPH_ENTITY_TYPE_MDS, auth); - if (ret) - return ret; - } + if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) { + ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS, auth); + if (ret) + return ret; } *proto = ac->protocol; diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 2da4b9e97dc1..f640bdf027e7 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -664,10 +664,10 @@ static void put_osd(struct ceph_osd *osd) { dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref), atomic_read(&osd->o_ref) - 1); - if (atomic_dec_and_test(&osd->o_ref)) { + if (atomic_dec_and_test(&osd->o_ref) && osd->o_auth.authorizer) { struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth; - if (osd->o_auth.authorizer) + if (ac->ops && ac->ops->destroy_authorizer) ac->ops->destroy_authorizer(ac, osd->o_auth.authorizer); kfree(osd); } @@ -2119,10 +2119,11 @@ static int get_authorizer(struct ceph_connection *con, int ret = 0; if (force_new && auth->authorizer) { - ac->ops->destroy_authorizer(ac, auth->authorizer); + if (ac->ops && ac->ops->destroy_authorizer) + ac->ops->destroy_authorizer(ac, auth->authorizer); auth->authorizer = NULL; } - if (auth->authorizer == NULL) { + if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) { ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, auth); if (ret) return ret; @@ -2144,6 +2145,10 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len) struct ceph_osd_client *osdc = o->o_osdc; struct ceph_auth_client *ac = osdc->client->monc.auth; + /* + * XXX If ac->ops or ac->ops->verify_authorizer_reply is null, + * XXX which do we do: succeed or fail? + */ return ac->ops->verify_authorizer_reply(ac, o->o_auth.authorizer, len); } @@ -2153,7 +2158,7 @@ static int invalidate_authorizer(struct ceph_connection *con) struct ceph_osd_client *osdc = o->o_osdc; struct ceph_auth_client *ac = osdc->client->monc.auth; - if (ac->ops->invalidate_authorizer) + if (ac->ops && ac->ops->invalidate_authorizer) ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD); return ceph_monc_validate_auth(&osdc->client->monc); -- GitLab From 4f33c7ed3796a5078cd9eef0d3af4ebf8f7e1b99 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:39 -0500 Subject: [PATCH 1054/1799] ceph: have get_authorizer methods return pointers (cherry picked from commit a3530df33eb91d787d08c7383a0a9982690e42d0) Have the get_authorizer auth_client method return a ceph_auth pointer rather than an integer, pointer-encoding any returned error value. This is to pave the way for making use of the returned value in an upcoming patch. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/mds_client.c | 20 +++++++++++++------- include/linux/ceph/messenger.h | 8 +++++--- net/ceph/messenger.c | 8 ++++---- net/ceph/osd_client.c | 19 ++++++++++++------- 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 462281742aef..67938a9d049b 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -3395,15 +3395,20 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg) /* * authentication */ -static int get_authorizer(struct ceph_connection *con, - void **buf, int *len, int *proto, - void **reply_buf, int *reply_len, int force_new) + +/* + * Note: returned pointer is the address of a structure that's + * managed separately. Caller must *not* attempt to free it. + */ +static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con, + void **buf, int *len, int *proto, + void **reply_buf, int *reply_len, + int force_new) { struct ceph_mds_session *s = con->private; struct ceph_mds_client *mdsc = s->s_mdsc; struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth; struct ceph_auth_handshake *auth = &s->s_auth; - int ret = 0; if (force_new && auth->authorizer) { if (ac->ops && ac->ops->destroy_authorizer) @@ -3411,9 +3416,10 @@ static int get_authorizer(struct ceph_connection *con, auth->authorizer = NULL; } if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) { - ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS, auth); + int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS, + auth); if (ret) - return ret; + return ERR_PTR(ret); } *proto = ac->protocol; @@ -3422,7 +3428,7 @@ static int get_authorizer(struct ceph_connection *con, *reply_buf = auth->authorizer_reply_buf; *reply_len = auth->authorizer_reply_buf_len; - return 0; + return auth; } diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 3bff047f6b0f..b10b55f8f301 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -25,9 +25,11 @@ struct ceph_connection_operations { void (*dispatch) (struct ceph_connection *con, struct ceph_msg *m); /* authorize an outgoing connection */ - int (*get_authorizer) (struct ceph_connection *con, - void **buf, int *len, int *proto, - void **reply_buf, int *reply_len, int force_new); + struct ceph_auth_handshake *(*get_authorizer) ( + struct ceph_connection *con, + void **buf, int *len, int *proto, + void **reply_buf, int *reply_len, + int force_new); int (*verify_authorizer_reply) (struct ceph_connection *con, int len); int (*invalidate_authorizer)(struct ceph_connection *con); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index e0532d5b22f5..ac27a2c0694a 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -658,7 +658,7 @@ static int prepare_connect_authorizer(struct ceph_connection *con) void *auth_buf; int auth_len; int auth_protocol; - int ret; + struct ceph_auth_handshake *auth; if (!con->ops->get_authorizer) { con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN; @@ -674,13 +674,13 @@ static int prepare_connect_authorizer(struct ceph_connection *con) auth_buf = NULL; auth_len = 0; auth_protocol = CEPH_AUTH_UNKNOWN; - ret = con->ops->get_authorizer(con, &auth_buf, &auth_len, + auth = con->ops->get_authorizer(con, &auth_buf, &auth_len, &auth_protocol, &con->auth_reply_buf, &con->auth_reply_buf_len, con->auth_retry); mutex_lock(&con->mutex); - if (ret) - return ret; + if (IS_ERR(auth)) + return PTR_ERR(auth); if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state)) return -EAGAIN; diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index f640bdf027e7..fa74ae0ea910 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -2108,15 +2108,19 @@ static void put_osd_con(struct ceph_connection *con) /* * authentication */ -static int get_authorizer(struct ceph_connection *con, - void **buf, int *len, int *proto, - void **reply_buf, int *reply_len, int force_new) +/* + * Note: returned pointer is the address of a structure that's + * managed separately. Caller must *not* attempt to free it. + */ +static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con, + void **buf, int *len, int *proto, + void **reply_buf, int *reply_len, + int force_new) { struct ceph_osd *o = con->private; struct ceph_osd_client *osdc = o->o_osdc; struct ceph_auth_client *ac = osdc->client->monc.auth; struct ceph_auth_handshake *auth = &o->o_auth; - int ret = 0; if (force_new && auth->authorizer) { if (ac->ops && ac->ops->destroy_authorizer) @@ -2124,9 +2128,10 @@ static int get_authorizer(struct ceph_connection *con, auth->authorizer = NULL; } if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) { - ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, auth); + int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, + auth); if (ret) - return ret; + return ERR_PTR(ret); } *proto = ac->protocol; @@ -2135,7 +2140,7 @@ static int get_authorizer(struct ceph_connection *con, *reply_buf = auth->authorizer_reply_buf; *reply_len = auth->authorizer_reply_buf_len; - return 0; + return auth; } -- GitLab From ed35fbcd3cf73dfbff59bf8c20c772925562bc45 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:39 -0500 Subject: [PATCH 1055/1799] ceph: use info returned by get_authorizer (cherry picked from commit 8f43fb53894079bf0caab6e348ceaffe7adc651a) Rather than passing a bunch of arguments to be filled in with the content of the ceph_auth_handshake buffer now returned by the get_authorizer method, just use the returned information in the caller, and drop the unnecessary arguments. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/mds_client.c | 9 +-------- include/linux/ceph/messenger.h | 4 +--- net/ceph/messenger.c | 13 +++++++------ net/ceph/osd_client.c | 9 +-------- 4 files changed, 10 insertions(+), 25 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 67938a9d049b..200bc87eceb1 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -3401,9 +3401,7 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg) * managed separately. Caller must *not* attempt to free it. */ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con, - void **buf, int *len, int *proto, - void **reply_buf, int *reply_len, - int force_new) + int *proto, int force_new) { struct ceph_mds_session *s = con->private; struct ceph_mds_client *mdsc = s->s_mdsc; @@ -3421,12 +3419,7 @@ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con, if (ret) return ERR_PTR(ret); } - *proto = ac->protocol; - *buf = auth->authorizer_buf; - *len = auth->authorizer_buf_len; - *reply_buf = auth->authorizer_reply_buf; - *reply_len = auth->authorizer_reply_buf_len; return auth; } diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index b10b55f8f301..2521a95fa6d9 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -27,9 +27,7 @@ struct ceph_connection_operations { /* authorize an outgoing connection */ struct ceph_auth_handshake *(*get_authorizer) ( struct ceph_connection *con, - void **buf, int *len, int *proto, - void **reply_buf, int *reply_len, - int force_new); + int *proto, int force_new); int (*verify_authorizer_reply) (struct ceph_connection *con, int len); int (*invalidate_authorizer)(struct ceph_connection *con); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index ac27a2c0694a..6d82c1a1a89b 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -671,20 +671,21 @@ static int prepare_connect_authorizer(struct ceph_connection *con) mutex_unlock(&con->mutex); - auth_buf = NULL; - auth_len = 0; auth_protocol = CEPH_AUTH_UNKNOWN; - auth = con->ops->get_authorizer(con, &auth_buf, &auth_len, - &auth_protocol, &con->auth_reply_buf, - &con->auth_reply_buf_len, con->auth_retry); + auth = con->ops->get_authorizer(con, &auth_protocol, con->auth_retry); + mutex_lock(&con->mutex); if (IS_ERR(auth)) return PTR_ERR(auth); - if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state)) return -EAGAIN; + auth_buf = auth->authorizer_buf; + auth_len = auth->authorizer_buf_len; + con->auth_reply_buf = auth->authorizer_reply_buf; + con->auth_reply_buf_len = auth->authorizer_reply_buf_len; + con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol); con->out_connect.authorizer_len = cpu_to_le32(auth_len); diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index fa74ae0ea910..b7d633cc96a6 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -2113,9 +2113,7 @@ static void put_osd_con(struct ceph_connection *con) * managed separately. Caller must *not* attempt to free it. */ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con, - void **buf, int *len, int *proto, - void **reply_buf, int *reply_len, - int force_new) + int *proto, int force_new) { struct ceph_osd *o = con->private; struct ceph_osd_client *osdc = o->o_osdc; @@ -2133,12 +2131,7 @@ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con, if (ret) return ERR_PTR(ret); } - *proto = ac->protocol; - *buf = auth->authorizer_buf; - *len = auth->authorizer_buf_len; - *reply_buf = auth->authorizer_reply_buf; - *reply_len = auth->authorizer_reply_buf_len; return auth; } -- GitLab From 8d19055c84e89980a0e60604bd925bf7cf4cb9e4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:39 -0500 Subject: [PATCH 1056/1799] ceph: return pointer from prepare_connect_authorizer() (cherry picked from commit 729796be9190f57ca40ccca315e8ad34a1eb8fef) Change prepare_connect_authorizer() so it returns a pointer (or pointer-coded error). Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 6d82c1a1a89b..f92d564c1505 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -653,7 +653,7 @@ static void prepare_write_keepalive(struct ceph_connection *con) * Connection negotiation. */ -static int prepare_connect_authorizer(struct ceph_connection *con) +static struct ceph_auth_handshake *prepare_connect_authorizer(struct ceph_connection *con) { void *auth_buf; int auth_len; @@ -664,7 +664,7 @@ static int prepare_connect_authorizer(struct ceph_connection *con) con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN; con->out_connect.authorizer_len = 0; - return 0; + return NULL; } /* Can't hold the mutex while getting authorizer */ @@ -677,9 +677,9 @@ static int prepare_connect_authorizer(struct ceph_connection *con) mutex_lock(&con->mutex); if (IS_ERR(auth)) - return PTR_ERR(auth); + return auth; if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state)) - return -EAGAIN; + return ERR_PTR(-EAGAIN); auth_buf = auth->authorizer_buf; auth_len = auth->authorizer_buf_len; @@ -692,7 +692,7 @@ static int prepare_connect_authorizer(struct ceph_connection *con) if (auth_len) ceph_con_out_kvec_add(con, auth_len, auth_buf); - return 0; + return auth; } /* @@ -712,7 +712,7 @@ static int prepare_write_connect(struct ceph_connection *con) { unsigned global_seq = get_global_seq(con->msgr, 0); int proto; - int ret; + struct ceph_auth_handshake *auth; switch (con->peer_name.type) { case CEPH_ENTITY_TYPE_MON: @@ -739,9 +739,9 @@ static int prepare_write_connect(struct ceph_connection *con) con->out_connect.flags = 0; ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); - ret = prepare_connect_authorizer(con); - if (ret) - return ret; + auth = prepare_connect_authorizer(con); + if (IS_ERR(auth)) + return PTR_ERR(auth); con->out_more = 0; set_bit(WRITE_PENDING, &con->state); -- GitLab From 3f13447d2c90842c9ea5ceb6b4f8b8b7737f04da Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:39 -0500 Subject: [PATCH 1057/1799] ceph: rename prepare_connect_authorizer() (cherry picked from commit dac1e716c60161867a47745bca592987ca3a9cb2) Change the name of prepare_connect_authorizer(). The next patch is going to make this function no longer add anything to the connection's out_kvec, so it will no longer fit the pattern of the rest of the prepare_connect_*() functions. In addition, pass the address of a variable that will hold the authorization protocol to use. Move the assignment of that to the connection's out_connect structure into prepare_write_connect(). Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index f92d564c1505..bfddd87db788 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -653,11 +653,11 @@ static void prepare_write_keepalive(struct ceph_connection *con) * Connection negotiation. */ -static struct ceph_auth_handshake *prepare_connect_authorizer(struct ceph_connection *con) +static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection *con, + int *auth_proto) { void *auth_buf; int auth_len; - int auth_protocol; struct ceph_auth_handshake *auth; if (!con->ops->get_authorizer) { @@ -671,8 +671,7 @@ static struct ceph_auth_handshake *prepare_connect_authorizer(struct ceph_connec mutex_unlock(&con->mutex); - auth_protocol = CEPH_AUTH_UNKNOWN; - auth = con->ops->get_authorizer(con, &auth_protocol, con->auth_retry); + auth = con->ops->get_authorizer(con, auth_proto, con->auth_retry); mutex_lock(&con->mutex); @@ -686,7 +685,6 @@ static struct ceph_auth_handshake *prepare_connect_authorizer(struct ceph_connec con->auth_reply_buf = auth->authorizer_reply_buf; con->auth_reply_buf_len = auth->authorizer_reply_buf_len; - con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol); con->out_connect.authorizer_len = cpu_to_le32(auth_len); if (auth_len) @@ -712,6 +710,7 @@ static int prepare_write_connect(struct ceph_connection *con) { unsigned global_seq = get_global_seq(con->msgr, 0); int proto; + int auth_proto; struct ceph_auth_handshake *auth; switch (con->peer_name.type) { @@ -739,9 +738,11 @@ static int prepare_write_connect(struct ceph_connection *con) con->out_connect.flags = 0; ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); - auth = prepare_connect_authorizer(con); + auth_proto = CEPH_AUTH_UNKNOWN; + auth = get_connect_authorizer(con, &auth_proto); if (IS_ERR(auth)) return PTR_ERR(auth); + con->out_connect.authorizer_protocol = cpu_to_le32(auth_proto); con->out_more = 0; set_bit(WRITE_PENDING, &con->state); -- GitLab From 1d3df0e26616d97a798950eb5fb908b14b1839da Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 16 May 2012 15:16:39 -0500 Subject: [PATCH 1058/1799] ceph: add auth buf in prepare_write_connect() (cherry picked from commit 3da54776e2c0385c32d143fd497a7f40a88e29dd) Move the addition of the authorizer buffer to a connection's out_kvec out of get_connect_authorizer() and into its caller. This way, the caller--prepare_write_connect()--can avoid adding the connect header to out_kvec before it has been fully initialized. Prior to this patch, it was possible for a connect header to be sent over the wire before the authorizer protocol or buffer length fields were initialized. An authorizer buffer associated with that header could also be queued to send only after the connection header that describes it was on the wire. Fixes http://tracker.newdream.net/issues/2424 Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index bfddd87db788..1a80907282cc 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -656,8 +656,6 @@ static void prepare_write_keepalive(struct ceph_connection *con) static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection *con, int *auth_proto) { - void *auth_buf; - int auth_len; struct ceph_auth_handshake *auth; if (!con->ops->get_authorizer) { @@ -680,15 +678,9 @@ static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state)) return ERR_PTR(-EAGAIN); - auth_buf = auth->authorizer_buf; - auth_len = auth->authorizer_buf_len; con->auth_reply_buf = auth->authorizer_reply_buf; con->auth_reply_buf_len = auth->authorizer_reply_buf_len; - con->out_connect.authorizer_len = cpu_to_le32(auth_len); - - if (auth_len) - ceph_con_out_kvec_add(con, auth_len, auth_buf); return auth; } @@ -737,12 +729,20 @@ static int prepare_write_connect(struct ceph_connection *con) con->out_connect.protocol_version = cpu_to_le32(proto); con->out_connect.flags = 0; - ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); auth_proto = CEPH_AUTH_UNKNOWN; auth = get_connect_authorizer(con, &auth_proto); if (IS_ERR(auth)) return PTR_ERR(auth); + con->out_connect.authorizer_protocol = cpu_to_le32(auth_proto); + con->out_connect.authorizer_len = auth ? + cpu_to_le32(auth->authorizer_buf_len) : 0; + + ceph_con_out_kvec_add(con, sizeof (con->out_connect), + &con->out_connect); + if (auth && auth->authorizer_buf_len) + ceph_con_out_kvec_add(con, auth->authorizer_buf_len, + auth->authorizer_buf); con->out_more = 0; set_bit(WRITE_PENDING, &con->state); -- GitLab From 15ba38ebcee664a5a5de57300ee721e0d65b2dd5 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 16 May 2012 15:16:38 -0500 Subject: [PATCH 1059/1799] libceph: avoid unregistering osd request when not registered (cherry picked from commit 35f9f8a09e1e88e31bd34a1e645ca0e5f070dd5c) There is a race between two __unregister_request() callers: the reply path and the ceph_osdc_wait_request(). If we get a reply *and* the timeout expires at roughly the same time, both callers will try to unregister the request, and the second one will do bad things. Simply check if the request is still already unregistered; if so, return immediately and do nothing. Fixes http://tracker.newdream.net/issues/2420 Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/osd_client.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index b7d633cc96a6..b098e7b591f0 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -841,6 +841,12 @@ static void register_request(struct ceph_osd_client *osdc, static void __unregister_request(struct ceph_osd_client *osdc, struct ceph_osd_request *req) { + if (RB_EMPTY_NODE(&req->r_node)) { + dout("__unregister_request %p tid %lld not registered\n", + req, req->r_tid); + return; + } + dout("__unregister_request %p tid %lld\n", req, req->r_tid); rb_erase(&req->r_node, &osdc->requests); osdc->num_requests--; -- GitLab From 1c201dffa3f4ef8e53dca7bffb8987a43e3e9139 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 21 May 2012 09:45:23 -0700 Subject: [PATCH 1060/1799] libceph: fix pg_temp updates (cherry picked from commit 6bd9adbdf9ca6a052b0b7455ac67b925eb38cfad) Usually, we are adding pg_temp entries or removing them. Occasionally they update. In that case, osdmap_apply_incremental() was failing because the rbtree entry already exists. Fix by removing the existing entry before inserting a new one. Fixes http://tracker.newdream.net/issues/2446 Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/osdmap.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 29ad46ec9dcf..7173ad54d239 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -890,8 +890,12 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, pglen = ceph_decode_32(p); if (pglen) { - /* insert */ ceph_decode_need(p, end, pglen*sizeof(u32), bad); + + /* removing existing (if any) */ + (void) __remove_pg_mapping(&map->pg_temp, pgid); + + /* insert */ pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); if (!pg) { err = -ENOMEM; -- GitLab From 40971fcf1578d743cde0272ad20539f5ea34725a Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 4 Jun 2012 14:43:32 -0500 Subject: [PATCH 1061/1799] libceph: osd_client: don't drop reply reference too early (cherry picked from commit ab8cb34a4b2f60281a4b18b1f1ad23bc2313d91b) In ceph_osdc_release_request(), a reference to the r_reply message is dropped. But just after that, that same message is revoked if it was in use to receive an incoming reply. Reorder these so we are sure we hold a reference until we're actually done with the message. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 680584fab05efff732b5ae16ad601ba994d7b505) --- net/ceph/osd_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index b098e7b591f0..67ed1a58d940 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -139,8 +139,6 @@ void ceph_osdc_release_request(struct kref *kref) if (req->r_request) ceph_msg_put(req->r_request); - if (req->r_reply) - ceph_msg_put(req->r_reply); if (req->r_con_filling_msg) { dout("release_request revoking pages %p from con %p\n", req->r_pages, req->r_con_filling_msg); @@ -148,6 +146,8 @@ void ceph_osdc_release_request(struct kref *kref) req->r_reply); ceph_con_put(req->r_con_filling_msg); } + if (req->r_reply) + ceph_msg_put(req->r_reply); if (req->r_own_pages) ceph_release_page_vector(req->r_pages, req->r_num_pages); -- GitLab From acecca48781a79040dca822cf96d505904c282c3 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 31 May 2012 20:22:18 -0700 Subject: [PATCH 1062/1799] libceph: use con get/put ops from osd_client (cherry picked from commit 0d47766f14211a73eaf54cab234db134ece79f49) There were a few direct calls to ceph_con_{get,put}() instead of the con ops from osd_client.c. This is a bug since those ops aren't defined to be ceph_con_get/put. This breaks refcounting on the ceph_osd structs that contain the ceph_connections, and could lead to all manner of strangeness. The purpose of the ->get and ->put methods in a ceph connection are to allow the connection to indicate it has a reference to something external to the messaging system, *not* to indicate something external has a reference to the connection. [elder@inktank.com: added that last sentence] Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 88ed6ea0b295f8e2383d599a04027ec596cdf97b) --- net/ceph/osd_client.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 67ed1a58d940..f4e2a4665d9b 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -144,7 +144,7 @@ void ceph_osdc_release_request(struct kref *kref) req->r_pages, req->r_con_filling_msg); ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply); - ceph_con_put(req->r_con_filling_msg); + req->r_con_filling_msg->ops->put(req->r_con_filling_msg); } if (req->r_reply) ceph_msg_put(req->r_reply); @@ -1216,7 +1216,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, if (req->r_con_filling_msg == con && req->r_reply == msg) { dout(" dropping con_filling_msg ref %p\n", con); req->r_con_filling_msg = NULL; - ceph_con_put(con); + con->ops->put(con); } if (!req->r_got_reply) { @@ -2028,7 +2028,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, dout("get_reply revoking msg %p from old con %p\n", req->r_reply, req->r_con_filling_msg); ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply); - ceph_con_put(req->r_con_filling_msg); + req->r_con_filling_msg->ops->put(req->r_con_filling_msg); req->r_con_filling_msg = NULL; } @@ -2063,7 +2063,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, #endif } *skip = 0; - req->r_con_filling_msg = ceph_con_get(con); + req->r_con_filling_msg = con->ops->get(con); dout("get_reply tid %lld %p\n", tid, m); out: -- GitLab From 576e428b246271f0f078079c68a9f11679c7db8a Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Wed, 6 Jun 2012 19:35:55 -0500 Subject: [PATCH 1063/1799] rbd: Clear ceph_msg->bio_iter for retransmitted message (cherry picked from commit 43643528cce60ca184fe8197efa8e8da7c89a037) (cherry picked from commit b132cf4c733f91bb4dd2277ea049243cf16e8b66) The bug can cause NULL pointer dereference in write_partial_msg_pages Signed-off-by: Zheng Yan Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 1a80907282cc..375ae3953e25 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -563,6 +563,10 @@ static void prepare_write_message(struct ceph_connection *con) m->hdr.seq = cpu_to_le64(++con->out_seq); m->needs_out_seq = false; } +#ifdef CONFIG_BLOCK + else + m->bio_iter = NULL; +#endif dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n", m, con->out_seq, le16_to_cpu(m->hdr.type), -- GitLab From 21cbad59b07693104dda76ee4afef41302b2b8fb Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Sun, 10 Jun 2012 20:43:56 -0700 Subject: [PATCH 1064/1799] libceph: flush msgr queue during mon_client shutdown (cherry picked from commit f3dea7edd3d449fe7a6d402c1ce56a294b985261) (cherry picked from commit 642c0dbde32f34baa7886e988a067089992adc8f) We need to flush the msgr workqueue during mon_client shutdown to ensure that any work affecting our embedded ceph_connection is finished so that we can be safely destroyed. Previously, we were flushing the work queue after osd_client shutdown and before mon_client shutdown to ensure that any osd connection refs to authorizers are flushed. Remove the redundant flush, and document in the comment that the mon_client flush is needed to cover that case as well. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/ceph_common.c | 7 ------- net/ceph/mon_client.c | 8 ++++++++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index cc913193d992..5dedac58faf4 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -504,13 +504,6 @@ void ceph_destroy_client(struct ceph_client *client) /* unmount */ ceph_osdc_stop(&client->osdc); - /* - * make sure osd connections close out before destroying the - * auth module, which is needed to free those connections' - * ceph_authorizers. - */ - ceph_msgr_flush(); - ceph_monc_stop(&client->monc); ceph_debugfs_client_cleanup(client); diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 1845cde26227..852dbb4a4e6b 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -847,6 +847,14 @@ void ceph_monc_stop(struct ceph_mon_client *monc) mutex_unlock(&monc->mutex); + /* + * flush msgr queue before we destroy ourselves to ensure that: + * - any work that references our embedded con is finished. + * - any osd_client or other work that may reference an authorizer + * finishes before we shut down the auth subsystem. + */ + ceph_msgr_flush(); + ceph_auth_destroy(monc->auth); ceph_msg_put(monc->m_auth); -- GitLab From 49da293c7dc4401c2c7963a2c70f633b1c8fa8c5 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 10 Jul 2012 11:53:34 -0700 Subject: [PATCH 1065/1799] libceph: fix messenger retry (cherry picked from commit 5bdca4e0768d3e0f4efa43d9a2cc8210aeb91ab9) In ancient times, the messenger could both initiate and accept connections. An artifact if that was data structures to store/process an incoming ceph_msg_connect request and send an outgoing ceph_msg_connect_reply. Sadly, the negotiation code was referencing those structures and ignoring important information (like the peer's connect_seq) from the correct ones. Among other things, this fixes tight reconnect loops where the server sends RETRY_SESSION and we (the client) retries with the same connect_seq as last time. This bug pretty easily triggered by injecting socket failures on the MDS and running some fs workload like workunits/direct_io/test_sync_io. Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 12 ++---------- net/ceph/messenger.c | 12 ++++++------ 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 2521a95fa6d9..44c87e731e9d 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -163,16 +163,8 @@ struct ceph_connection { /* connection negotiation temps */ char in_banner[CEPH_BANNER_MAX_LEN]; - union { - struct { /* outgoing connection */ - struct ceph_msg_connect out_connect; - struct ceph_msg_connect_reply in_reply; - }; - struct { /* incoming */ - struct ceph_msg_connect in_connect; - struct ceph_msg_connect_reply out_reply; - }; - }; + struct ceph_msg_connect out_connect; + struct ceph_msg_connect_reply in_reply; struct ceph_entity_addr actual_peer_addr; /* message out temps */ diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 375ae3953e25..0e270166f72f 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1423,7 +1423,7 @@ static int process_connect(struct ceph_connection *con) * dropped messages. */ dout("process_connect got RESET peer seq %u\n", - le32_to_cpu(con->in_connect.connect_seq)); + le32_to_cpu(con->in_reply.connect_seq)); pr_err("%s%lld %s connection reset\n", ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr)); @@ -1450,10 +1450,10 @@ static int process_connect(struct ceph_connection *con) * If we sent a smaller connect_seq than the peer has, try * again with a larger value. */ - dout("process_connect got RETRY my seq = %u, peer_seq = %u\n", + dout("process_connect got RETRY_SESSION my seq %u, peer %u\n", le32_to_cpu(con->out_connect.connect_seq), - le32_to_cpu(con->in_connect.connect_seq)); - con->connect_seq = le32_to_cpu(con->in_connect.connect_seq); + le32_to_cpu(con->in_reply.connect_seq)); + con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); ceph_con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) @@ -1468,9 +1468,9 @@ static int process_connect(struct ceph_connection *con) */ dout("process_connect got RETRY_GLOBAL my %u peer_gseq %u\n", con->peer_global_seq, - le32_to_cpu(con->in_connect.global_seq)); + le32_to_cpu(con->in_reply.global_seq)); get_global_seq(con->msgr, - le32_to_cpu(con->in_connect.global_seq)); + le32_to_cpu(con->in_reply.global_seq)); ceph_con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) -- GitLab From 095cb2142dfb10daea5a3351ed9646d3178a6823 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 4 Apr 2012 13:35:44 -0500 Subject: [PATCH 1066/1799] rbd: don't hold spinlock during messenger flush (cherry picked from commit cd9d9f5df6098c50726200d4185e9e8da32785b3) A recent change made changes to the rbd_client_list be protected by a spinlock. Unfortunately in rbd_put_client(), the lock is taken before possibly dropping the last reference to an rbd_client, and on the last reference that eventually calls flush_workqueue() which can sleep. The problem was flagged by a debug spinlock warning: BUG: spinlock wrong CPU on CPU#3, rbd/27814 The solution is to move the spinlock acquisition and release inside rbd_client_release(), which is the spot where it's really needed for protecting the removal of the rbd_client from the client list. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- drivers/block/rbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 013c7a549fb6..c1f770131654 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -450,7 +450,9 @@ static void rbd_client_release(struct kref *kref) struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref); dout("rbd_release_client %p\n", rbdc); + spin_lock(&rbd_client_list_lock); list_del(&rbdc->node); + spin_unlock(&rbd_client_list_lock); ceph_destroy_client(rbdc->client); kfree(rbdc->rbd_opts); @@ -463,9 +465,7 @@ static void rbd_client_release(struct kref *kref) */ static void rbd_put_client(struct rbd_device *rbd_dev) { - spin_lock(&rbd_client_list_lock); kref_put(&rbd_dev->rbd_client->kref, rbd_client_release); - spin_unlock(&rbd_client_list_lock); rbd_dev->rbd_client = NULL; } -- GitLab From 45739514727c294e843269d515b952d5dbd911bf Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 5 Dec 2011 10:47:13 -0800 Subject: [PATCH 1067/1799] rbd: protect read of snapshot sequence number (cherry picked from commit 403f24d3d51760a8b9368d595fa5f48c309f1a0f) This is updated whenever a snapshot is added or deleted, and the snapc pointer is changed with every refresh of the header. Signed-off-by: Josh Durgin Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh Signed-off-by: Greg Kroah-Hartman --- drivers/block/rbd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index c1f770131654..ff224baf0ff6 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1683,7 +1683,9 @@ static int rbd_header_add_snap(struct rbd_device *dev, if (ret < 0) return ret; - dev->header.snapc->seq = new_snapid; + down_write(&dev->header_rwsem); + dev->header.snapc->seq = new_snapid; + up_write(&dev->header_rwsem); return 0; bad: -- GitLab From 6448acf6e6b603c4fa21697931cd400ebee21d4a Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 21 Nov 2011 13:04:42 -0800 Subject: [PATCH 1068/1799] rbd: store snapshot id instead of index (cherry picked from commit 77dfe99fe3cb0b2b0545e19e2d57b7a9134ee3c0) When a device was open at a snapshot, and snapshots were deleted or added, data from the wrong snapshot could be read. Instead of assuming the snap context is constant, store the actual snap id when the device is initialized, and rely on the OSDs to signal an error if we try reading from a snapshot that was deleted. Signed-off-by: Josh Durgin Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh Signed-off-by: Greg Kroah-Hartman --- drivers/block/rbd.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index ff224baf0ff6..d074ed9e233c 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -175,8 +175,7 @@ struct rbd_device { /* protects updating the header */ struct rw_semaphore header_rwsem; char snap_name[RBD_MAX_SNAP_NAME_LEN]; - u32 cur_snap; /* index+1 of current snapshot within snap context - 0 - for the head */ + u64 snap_id; /* current snapshot id */ int read_only; struct list_head node; @@ -552,21 +551,6 @@ static int rbd_header_from_disk(struct rbd_image_header *header, return -ENOMEM; } -static int snap_index(struct rbd_image_header *header, int snap_num) -{ - return header->total_snaps - snap_num; -} - -static u64 cur_snap_id(struct rbd_device *rbd_dev) -{ - struct rbd_image_header *header = &rbd_dev->header; - - if (!rbd_dev->cur_snap) - return 0; - - return header->snapc->snaps[snap_index(header, rbd_dev->cur_snap)]; -} - static int snap_by_name(struct rbd_image_header *header, const char *snap_name, u64 *seq, u64 *size) { @@ -605,7 +589,7 @@ static int rbd_header_set_snap(struct rbd_device *dev, u64 *size) snapc->seq = header->snap_seq; else snapc->seq = 0; - dev->cur_snap = 0; + dev->snap_id = CEPH_NOSNAP; dev->read_only = 0; if (size) *size = header->image_size; @@ -613,8 +597,7 @@ static int rbd_header_set_snap(struct rbd_device *dev, u64 *size) ret = snap_by_name(header, dev->snap_name, &snapc->seq, size); if (ret < 0) goto done; - - dev->cur_snap = header->total_snaps - ret; + dev->snap_id = snapc->seq; dev->read_only = 1; } @@ -1521,7 +1504,7 @@ static void rbd_rq_fn(struct request_queue *q) coll, cur_seg); else rbd_req_read(rq, rbd_dev, - cur_snap_id(rbd_dev), + rbd_dev->snap_id, ofs, op_size, bio, coll, cur_seg); @@ -1656,7 +1639,7 @@ static int rbd_header_add_snap(struct rbd_device *dev, struct ceph_mon_client *monc; /* we should create a snapshot only if we're pointing at the head */ - if (dev->cur_snap) + if (dev->snap_id != CEPH_NOSNAP) return -EINVAL; monc = &dev->rbd_client->client->monc; -- GitLab From 9923ad77a69ab565af2746262989cc0340943668 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Wed, 6 Jun 2012 09:15:33 -0500 Subject: [PATCH 1069/1799] rbd: Fix ceph_snap_context size calculation (cherry picked from commit f9f9a1904467816452fc70740165030e84c2c659) ceph_snap_context->snaps is an u64 array Signed-off-by: Zheng Yan Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- drivers/block/rbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index d074ed9e233c..7b331366a8a4 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -497,7 +497,7 @@ static int rbd_header_from_disk(struct rbd_image_header *header, snap_count = le32_to_cpu(ondisk->snap_count); header->snapc = kmalloc(sizeof(struct ceph_snap_context) + - snap_count * sizeof (*ondisk), + snap_count * sizeof(u64), gfp_flags); if (!header->snapc) return -ENOMEM; -- GitLab From e7fda85c9dab7396c5ed7345ab7c6fcdf4ffc366 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 28 May 2012 14:44:30 +0800 Subject: [PATCH 1070/1799] ceph: check PG_Private flag before accessing page->private (cherry picked from commit 28c0254ede13ab575d2df5c6585ed3d4817c3e6b) I got lots of NULL pointer dereference Oops when compiling kernel on ceph. The bug is because the kernel page migration routine replaces some pages in the page cache with new pages, these new pages' private can be non-zero. Signed-off-by: Zheng Yan Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/addr.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 173b1d22e59b..8b67304e4b80 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -54,7 +54,12 @@ (CONGESTION_ON_THRESH(congestion_kb) - \ (CONGESTION_ON_THRESH(congestion_kb) >> 2)) - +static inline struct ceph_snap_context *page_snap_context(struct page *page) +{ + if (PagePrivate(page)) + return (void *)page->private; + return NULL; +} /* * Dirty a page. Optimistically adjust accounting, on the assumption @@ -142,10 +147,9 @@ static void ceph_invalidatepage(struct page *page, unsigned long offset) { struct inode *inode; struct ceph_inode_info *ci; - struct ceph_snap_context *snapc = (void *)page->private; + struct ceph_snap_context *snapc = page_snap_context(page); BUG_ON(!PageLocked(page)); - BUG_ON(!page->private); BUG_ON(!PagePrivate(page)); BUG_ON(!page->mapping); @@ -182,7 +186,6 @@ static int ceph_releasepage(struct page *page, gfp_t g) struct inode *inode = page->mapping ? page->mapping->host : NULL; dout("%p releasepage %p idx %lu\n", inode, page, page->index); WARN_ON(PageDirty(page)); - WARN_ON(page->private); WARN_ON(PagePrivate(page)); return 0; } @@ -443,7 +446,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) osdc = &fsc->client->osdc; /* verify this is a writeable snap context */ - snapc = (void *)page->private; + snapc = page_snap_context(page); if (snapc == NULL) { dout("writepage %p page %p not dirty?\n", inode, page); goto out; @@ -451,7 +454,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) oldest = get_oldest_context(inode, &snap_size); if (snapc->seq > oldest->seq) { dout("writepage %p page %p snapc %p not writeable - noop\n", - inode, page, (void *)page->private); + inode, page, snapc); /* we should only noop if called by kswapd */ WARN_ON((current->flags & PF_MEMALLOC) == 0); ceph_put_snap_context(oldest); @@ -591,7 +594,7 @@ static void writepages_finish(struct ceph_osd_request *req, clear_bdi_congested(&fsc->backing_dev_info, BLK_RW_ASYNC); - ceph_put_snap_context((void *)page->private); + ceph_put_snap_context(page_snap_context(page)); page->private = 0; ClearPagePrivate(page); dout("unlocking %d %p\n", i, page); @@ -795,7 +798,7 @@ static int ceph_writepages_start(struct address_space *mapping, } /* only if matching snap context */ - pgsnapc = (void *)page->private; + pgsnapc = page_snap_context(page); if (pgsnapc->seq > snapc->seq) { dout("page snapc %p %lld > oldest %p %lld\n", pgsnapc, pgsnapc->seq, snapc, snapc->seq); @@ -984,7 +987,7 @@ static int ceph_update_writeable_page(struct file *file, BUG_ON(!ci->i_snap_realm); down_read(&mdsc->snap_rwsem); BUG_ON(!ci->i_snap_realm->cached_context); - snapc = (void *)page->private; + snapc = page_snap_context(page); if (snapc && snapc != ci->i_head_snapc) { /* * this page is already dirty in another (older) snap -- GitLab From ac7a42681718cd7474cec70f198f0684ba7444eb Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 22 May 2012 11:41:43 -0500 Subject: [PATCH 1071/1799] libceph: eliminate connection state "DEAD" (cherry picked from commit e5e372da9a469dfe3ece40277090a7056c566838) The ceph connection state "DEAD" is never set and is therefore not needed. Eliminate it. Signed-off-by: Alex Elder Reviewed-by: Yehuda Sadeh Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 1 - net/ceph/messenger.c | 6 ------ 2 files changed, 7 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 44c87e731e9d..6a1dc80cf1e7 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -119,7 +119,6 @@ struct ceph_msg_pos { #define CLOSED 10 /* we've closed the connection */ #define SOCK_CLOSED 11 /* socket state changed to closed */ #define OPENING 13 /* open connection w/ (possibly new) peer */ -#define DEAD 14 /* dead, about to kfree */ #define BACKOFF 15 /* diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 0e270166f72f..4054adb66513 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2091,12 +2091,6 @@ static int try_read(struct ceph_connection *con) */ static void queue_con(struct ceph_connection *con) { - if (test_bit(DEAD, &con->state)) { - dout("queue_con %p ignoring: DEAD\n", - con); - return; - } - if (!con->ops->get(con)) { dout("queue_con %p ref count 0\n", con); return; -- GitLab From 809c58f1bd5fa3d3e9ff1d3614c00c1a1239abf1 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 29 May 2012 21:47:38 -0500 Subject: [PATCH 1072/1799] libceph: kill bad_proto ceph connection op (cherry picked from commit 6384bb8b8e88a9c6bf2ae0d9517c2c0199177c34) No code sets a bad_proto method in its ceph connection operations vector, so just get rid of it. Signed-off-by: Alex Elder Reviewed-by: Yehuda Sadeh Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 3 --- net/ceph/messenger.c | 5 ----- 2 files changed, 8 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 6a1dc80cf1e7..ce7a4830529d 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -31,9 +31,6 @@ struct ceph_connection_operations { int (*verify_authorizer_reply) (struct ceph_connection *con, int len); int (*invalidate_authorizer)(struct ceph_connection *con); - /* protocol version mismatch */ - void (*bad_proto) (struct ceph_connection *con); - /* there was some error on the socket (disconnect, whatever) */ void (*fault) (struct ceph_connection *con); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 4054adb66513..b408ea7cce96 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1360,11 +1360,6 @@ static void fail_protocol(struct ceph_connection *con) { reset_connection(con); set_bit(CLOSED, &con->state); /* in case there's queued work */ - - mutex_unlock(&con->mutex); - if (con->ops->bad_proto) - con->ops->bad_proto(con); - mutex_lock(&con->mutex); } static int process_connect(struct ceph_connection *con) -- GitLab From f5e79a443054452866bba4856ed243faf502d708 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 22 May 2012 11:41:43 -0500 Subject: [PATCH 1073/1799] libceph: rename socket callbacks (cherry picked from commit 327800bdc2cb9b71f4b458ca07aa9d522668dde0) Change the names of the three socket callback functions to make it more obvious they're specifically associated with a connection's socket (not the ceph connection that uses it). Signed-off-by: Alex Elder Reviewed-by: Yehuda Sadeh Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index b408ea7cce96..1250b157b9d6 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -153,46 +153,46 @@ EXPORT_SYMBOL(ceph_msgr_flush); */ /* data available on socket, or listen socket received a connect */ -static void ceph_data_ready(struct sock *sk, int count_unused) +static void ceph_sock_data_ready(struct sock *sk, int count_unused) { struct ceph_connection *con = sk->sk_user_data; if (sk->sk_state != TCP_CLOSE_WAIT) { - dout("ceph_data_ready on %p state = %lu, queueing work\n", + dout("%s on %p state = %lu, queueing work\n", __func__, con, con->state); queue_con(con); } } /* socket has buffer space for writing */ -static void ceph_write_space(struct sock *sk) +static void ceph_sock_write_space(struct sock *sk) { struct ceph_connection *con = sk->sk_user_data; /* only queue to workqueue if there is data we want to write, * and there is sufficient space in the socket buffer to accept - * more data. clear SOCK_NOSPACE so that ceph_write_space() + * more data. clear SOCK_NOSPACE so that ceph_sock_write_space() * doesn't get called again until try_write() fills the socket * buffer. See net/ipv4/tcp_input.c:tcp_check_space() * and net/core/stream.c:sk_stream_write_space(). */ if (test_bit(WRITE_PENDING, &con->state)) { if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) { - dout("ceph_write_space %p queueing write work\n", con); + dout("%s %p queueing write work\n", __func__, con); clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); queue_con(con); } } else { - dout("ceph_write_space %p nothing to write\n", con); + dout("%s %p nothing to write\n", __func__, con); } } /* socket's state has changed */ -static void ceph_state_change(struct sock *sk) +static void ceph_sock_state_change(struct sock *sk) { struct ceph_connection *con = sk->sk_user_data; - dout("ceph_state_change %p state = %lu sk_state = %u\n", + dout("%s %p state = %lu sk_state = %u\n", __func__, con, con->state, sk->sk_state); if (test_bit(CLOSED, &con->state)) @@ -200,9 +200,9 @@ static void ceph_state_change(struct sock *sk) switch (sk->sk_state) { case TCP_CLOSE: - dout("ceph_state_change TCP_CLOSE\n"); + dout("%s TCP_CLOSE\n", __func__); case TCP_CLOSE_WAIT: - dout("ceph_state_change TCP_CLOSE_WAIT\n"); + dout("%s TCP_CLOSE_WAIT\n", __func__); if (test_and_set_bit(SOCK_CLOSED, &con->state) == 0) { if (test_bit(CONNECTING, &con->state)) con->error_msg = "connection failed"; @@ -212,7 +212,7 @@ static void ceph_state_change(struct sock *sk) } break; case TCP_ESTABLISHED: - dout("ceph_state_change TCP_ESTABLISHED\n"); + dout("%s TCP_ESTABLISHED\n", __func__); queue_con(con); break; default: /* Everything else is uninteresting */ @@ -228,9 +228,9 @@ static void set_sock_callbacks(struct socket *sock, { struct sock *sk = sock->sk; sk->sk_user_data = con; - sk->sk_data_ready = ceph_data_ready; - sk->sk_write_space = ceph_write_space; - sk->sk_state_change = ceph_state_change; + sk->sk_data_ready = ceph_sock_data_ready; + sk->sk_write_space = ceph_sock_write_space; + sk->sk_state_change = ceph_sock_state_change; } -- GitLab From 4874ba9c07e2fa418cd7272d657f5cc883efd35a Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 23 May 2012 14:35:23 -0500 Subject: [PATCH 1074/1799] libceph: rename kvec_reset and kvec_add functions (cherry picked from commit e22004235a900213625acd6583ac913d5a30c155) The functions ceph_con_out_kvec_reset() and ceph_con_out_kvec_add() are entirely private functions, so drop the "ceph_" prefix in their name to make them slightly more wieldy. Signed-off-by: Alex Elder Reviewed-by: Yehuda Sadeh Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 48 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 1250b157b9d6..2a8f3d3ec1a9 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -486,14 +486,14 @@ static u32 get_global_seq(struct ceph_messenger *msgr, u32 gt) return ret; } -static void ceph_con_out_kvec_reset(struct ceph_connection *con) +static void con_out_kvec_reset(struct ceph_connection *con) { con->out_kvec_left = 0; con->out_kvec_bytes = 0; con->out_kvec_cur = &con->out_kvec[0]; } -static void ceph_con_out_kvec_add(struct ceph_connection *con, +static void con_out_kvec_add(struct ceph_connection *con, size_t size, void *data) { int index; @@ -534,7 +534,7 @@ static void prepare_write_message(struct ceph_connection *con) struct ceph_msg *m; u32 crc; - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); con->out_kvec_is_msg = true; con->out_msg_done = false; @@ -542,9 +542,9 @@ static void prepare_write_message(struct ceph_connection *con) * TCP packet that's a good thing. */ if (con->in_seq > con->in_seq_acked) { con->in_seq_acked = con->in_seq; - ceph_con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); + con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); con->out_temp_ack = cpu_to_le64(con->in_seq_acked); - ceph_con_out_kvec_add(con, sizeof (con->out_temp_ack), + con_out_kvec_add(con, sizeof (con->out_temp_ack), &con->out_temp_ack); } @@ -576,12 +576,12 @@ static void prepare_write_message(struct ceph_connection *con) BUG_ON(le32_to_cpu(m->hdr.front_len) != m->front.iov_len); /* tag + hdr + front + middle */ - ceph_con_out_kvec_add(con, sizeof (tag_msg), &tag_msg); - ceph_con_out_kvec_add(con, sizeof (m->hdr), &m->hdr); - ceph_con_out_kvec_add(con, m->front.iov_len, m->front.iov_base); + con_out_kvec_add(con, sizeof (tag_msg), &tag_msg); + con_out_kvec_add(con, sizeof (m->hdr), &m->hdr); + con_out_kvec_add(con, m->front.iov_len, m->front.iov_base); if (m->middle) - ceph_con_out_kvec_add(con, m->middle->vec.iov_len, + con_out_kvec_add(con, m->middle->vec.iov_len, m->middle->vec.iov_base); /* fill in crc (except data pages), footer */ @@ -630,12 +630,12 @@ static void prepare_write_ack(struct ceph_connection *con) con->in_seq_acked, con->in_seq); con->in_seq_acked = con->in_seq; - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); - ceph_con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); + con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); con->out_temp_ack = cpu_to_le64(con->in_seq_acked); - ceph_con_out_kvec_add(con, sizeof (con->out_temp_ack), + con_out_kvec_add(con, sizeof (con->out_temp_ack), &con->out_temp_ack); con->out_more = 1; /* more will follow.. eventually.. */ @@ -648,8 +648,8 @@ static void prepare_write_ack(struct ceph_connection *con) static void prepare_write_keepalive(struct ceph_connection *con) { dout("prepare_write_keepalive %p\n", con); - ceph_con_out_kvec_reset(con); - ceph_con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive); + con_out_kvec_reset(con); + con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive); set_bit(WRITE_PENDING, &con->state); } @@ -694,8 +694,8 @@ static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection */ static void prepare_write_banner(struct ceph_connection *con) { - ceph_con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER); - ceph_con_out_kvec_add(con, sizeof (con->msgr->my_enc_addr), + con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER); + con_out_kvec_add(con, sizeof (con->msgr->my_enc_addr), &con->msgr->my_enc_addr); con->out_more = 0; @@ -742,10 +742,10 @@ static int prepare_write_connect(struct ceph_connection *con) con->out_connect.authorizer_len = auth ? cpu_to_le32(auth->authorizer_buf_len) : 0; - ceph_con_out_kvec_add(con, sizeof (con->out_connect), + con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); if (auth && auth->authorizer_buf_len) - ceph_con_out_kvec_add(con, auth->authorizer_buf_len, + con_out_kvec_add(con, auth->authorizer_buf_len, auth->authorizer_buf); con->out_more = 0; @@ -939,7 +939,7 @@ static int write_partial_msg_pages(struct ceph_connection *con) /* prepare and queue up footer, too */ if (!do_datacrc) con->out_msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); prepare_write_message_footer(con); ret = 1; out: @@ -1402,7 +1402,7 @@ static int process_connect(struct ceph_connection *con) return -1; } con->auth_retry = 1; - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1423,7 +1423,7 @@ static int process_connect(struct ceph_connection *con) ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr)); reset_connection(con); - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1449,7 +1449,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->out_connect.connect_seq), le32_to_cpu(con->in_reply.connect_seq)); con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1466,7 +1466,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_reply.global_seq)); get_global_seq(con->msgr, le32_to_cpu(con->in_reply.global_seq)); - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1873,7 +1873,7 @@ static int try_write(struct ceph_connection *con) /* open the socket first? */ if (con->sock == NULL) { - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); prepare_write_banner(con); ret = prepare_write_connect(con); if (ret < 0) -- GitLab From d910c114b6da5b78c88889eff1b3f9e83c6f81cb Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 26 May 2012 23:26:43 -0500 Subject: [PATCH 1075/1799] libceph: embed ceph messenger structure in ceph_client (cherry picked from commit 15d9882c336db2db73ccf9871ae2398e452f694c) A ceph client has a pointer to a ceph messenger structure in it. There is always exactly one ceph messenger for a ceph client, so there is no need to allocate it separate from the ceph client structure. Switch the ceph_client structure to embed its ceph_messenger structure. Signed-off-by: Alex Elder Reviewed-by: Yehuda Sadeh Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/mds_client.c | 2 +- include/linux/ceph/libceph.h | 2 +- include/linux/ceph/messenger.h | 9 +++++---- net/ceph/ceph_common.c | 18 +++++------------- net/ceph/messenger.c | 30 +++++++++--------------------- net/ceph/mon_client.c | 6 +++--- net/ceph/osd_client.c | 4 ++-- 7 files changed, 26 insertions(+), 45 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 200bc87eceb1..ad30261cd4c0 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -394,7 +394,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, s->s_seq = 0; mutex_init(&s->s_mutex); - ceph_con_init(mdsc->fsc->client->msgr, &s->s_con); + ceph_con_init(&mdsc->fsc->client->msgr, &s->s_con); s->s_con.private = s; s->s_con.ops = &mds_con_ops; s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS; diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h index e71d683982a6..98ec36ae8a3b 100644 --- a/include/linux/ceph/libceph.h +++ b/include/linux/ceph/libceph.h @@ -132,7 +132,7 @@ struct ceph_client { u32 supported_features; u32 required_features; - struct ceph_messenger *msgr; /* messenger instance */ + struct ceph_messenger msgr; /* messenger instance */ struct ceph_mon_client monc; struct ceph_osd_client osdc; diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index ce7a4830529d..771b2edd4717 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -203,10 +203,11 @@ extern int ceph_msgr_init(void); extern void ceph_msgr_exit(void); extern void ceph_msgr_flush(void); -extern struct ceph_messenger *ceph_messenger_create( - struct ceph_entity_addr *myaddr, - u32 features, u32 required); -extern void ceph_messenger_destroy(struct ceph_messenger *); +extern void ceph_messenger_init(struct ceph_messenger *msgr, + struct ceph_entity_addr *myaddr, + u32 supported_features, + u32 required_features, + bool nocrc); extern void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con); diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 5dedac58faf4..c815f31a1a3f 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -468,19 +468,15 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, /* msgr */ if (ceph_test_opt(client, MYIP)) myaddr = &client->options->my_addr; - client->msgr = ceph_messenger_create(myaddr, - client->supported_features, - client->required_features); - if (IS_ERR(client->msgr)) { - err = PTR_ERR(client->msgr); - goto fail; - } - client->msgr->nocrc = ceph_test_opt(client, NOCRC); + ceph_messenger_init(&client->msgr, myaddr, + client->supported_features, + client->required_features, + ceph_test_opt(client, NOCRC)); /* subsystems */ err = ceph_monc_init(&client->monc, client); if (err < 0) - goto fail_msgr; + goto fail; err = ceph_osdc_init(&client->osdc, client); if (err < 0) goto fail_monc; @@ -489,8 +485,6 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, fail_monc: ceph_monc_stop(&client->monc); -fail_msgr: - ceph_messenger_destroy(client->msgr); fail: kfree(client); return ERR_PTR(err); @@ -508,8 +502,6 @@ void ceph_destroy_client(struct ceph_client *client) ceph_debugfs_client_cleanup(client); - ceph_messenger_destroy(client->msgr); - ceph_destroy_options(client->options); kfree(client); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 2a8f3d3ec1a9..9570c7628798 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2249,18 +2249,14 @@ static void ceph_fault(struct ceph_connection *con) /* - * create a new messenger instance + * initialize a new messenger instance */ -struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr, - u32 supported_features, - u32 required_features) +void ceph_messenger_init(struct ceph_messenger *msgr, + struct ceph_entity_addr *myaddr, + u32 supported_features, + u32 required_features, + bool nocrc) { - struct ceph_messenger *msgr; - - msgr = kzalloc(sizeof(*msgr), GFP_KERNEL); - if (msgr == NULL) - return ERR_PTR(-ENOMEM); - msgr->supported_features = supported_features; msgr->required_features = required_features; @@ -2273,19 +2269,11 @@ struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr, msgr->inst.addr.type = 0; get_random_bytes(&msgr->inst.addr.nonce, sizeof(msgr->inst.addr.nonce)); encode_my_addr(msgr); + msgr->nocrc = nocrc; - dout("messenger_create %p\n", msgr); - return msgr; -} -EXPORT_SYMBOL(ceph_messenger_create); - -void ceph_messenger_destroy(struct ceph_messenger *msgr) -{ - dout("destroy %p\n", msgr); - kfree(msgr); - dout("destroyed messenger %p\n", msgr); + dout("%s %p\n", __func__, msgr); } -EXPORT_SYMBOL(ceph_messenger_destroy); +EXPORT_SYMBOL(ceph_messenger_init); static void clear_standby(struct ceph_connection *con) { diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 852dbb4a4e6b..b2d9ce4d80d9 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -763,7 +763,7 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL); if (!monc->con) goto out_monmap; - ceph_con_init(monc->client->msgr, monc->con); + ceph_con_init(&monc->client->msgr, monc->con); monc->con->private = monc; monc->con->ops = &mon_con_ops; @@ -888,8 +888,8 @@ static void handle_auth_reply(struct ceph_mon_client *monc, } else if (!was_auth && monc->auth->ops->is_authenticated(monc->auth)) { dout("authenticated, starting session\n"); - monc->client->msgr->inst.name.type = CEPH_ENTITY_TYPE_CLIENT; - monc->client->msgr->inst.name.num = + monc->client->msgr.inst.name.type = CEPH_ENTITY_TYPE_CLIENT; + monc->client->msgr.inst.name.num = cpu_to_le64(monc->auth->global_id); __send_subscribe(monc); diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index f4e2a4665d9b..6c948dc4d77e 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -639,7 +639,7 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc) INIT_LIST_HEAD(&osd->o_osd_lru); osd->o_incarnation = 1; - ceph_con_init(osdc->client->msgr, &osd->o_con); + ceph_con_init(&osdc->client->msgr, &osd->o_con); osd->o_con.private = osd; osd->o_con.ops = &osd_con_ops; osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD; @@ -1391,7 +1391,7 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) epoch, maplen); newmap = osdmap_apply_incremental(&p, next, osdc->osdmap, - osdc->client->msgr); + &osdc->client->msgr); if (IS_ERR(newmap)) { err = PTR_ERR(newmap); goto bad; -- GitLab From bc327474a0c9f3477be61b2d3e33833ef7b01bf9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 22 May 2012 11:41:43 -0500 Subject: [PATCH 1076/1799] libceph: start separating connection flags from state (cherry picked from commit 928443cd9644e7cfd46f687dbeffda2d1a357ff9) A ceph_connection holds a mixture of connection state (as in "state machine" state) and connection flags in a single "state" field. To make the distinction more clear, define a new "flags" field and use it rather than the "state" field to hold Boolean flag values. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 18 ++++++++---- net/ceph/messenger.c | 50 +++++++++++++++++----------------- 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 771b2edd4717..34e9506be6b2 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -103,20 +103,25 @@ struct ceph_msg_pos { #define MAX_DELAY_INTERVAL (5 * 60 * HZ) /* - * ceph_connection state bit flags + * ceph_connection flag bits */ + #define LOSSYTX 0 /* we can close channel or drop messages on errors */ -#define CONNECTING 1 -#define NEGOTIATING 2 #define KEEPALIVE_PENDING 3 #define WRITE_PENDING 4 /* we have data ready to send */ +#define SOCK_CLOSED 11 /* socket state changed to closed */ +#define BACKOFF 15 + +/* + * ceph_connection states + */ +#define CONNECTING 1 +#define NEGOTIATING 2 #define STANDBY 8 /* no outgoing messages, socket closed. we keep * the ceph_connection around to maintain shared * state with the peer. */ #define CLOSED 10 /* we've closed the connection */ -#define SOCK_CLOSED 11 /* socket state changed to closed */ #define OPENING 13 /* open connection w/ (possibly new) peer */ -#define BACKOFF 15 /* * A single connection with another host. @@ -133,7 +138,8 @@ struct ceph_connection { struct ceph_messenger *msgr; struct socket *sock; - unsigned long state; /* connection state (see flags above) */ + unsigned long flags; + unsigned long state; const char *error_msg; /* error message, if any */ struct ceph_entity_addr peer_addr; /* peer address */ diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 9570c7628798..27e4e58922b3 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -176,7 +176,7 @@ static void ceph_sock_write_space(struct sock *sk) * buffer. See net/ipv4/tcp_input.c:tcp_check_space() * and net/core/stream.c:sk_stream_write_space(). */ - if (test_bit(WRITE_PENDING, &con->state)) { + if (test_bit(WRITE_PENDING, &con->flags)) { if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) { dout("%s %p queueing write work\n", __func__, con); clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); @@ -203,7 +203,7 @@ static void ceph_sock_state_change(struct sock *sk) dout("%s TCP_CLOSE\n", __func__); case TCP_CLOSE_WAIT: dout("%s TCP_CLOSE_WAIT\n", __func__); - if (test_and_set_bit(SOCK_CLOSED, &con->state) == 0) { + if (test_and_set_bit(SOCK_CLOSED, &con->flags) == 0) { if (test_bit(CONNECTING, &con->state)) con->error_msg = "connection failed"; else @@ -395,9 +395,9 @@ void ceph_con_close(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr)); set_bit(CLOSED, &con->state); /* in case there's queued work */ clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */ - clear_bit(LOSSYTX, &con->state); /* so we retry next connect */ - clear_bit(KEEPALIVE_PENDING, &con->state); - clear_bit(WRITE_PENDING, &con->state); + clear_bit(LOSSYTX, &con->flags); /* so we retry next connect */ + clear_bit(KEEPALIVE_PENDING, &con->flags); + clear_bit(WRITE_PENDING, &con->flags); mutex_lock(&con->mutex); reset_connection(con); con->peer_global_seq = 0; @@ -618,7 +618,7 @@ static void prepare_write_message(struct ceph_connection *con) prepare_write_message_footer(con); } - set_bit(WRITE_PENDING, &con->state); + set_bit(WRITE_PENDING, &con->flags); } /* @@ -639,7 +639,7 @@ static void prepare_write_ack(struct ceph_connection *con) &con->out_temp_ack); con->out_more = 1; /* more will follow.. eventually.. */ - set_bit(WRITE_PENDING, &con->state); + set_bit(WRITE_PENDING, &con->flags); } /* @@ -650,7 +650,7 @@ static void prepare_write_keepalive(struct ceph_connection *con) dout("prepare_write_keepalive %p\n", con); con_out_kvec_reset(con); con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive); - set_bit(WRITE_PENDING, &con->state); + set_bit(WRITE_PENDING, &con->flags); } /* @@ -679,7 +679,7 @@ static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection if (IS_ERR(auth)) return auth; - if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state)) + if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->flags)) return ERR_PTR(-EAGAIN); con->auth_reply_buf = auth->authorizer_reply_buf; @@ -699,7 +699,7 @@ static void prepare_write_banner(struct ceph_connection *con) &con->msgr->my_enc_addr); con->out_more = 0; - set_bit(WRITE_PENDING, &con->state); + set_bit(WRITE_PENDING, &con->flags); } static int prepare_write_connect(struct ceph_connection *con) @@ -749,7 +749,7 @@ static int prepare_write_connect(struct ceph_connection *con) auth->authorizer_buf); con->out_more = 0; - set_bit(WRITE_PENDING, &con->state); + set_bit(WRITE_PENDING, &con->flags); return 0; } @@ -1496,7 +1496,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_reply.connect_seq)); if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY) - set_bit(LOSSYTX, &con->state); + set_bit(LOSSYTX, &con->flags); prepare_read_tag(con); break; @@ -1937,14 +1937,14 @@ static int try_write(struct ceph_connection *con) prepare_write_ack(con); goto more; } - if (test_and_clear_bit(KEEPALIVE_PENDING, &con->state)) { + if (test_and_clear_bit(KEEPALIVE_PENDING, &con->flags)) { prepare_write_keepalive(con); goto more; } } /* Nothing to do! */ - clear_bit(WRITE_PENDING, &con->state); + clear_bit(WRITE_PENDING, &con->flags); dout("try_write nothing else to write.\n"); ret = 0; out: @@ -2110,7 +2110,7 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: - if (test_and_clear_bit(BACKOFF, &con->state)) { + if (test_and_clear_bit(BACKOFF, &con->flags)) { dout("con_work %p backing off\n", con); if (queue_delayed_work(ceph_msgr_wq, &con->work, round_jiffies_relative(con->delay))) { @@ -2139,7 +2139,7 @@ static void con_work(struct work_struct *work) con_close_socket(con); } - if (test_and_clear_bit(SOCK_CLOSED, &con->state)) + if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) goto fault; ret = try_read(con); @@ -2178,7 +2178,7 @@ static void ceph_fault(struct ceph_connection *con) dout("fault %p state %lu to peer %s\n", con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); - if (test_bit(LOSSYTX, &con->state)) { + if (test_bit(LOSSYTX, &con->flags)) { dout("fault on LOSSYTX channel\n"); goto out; } @@ -2200,9 +2200,9 @@ static void ceph_fault(struct ceph_connection *con) /* If there are no messages queued or keepalive pending, place * the connection in a STANDBY state */ if (list_empty(&con->out_queue) && - !test_bit(KEEPALIVE_PENDING, &con->state)) { + !test_bit(KEEPALIVE_PENDING, &con->flags)) { dout("fault %p setting STANDBY clearing WRITE_PENDING\n", con); - clear_bit(WRITE_PENDING, &con->state); + clear_bit(WRITE_PENDING, &con->flags); set_bit(STANDBY, &con->state); } else { /* retry after a delay. */ @@ -2226,7 +2226,7 @@ static void ceph_fault(struct ceph_connection *con) * that when con_work restarts we schedule the * delay then. */ - set_bit(BACKOFF, &con->state); + set_bit(BACKOFF, &con->flags); } } @@ -2282,8 +2282,8 @@ static void clear_standby(struct ceph_connection *con) mutex_lock(&con->mutex); dout("clear_standby %p and ++connect_seq\n", con); con->connect_seq++; - WARN_ON(test_bit(WRITE_PENDING, &con->state)); - WARN_ON(test_bit(KEEPALIVE_PENDING, &con->state)); + WARN_ON(test_bit(WRITE_PENDING, &con->flags)); + WARN_ON(test_bit(KEEPALIVE_PENDING, &con->flags)); mutex_unlock(&con->mutex); } } @@ -2321,7 +2321,7 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) /* if there wasn't anything waiting to send before, queue * new work */ clear_standby(con); - if (test_and_set_bit(WRITE_PENDING, &con->state) == 0) + if (test_and_set_bit(WRITE_PENDING, &con->flags) == 0) queue_con(con); } EXPORT_SYMBOL(ceph_con_send); @@ -2388,8 +2388,8 @@ void ceph_con_keepalive(struct ceph_connection *con) { dout("con_keepalive %p\n", con); clear_standby(con); - if (test_and_set_bit(KEEPALIVE_PENDING, &con->state) == 0 && - test_and_set_bit(WRITE_PENDING, &con->state) == 0) + if (test_and_set_bit(KEEPALIVE_PENDING, &con->flags) == 0 && + test_and_set_bit(WRITE_PENDING, &con->flags) == 0) queue_con(con); } EXPORT_SYMBOL(ceph_con_keepalive); -- GitLab From 0bcd15777405bf024a3ec591731582f7263ea1c0 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 22 May 2012 22:15:49 -0500 Subject: [PATCH 1077/1799] libceph: start tracking connection socket state (cherry picked from commit ce2c8903e76e690846a00a0284e4bd9ee954d680) Start explicitly keeping track of the state of a ceph connection's socket, separate from the state of the connection itself. Create placeholder functions to encapsulate the state transitions. -------- | NEW* | transient initial state -------- | con_sock_state_init() v ---------- | CLOSED | initialized, but no socket (and no ---------- TCP connection) ^ \ | \ con_sock_state_connecting() | ---------------------- | \ + con_sock_state_closed() \ |\ \ | \ \ | ----------- \ | | CLOSING | socket event; \ | ----------- await close \ | ^ | | | | | + con_sock_state_closing() | | / \ | | / --------------- | | / \ v | / -------------- | / -----------------| CONNECTING | socket created, TCP | | / -------------- connect initiated | | | con_sock_state_connected() | | v ------------- | CONNECTED | TCP connection established ------------- Make the socket state an atomic variable, reinforcing that it's a distinct transtion with no possible "intermediate/both" states. This is almost certainly overkill at this point, though the transitions into CONNECTED and CLOSING state do get called via socket callback (the rest of the transitions occur with the connection mutex held). We can back out the atomicity later. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 8 +++-- net/ceph/messenger.c | 64 ++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 34e9506be6b2..5f30c81d4746 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -137,14 +137,18 @@ struct ceph_connection { const struct ceph_connection_operations *ops; struct ceph_messenger *msgr; + + atomic_t sock_state; struct socket *sock; + struct ceph_entity_addr peer_addr; /* peer address */ + struct ceph_entity_addr peer_addr_for_me; + unsigned long flags; unsigned long state; const char *error_msg; /* error message, if any */ - struct ceph_entity_addr peer_addr; /* peer address */ struct ceph_entity_name peer_name; /* peer name */ - struct ceph_entity_addr peer_addr_for_me; + unsigned peer_features; u32 connect_seq; /* identify the most recent connection attempt for this connection, client */ diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 27e4e58922b3..2ad67994e435 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -29,6 +29,14 @@ * the sender. */ +/* State values for ceph_connection->sock_state; NEW is assumed to be 0 */ + +#define CON_SOCK_STATE_NEW 0 /* -> CLOSED */ +#define CON_SOCK_STATE_CLOSED 1 /* -> CONNECTING */ +#define CON_SOCK_STATE_CONNECTING 2 /* -> CONNECTED or -> CLOSING */ +#define CON_SOCK_STATE_CONNECTED 3 /* -> CLOSING or -> CLOSED */ +#define CON_SOCK_STATE_CLOSING 4 /* -> CLOSED */ + /* static tag bytes (protocol control messages) */ static char tag_msg = CEPH_MSGR_TAG_MSG; static char tag_ack = CEPH_MSGR_TAG_ACK; @@ -147,6 +155,55 @@ void ceph_msgr_flush(void) } EXPORT_SYMBOL(ceph_msgr_flush); +/* Connection socket state transition functions */ + +static void con_sock_state_init(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); + if (WARN_ON(old_state != CON_SOCK_STATE_NEW)) + printk("%s: unexpected old state %d\n", __func__, old_state); +} + +static void con_sock_state_connecting(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTING); + if (WARN_ON(old_state != CON_SOCK_STATE_CLOSED)) + printk("%s: unexpected old state %d\n", __func__, old_state); +} + +static void con_sock_state_connected(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTED); + if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTING)) + printk("%s: unexpected old state %d\n", __func__, old_state); +} + +static void con_sock_state_closing(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSING); + if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTING && + old_state != CON_SOCK_STATE_CONNECTED && + old_state != CON_SOCK_STATE_CLOSING)) + printk("%s: unexpected old state %d\n", __func__, old_state); +} + +static void con_sock_state_closed(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); + if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTED && + old_state != CON_SOCK_STATE_CLOSING)) + printk("%s: unexpected old state %d\n", __func__, old_state); +} /* * socket callback functions @@ -203,6 +260,7 @@ static void ceph_sock_state_change(struct sock *sk) dout("%s TCP_CLOSE\n", __func__); case TCP_CLOSE_WAIT: dout("%s TCP_CLOSE_WAIT\n", __func__); + con_sock_state_closing(con); if (test_and_set_bit(SOCK_CLOSED, &con->flags) == 0) { if (test_bit(CONNECTING, &con->state)) con->error_msg = "connection failed"; @@ -213,6 +271,7 @@ static void ceph_sock_state_change(struct sock *sk) break; case TCP_ESTABLISHED: dout("%s TCP_ESTABLISHED\n", __func__); + con_sock_state_connected(con); queue_con(con); break; default: /* Everything else is uninteresting */ @@ -277,6 +336,7 @@ static int ceph_tcp_connect(struct ceph_connection *con) return ret; } con->sock = sock; + con_sock_state_connecting(con); return 0; } @@ -343,6 +403,7 @@ static int con_close_socket(struct ceph_connection *con) sock_release(con->sock); con->sock = NULL; clear_bit(SOCK_CLOSED, &con->state); + con_sock_state_closed(con); return rc; } @@ -462,6 +523,9 @@ void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con) memset(con, 0, sizeof(*con)); atomic_set(&con->nref, 1); con->msgr = msgr; + + con_sock_state_init(con); + mutex_init(&con->mutex); INIT_LIST_HEAD(&con->out_queue); INIT_LIST_HEAD(&con->out_sent); -- GitLab From d39319ee9b0381848a7e2261d53914e2732191d7 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 26 May 2012 23:26:43 -0500 Subject: [PATCH 1078/1799] libceph: provide osd number when creating osd (cherry picked from commit e10006f807ffc4d5b1d861305d18d9e8145891ca) Pass the osd number to the create_osd() routine, and move the initialization of fields that depend on it therein. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/osd_client.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 6c948dc4d77e..5b41a6929cd9 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -624,7 +624,7 @@ static void osd_reset(struct ceph_connection *con) /* * Track open sessions with osds. */ -static struct ceph_osd *create_osd(struct ceph_osd_client *osdc) +static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum) { struct ceph_osd *osd; @@ -634,6 +634,7 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc) atomic_set(&osd->o_ref, 1); osd->o_osdc = osdc; + osd->o_osd = onum; INIT_LIST_HEAD(&osd->o_requests); INIT_LIST_HEAD(&osd->o_linger_requests); INIT_LIST_HEAD(&osd->o_osd_lru); @@ -643,6 +644,7 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc) osd->o_con.private = osd; osd->o_con.ops = &osd_con_ops; osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD; + osd->o_con.peer_name.num = cpu_to_le64(onum); INIT_LIST_HEAD(&osd->o_keepalive_item); return osd; @@ -998,15 +1000,13 @@ static int __map_request(struct ceph_osd_client *osdc, req->r_osd = __lookup_osd(osdc, o); if (!req->r_osd && o >= 0) { err = -ENOMEM; - req->r_osd = create_osd(osdc); + req->r_osd = create_osd(osdc, o); if (!req->r_osd) { list_move(&req->r_req_lru_item, &osdc->req_notarget); goto out; } dout("map_request osd %p is osd%d\n", req->r_osd, o); - req->r_osd->o_osd = o; - req->r_osd->o_con.peer_name.num = cpu_to_le64(o); __insert_osd(osdc, req->r_osd); ceph_con_open(&req->r_osd->o_con, &osdc->osdmap->osd_addr[o]); -- GitLab From 51588ed26f489e50bfd2359d55abcb4d907149bc Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 29 May 2012 11:04:58 -0500 Subject: [PATCH 1079/1799] libceph: set CLOSED state bit in con_init (cherry picked from commit a5988c490ef66cb04ea2f610681949b25c773b3c) Once a connection is fully initialized, it is really in a CLOSED state, so make that explicit by setting the bit in its state field. It is possible for a connection in NEGOTIATING state to get a failure, leading to ceph_fault() and ultimately ceph_con_close(). Clear that bits if it is set in that case, to reflect that the connection truly is closed and is no longer participating in a connect sequence. Issue a warning if ceph_con_open() is called on a connection that is not in CLOSED state. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 2ad67994e435..ca0e4c126f48 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -454,11 +454,14 @@ void ceph_con_close(struct ceph_connection *con) { dout("con_close %p peer %s\n", con, ceph_pr_addr(&con->peer_addr.in_addr)); - set_bit(CLOSED, &con->state); /* in case there's queued work */ + clear_bit(NEGOTIATING, &con->state); clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */ + set_bit(CLOSED, &con->state); + clear_bit(LOSSYTX, &con->flags); /* so we retry next connect */ clear_bit(KEEPALIVE_PENDING, &con->flags); clear_bit(WRITE_PENDING, &con->flags); + mutex_lock(&con->mutex); reset_connection(con); con->peer_global_seq = 0; @@ -475,7 +478,8 @@ void ceph_con_open(struct ceph_connection *con, struct ceph_entity_addr *addr) { dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); set_bit(OPENING, &con->state); - clear_bit(CLOSED, &con->state); + WARN_ON(!test_and_clear_bit(CLOSED, &con->state)); + memcpy(&con->peer_addr, addr, sizeof(*addr)); con->delay = 0; /* reset backoff memory */ queue_con(con); @@ -530,6 +534,8 @@ void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con) INIT_LIST_HEAD(&con->out_queue); INIT_LIST_HEAD(&con->out_sent); INIT_DELAYED_WORK(&con->work, con_work); + + set_bit(CLOSED, &con->state); } EXPORT_SYMBOL(ceph_con_init); @@ -1937,14 +1943,15 @@ static int try_write(struct ceph_connection *con) /* open the socket first? */ if (con->sock == NULL) { + clear_bit(NEGOTIATING, &con->state); + set_bit(CONNECTING, &con->state); + con_out_kvec_reset(con); prepare_write_banner(con); ret = prepare_write_connect(con); if (ret < 0) goto out; prepare_read_banner(con); - set_bit(CONNECTING, &con->state); - clear_bit(NEGOTIATING, &con->state); BUG_ON(con->in_msg); con->in_tag = CEPH_MSGR_TAG_READY; -- GitLab From 31a84d83433edc79151e28762c1992c0708b222c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 26 May 2012 23:26:43 -0500 Subject: [PATCH 1080/1799] libceph: embed ceph connection structure in mon_client (cherry picked from commit 67130934fb579fdf0f2f6d745960264378b57dc8) A monitor client has a pointer to a ceph connection structure in it. This is the only one of the three ceph client types that do it this way; the OSD and MDS clients embed the connection into their main structures. There is always exactly one ceph connection for a monitor client, so there is no need to allocate it separate from the monitor client structure. So switch the ceph_mon_client structure to embed its ceph_connection structure. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/mon_client.h | 2 +- net/ceph/mon_client.c | 47 ++++++++++++++------------------- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/include/linux/ceph/mon_client.h b/include/linux/ceph/mon_client.h index 545f85917780..2113e3850a4e 100644 --- a/include/linux/ceph/mon_client.h +++ b/include/linux/ceph/mon_client.h @@ -70,7 +70,7 @@ struct ceph_mon_client { bool hunting; int cur_mon; /* last monitor i contacted */ unsigned long sub_sent, sub_renew_after; - struct ceph_connection *con; + struct ceph_connection con; bool have_fsid; /* pending generic requests */ diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index b2d9ce4d80d9..5cdd8f6d38da 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -106,9 +106,9 @@ static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len) monc->pending_auth = 1; monc->m_auth->front.iov_len = len; monc->m_auth->hdr.front_len = cpu_to_le32(len); - ceph_con_revoke(monc->con, monc->m_auth); + ceph_con_revoke(&monc->con, monc->m_auth); ceph_msg_get(monc->m_auth); /* keep our ref */ - ceph_con_send(monc->con, monc->m_auth); + ceph_con_send(&monc->con, monc->m_auth); } /* @@ -117,8 +117,8 @@ static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len) static void __close_session(struct ceph_mon_client *monc) { dout("__close_session closing mon%d\n", monc->cur_mon); - ceph_con_revoke(monc->con, monc->m_auth); - ceph_con_close(monc->con); + ceph_con_revoke(&monc->con, monc->m_auth); + ceph_con_close(&monc->con); monc->cur_mon = -1; monc->pending_auth = 0; ceph_auth_reset(monc->auth); @@ -142,9 +142,9 @@ static int __open_session(struct ceph_mon_client *monc) monc->want_next_osdmap = !!monc->want_next_osdmap; dout("open_session mon%d opening\n", monc->cur_mon); - monc->con->peer_name.type = CEPH_ENTITY_TYPE_MON; - monc->con->peer_name.num = cpu_to_le64(monc->cur_mon); - ceph_con_open(monc->con, + monc->con.peer_name.type = CEPH_ENTITY_TYPE_MON; + monc->con.peer_name.num = cpu_to_le64(monc->cur_mon); + ceph_con_open(&monc->con, &monc->monmap->mon_inst[monc->cur_mon].addr); /* initiatiate authentication handshake */ @@ -226,8 +226,8 @@ static void __send_subscribe(struct ceph_mon_client *monc) msg->front.iov_len = p - msg->front.iov_base; msg->hdr.front_len = cpu_to_le32(msg->front.iov_len); - ceph_con_revoke(monc->con, msg); - ceph_con_send(monc->con, ceph_msg_get(msg)); + ceph_con_revoke(&monc->con, msg); + ceph_con_send(&monc->con, ceph_msg_get(msg)); monc->sub_sent = jiffies | 1; /* never 0 */ } @@ -247,7 +247,7 @@ static void handle_subscribe_ack(struct ceph_mon_client *monc, if (monc->hunting) { pr_info("mon%d %s session established\n", monc->cur_mon, - ceph_pr_addr(&monc->con->peer_addr.in_addr)); + ceph_pr_addr(&monc->con.peer_addr.in_addr)); monc->hunting = false; } dout("handle_subscribe_ack after %d seconds\n", seconds); @@ -461,7 +461,7 @@ static int do_generic_request(struct ceph_mon_client *monc, req->request->hdr.tid = cpu_to_le64(req->tid); __insert_generic_request(monc, req); monc->num_generic_requests++; - ceph_con_send(monc->con, ceph_msg_get(req->request)); + ceph_con_send(&monc->con, ceph_msg_get(req->request)); mutex_unlock(&monc->mutex); err = wait_for_completion_interruptible(&req->completion); @@ -684,8 +684,8 @@ static void __resend_generic_request(struct ceph_mon_client *monc) for (p = rb_first(&monc->generic_request_tree); p; p = rb_next(p)) { req = rb_entry(p, struct ceph_mon_generic_request, node); - ceph_con_revoke(monc->con, req->request); - ceph_con_send(monc->con, ceph_msg_get(req->request)); + ceph_con_revoke(&monc->con, req->request); + ceph_con_send(&monc->con, ceph_msg_get(req->request)); } } @@ -705,7 +705,7 @@ static void delayed_work(struct work_struct *work) __close_session(monc); __open_session(monc); /* continue hunting */ } else { - ceph_con_keepalive(monc->con); + ceph_con_keepalive(&monc->con); __validate_auth(monc); @@ -760,19 +760,16 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) goto out; /* connection */ - monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL); - if (!monc->con) - goto out_monmap; - ceph_con_init(&monc->client->msgr, monc->con); - monc->con->private = monc; - monc->con->ops = &mon_con_ops; + ceph_con_init(&monc->client->msgr, &monc->con); + monc->con.private = monc; + monc->con.ops = &mon_con_ops; /* authentication */ monc->auth = ceph_auth_init(cl->options->name, cl->options->key); if (IS_ERR(monc->auth)) { err = PTR_ERR(monc->auth); - goto out_con; + goto out_monmap; } monc->auth->want_keys = CEPH_ENTITY_TYPE_AUTH | CEPH_ENTITY_TYPE_MON | @@ -824,8 +821,6 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) ceph_msg_put(monc->m_subscribe_ack); out_auth: ceph_auth_destroy(monc->auth); -out_con: - monc->con->ops->put(monc->con); out_monmap: kfree(monc->monmap); out: @@ -841,9 +836,7 @@ void ceph_monc_stop(struct ceph_mon_client *monc) mutex_lock(&monc->mutex); __close_session(monc); - monc->con->private = NULL; - monc->con->ops->put(monc->con); - monc->con = NULL; + monc->con.private = NULL; mutex_unlock(&monc->mutex); @@ -1029,7 +1022,7 @@ static void mon_fault(struct ceph_connection *con) if (!monc->hunting) pr_info("mon%d %s session lost, " "hunting for new mon\n", monc->cur_mon, - ceph_pr_addr(&monc->con->peer_addr.in_addr)); + ceph_pr_addr(&monc->con.peer_addr.in_addr)); __close_session(monc); if (!monc->hunting) { -- GitLab From a2b87615e2acfb851ec43603d0061f631381301a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 31 May 2012 20:27:50 -0700 Subject: [PATCH 1081/1799] libceph: drop connection refcounting for mon_client (cherry picked from commit ec87ef4309d33bd9c87a53bb5152a86ae7a65f25) All references to the embedded ceph_connection come from the msgr workqueue, which is drained prior to mon_client destruction. That means we can ignore con refcounting entirely. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/mon_client.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 5cdd8f6d38da..bbb2c660fd60 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -1037,9 +1037,23 @@ static void mon_fault(struct ceph_connection *con) mutex_unlock(&monc->mutex); } +/* + * We can ignore refcounting on the connection struct, as all references + * will come from the messenger workqueue, which is drained prior to + * mon_client destruction. + */ +static struct ceph_connection *con_get(struct ceph_connection *con) +{ + return con; +} + +static void con_put(struct ceph_connection *con) +{ +} + static const struct ceph_connection_operations mon_con_ops = { - .get = ceph_con_get, - .put = ceph_con_put, + .get = con_get, + .put = con_put, .dispatch = dispatch, .fault = mon_fault, .alloc_msg = mon_alloc_msg, -- GitLab From 9403ae33bf946342b23cfe3dbf3e4c9b86860c97 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 26 May 2012 23:26:43 -0500 Subject: [PATCH 1082/1799] libceph: init monitor connection when opening (cherry picked from commit 20581c1faf7b15ae1f8b80c0ec757877b0b53151) Hold off initializing a monitor client's connection until just before it gets opened for use. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/mon_client.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index bbb2c660fd60..1b03493f8749 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -119,6 +119,7 @@ static void __close_session(struct ceph_mon_client *monc) dout("__close_session closing mon%d\n", monc->cur_mon); ceph_con_revoke(&monc->con, monc->m_auth); ceph_con_close(&monc->con); + monc->con.private = NULL; monc->cur_mon = -1; monc->pending_auth = 0; ceph_auth_reset(monc->auth); @@ -141,9 +142,13 @@ static int __open_session(struct ceph_mon_client *monc) monc->sub_renew_after = jiffies; /* i.e., expired */ monc->want_next_osdmap = !!monc->want_next_osdmap; - dout("open_session mon%d opening\n", monc->cur_mon); + ceph_con_init(&monc->client->msgr, &monc->con); + monc->con.private = monc; + monc->con.ops = &mon_con_ops; monc->con.peer_name.type = CEPH_ENTITY_TYPE_MON; monc->con.peer_name.num = cpu_to_le64(monc->cur_mon); + + dout("open_session mon%d opening\n", monc->cur_mon); ceph_con_open(&monc->con, &monc->monmap->mon_inst[monc->cur_mon].addr); @@ -760,10 +765,6 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) goto out; /* connection */ - ceph_con_init(&monc->client->msgr, &monc->con); - monc->con.private = monc; - monc->con.ops = &mon_con_ops; - /* authentication */ monc->auth = ceph_auth_init(cl->options->name, cl->options->key); @@ -836,8 +837,6 @@ void ceph_monc_stop(struct ceph_mon_client *monc) mutex_lock(&monc->mutex); __close_session(monc); - monc->con.private = NULL; - mutex_unlock(&monc->mutex); /* -- GitLab From 6880138c03448b3c375a3d7a8ef6acd688e6fb40 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 26 May 2012 23:26:43 -0500 Subject: [PATCH 1083/1799] libceph: fully initialize connection in con_init() (cherry picked from commit 1bfd89f4e6e1adc6a782d94aa5d4c53be1e404d7) Move the initialization of a ceph connection's private pointer, operations vector pointer, and peer name information into ceph_con_init(). Rearrange the arguments so the connection pointer is first. Hide the byte-swapping of the peer entity number inside ceph_con_init() Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/mds_client.c | 7 ++----- include/linux/ceph/messenger.h | 6 ++++-- net/ceph/messenger.c | 9 ++++++++- net/ceph/mon_client.c | 8 +++----- net/ceph/osd_client.c | 7 ++----- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index ad30261cd4c0..ecd7f15741c1 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -394,11 +394,8 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, s->s_seq = 0; mutex_init(&s->s_mutex); - ceph_con_init(&mdsc->fsc->client->msgr, &s->s_con); - s->s_con.private = s; - s->s_con.ops = &mds_con_ops; - s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS; - s->s_con.peer_name.num = cpu_to_le64(mds); + ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr, + CEPH_ENTITY_TYPE_MDS, mds); spin_lock_init(&s->s_gen_ttl_lock); s->s_cap_gen = 0; diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 5f30c81d4746..7ed7a87aa6b5 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -219,8 +219,10 @@ extern void ceph_messenger_init(struct ceph_messenger *msgr, u32 required_features, bool nocrc); -extern void ceph_con_init(struct ceph_messenger *msgr, - struct ceph_connection *con); +extern void ceph_con_init(struct ceph_connection *con, void *private, + const struct ceph_connection_operations *ops, + struct ceph_messenger *msgr, __u8 entity_type, + __u64 entity_num); extern void ceph_con_open(struct ceph_connection *con, struct ceph_entity_addr *addr); extern bool ceph_con_opened(struct ceph_connection *con); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index ca0e4c126f48..6e21e609d791 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -521,15 +521,22 @@ void ceph_con_put(struct ceph_connection *con) /* * initialize a new connection. */ -void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con) +void ceph_con_init(struct ceph_connection *con, void *private, + const struct ceph_connection_operations *ops, + struct ceph_messenger *msgr, __u8 entity_type, __u64 entity_num) { dout("con_init %p\n", con); memset(con, 0, sizeof(*con)); + con->private = private; + con->ops = ops; atomic_set(&con->nref, 1); con->msgr = msgr; con_sock_state_init(con); + con->peer_name.type = (__u8) entity_type; + con->peer_name.num = cpu_to_le64(entity_num); + mutex_init(&con->mutex); INIT_LIST_HEAD(&con->out_queue); INIT_LIST_HEAD(&con->out_sent); diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 1b03493f8749..d3c22b7218c8 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -142,11 +142,9 @@ static int __open_session(struct ceph_mon_client *monc) monc->sub_renew_after = jiffies; /* i.e., expired */ monc->want_next_osdmap = !!monc->want_next_osdmap; - ceph_con_init(&monc->client->msgr, &monc->con); - monc->con.private = monc; - monc->con.ops = &mon_con_ops; - monc->con.peer_name.type = CEPH_ENTITY_TYPE_MON; - monc->con.peer_name.num = cpu_to_le64(monc->cur_mon); + ceph_con_init(&monc->con, monc, &mon_con_ops, + &monc->client->msgr, + CEPH_ENTITY_TYPE_MON, monc->cur_mon); dout("open_session mon%d opening\n", monc->cur_mon); ceph_con_open(&monc->con, diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 5b41a6929cd9..448c9da8beff 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -640,11 +640,8 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum) INIT_LIST_HEAD(&osd->o_osd_lru); osd->o_incarnation = 1; - ceph_con_init(&osdc->client->msgr, &osd->o_con); - osd->o_con.private = osd; - osd->o_con.ops = &osd_con_ops; - osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD; - osd->o_con.peer_name.num = cpu_to_le64(onum); + ceph_con_init(&osd->o_con, osd, &osd_con_ops, &osdc->client->msgr, + CEPH_ENTITY_TYPE_OSD, onum); INIT_LIST_HEAD(&osd->o_keepalive_item); return osd; -- GitLab From 35067a20685e5f51513c3633256e658fc71e847e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 4 Jun 2012 14:43:32 -0500 Subject: [PATCH 1084/1799] libceph: tweak ceph_alloc_msg() (cherry picked from commit 1c20f2d26795803fc4f5155fe4fca5717a5944b6) The function ceph_alloc_msg() is only used to allocate a message that will be assigned to a connection's in_msg pointer. Rename the function so this implied usage is more clear. In addition, make that assignment inside the function (again, since that's precisely what it's intended to be used for). This allows us to return what is now provided via the passed-in address of a "skip" variable. The return type is now Boolean to be explicit that there are only two possible outcomes. Make sure the result of an ->alloc_msg method call always sets the value of *skip properly. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 61 ++++++++++++++++++++++++------------------- net/ceph/mon_client.c | 3 +++ net/ceph/osd_client.c | 1 + 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 6e21e609d791..31e8a15fa28c 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1659,9 +1659,8 @@ static int read_partial_message_section(struct ceph_connection *con, return 1; } -static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, - struct ceph_msg_header *hdr, - int *skip); +static bool ceph_con_in_msg_alloc(struct ceph_connection *con, + struct ceph_msg_header *hdr); static int read_partial_message_pages(struct ceph_connection *con, @@ -1744,7 +1743,6 @@ static int read_partial_message(struct ceph_connection *con) int ret; unsigned front_len, middle_len, data_len; bool do_datacrc = !con->msgr->nocrc; - int skip; u64 seq; u32 crc; @@ -1797,9 +1795,7 @@ static int read_partial_message(struct ceph_connection *con) if (!con->in_msg) { dout("got hdr type %d front %d data %d\n", con->in_hdr.type, con->in_hdr.front_len, con->in_hdr.data_len); - skip = 0; - con->in_msg = ceph_alloc_msg(con, &con->in_hdr, &skip); - if (skip) { + if (ceph_con_in_msg_alloc(con, &con->in_hdr)) { /* skip this message */ dout("alloc_msg said skip message\n"); BUG_ON(con->in_msg); @@ -2581,46 +2577,57 @@ static int ceph_alloc_middle(struct ceph_connection *con, struct ceph_msg *msg) } /* - * Generic message allocator, for incoming messages. + * Allocate a message for receiving an incoming message on a + * connection, and save the result in con->in_msg. Uses the + * connection's private alloc_msg op if available. + * + * Returns true if the message should be skipped, false otherwise. + * If true is returned (skip message), con->in_msg will be NULL. + * If false is returned, con->in_msg will contain a pointer to the + * newly-allocated message, or NULL in case of memory exhaustion. */ -static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, - struct ceph_msg_header *hdr, - int *skip) +static bool ceph_con_in_msg_alloc(struct ceph_connection *con, + struct ceph_msg_header *hdr) { int type = le16_to_cpu(hdr->type); int front_len = le32_to_cpu(hdr->front_len); int middle_len = le32_to_cpu(hdr->middle_len); - struct ceph_msg *msg = NULL; int ret; + BUG_ON(con->in_msg != NULL); + if (con->ops->alloc_msg) { + int skip = 0; + mutex_unlock(&con->mutex); - msg = con->ops->alloc_msg(con, hdr, skip); + con->in_msg = con->ops->alloc_msg(con, hdr, &skip); mutex_lock(&con->mutex); - if (!msg || *skip) - return NULL; + if (skip) + con->in_msg = NULL; + + if (!con->in_msg) + return skip != 0; } - if (!msg) { - *skip = 0; - msg = ceph_msg_new(type, front_len, GFP_NOFS, false); - if (!msg) { + if (!con->in_msg) { + con->in_msg = ceph_msg_new(type, front_len, GFP_NOFS, false); + if (!con->in_msg) { pr_err("unable to allocate msg type %d len %d\n", type, front_len); - return NULL; + return false; } - msg->page_alignment = le16_to_cpu(hdr->data_off); + con->in_msg->page_alignment = le16_to_cpu(hdr->data_off); } - memcpy(&msg->hdr, &con->in_hdr, sizeof(con->in_hdr)); + memcpy(&con->in_msg->hdr, &con->in_hdr, sizeof(con->in_hdr)); - if (middle_len && !msg->middle) { - ret = ceph_alloc_middle(con, msg); + if (middle_len && !con->in_msg->middle) { + ret = ceph_alloc_middle(con, con->in_msg); if (ret < 0) { - ceph_msg_put(msg); - return NULL; + ceph_msg_put(con->in_msg); + con->in_msg = NULL; } } - return msg; + return false; } diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index d3c22b7218c8..674f191341a7 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -442,6 +442,7 @@ static struct ceph_msg *get_generic_reply(struct ceph_connection *con, m = NULL; } else { dout("get_generic_reply %lld got %p\n", tid, req->reply); + *skip = 0; m = ceph_msg_get(req->reply); /* * we don't need to track the connection reading into @@ -990,6 +991,8 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con, case CEPH_MSG_MDS_MAP: case CEPH_MSG_OSD_MAP: m = ceph_msg_new(type, front_len, GFP_NOFS, false); + if (!m) + return NULL; /* ENOMEM--return skip == 0 */ break; } diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 448c9da8beff..24b427b1eca4 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -2077,6 +2077,7 @@ static struct ceph_msg *alloc_msg(struct ceph_connection *con, int type = le16_to_cpu(hdr->type); int front = le32_to_cpu(hdr->front_len); + *skip = 0; switch (type) { case CEPH_MSG_OSD_MAP: case CEPH_MSG_WATCH_NOTIFY: -- GitLab From e84e066e5c8c858d3954b2ef1da25c14309e4cef Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 1 Jun 2012 14:56:43 -0500 Subject: [PATCH 1085/1799] libceph: have messages point to their connection (cherry picked from commit 38941f8031bf042dba3ced6394ba3a3b16c244ea) When a ceph message is queued for sending it is placed on a list of pending messages (ceph_connection->out_queue). When they are actually sent over the wire, they are moved from that list to another (ceph_connection->out_sent). When acknowledgement for the message is received, it is removed from the sent messages list. During that entire time the message is "in the possession" of a single ceph connection. Keep track of that connection in the message. This will be used in the next patch (and is a helpful bit of information for debugging anyway). Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 3 +++ net/ceph/messenger.c | 27 +++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 7ed7a87aa6b5..7d48ffc02c7b 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -77,7 +77,10 @@ struct ceph_msg { unsigned nr_pages; /* size of page array */ unsigned page_alignment; /* io offset in first page */ struct ceph_pagelist *pagelist; /* instead of pages */ + + struct ceph_connection *con; struct list_head list_head; + struct kref kref; struct bio *bio; /* instead of pages/pagelist */ struct bio *bio_iter; /* bio iterator */ diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 31e8a15fa28c..51cf73180260 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -414,6 +414,9 @@ static int con_close_socket(struct ceph_connection *con) static void ceph_msg_remove(struct ceph_msg *msg) { list_del_init(&msg->list_head); + BUG_ON(msg->con == NULL); + msg->con = NULL; + ceph_msg_put(msg); } static void ceph_msg_remove_list(struct list_head *head) @@ -433,6 +436,8 @@ static void reset_connection(struct ceph_connection *con) ceph_msg_remove_list(&con->out_sent); if (con->in_msg) { + BUG_ON(con->in_msg->con != con); + con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; } @@ -625,8 +630,10 @@ static void prepare_write_message(struct ceph_connection *con) &con->out_temp_ack); } + BUG_ON(list_empty(&con->out_queue)); m = list_first_entry(&con->out_queue, struct ceph_msg, list_head); con->out_msg = m; + BUG_ON(m->con != con); /* put message on sent list */ ceph_msg_get(m); @@ -1810,6 +1817,8 @@ static int read_partial_message(struct ceph_connection *con) "error allocating memory for incoming message"; return -ENOMEM; } + + BUG_ON(con->in_msg->con != con); m = con->in_msg; m->front.iov_len = 0; /* haven't read it yet */ if (m->middle) @@ -1905,6 +1914,8 @@ static void process_message(struct ceph_connection *con) { struct ceph_msg *msg; + BUG_ON(con->in_msg->con != con); + con->in_msg->con = NULL; msg = con->in_msg; con->in_msg = NULL; @@ -2264,6 +2275,8 @@ static void ceph_fault(struct ceph_connection *con) con_close_socket(con); if (con->in_msg) { + BUG_ON(con->in_msg->con != con); + con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; } @@ -2382,6 +2395,8 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) /* queue */ mutex_lock(&con->mutex); + BUG_ON(msg->con != NULL); + msg->con = con; BUG_ON(!list_empty(&msg->list_head)); list_add_tail(&msg->list_head, &con->out_queue); dout("----- %p to %s%lld %d=%s len %d+%d+%d -----\n", msg, @@ -2407,13 +2422,16 @@ void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg) { mutex_lock(&con->mutex); if (!list_empty(&msg->list_head)) { - dout("con_revoke %p msg %p - was on queue\n", con, msg); + dout("%s %p msg %p - was on queue\n", __func__, con, msg); list_del_init(&msg->list_head); + BUG_ON(msg->con == NULL); + msg->con = NULL; + ceph_msg_put(msg); msg->hdr.seq = 0; } if (con->out_msg == msg) { - dout("con_revoke %p msg %p - was sending\n", con, msg); + dout("%s %p msg %p - was sending\n", __func__, con, msg); con->out_msg = NULL; if (con->out_kvec_is_msg) { con->out_skip = con->out_kvec_bytes; @@ -2482,6 +2500,8 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags, if (m == NULL) goto out; kref_init(&m->kref); + + m->con = NULL; INIT_LIST_HEAD(&m->list_head); m->hdr.tid = 0; @@ -2602,6 +2622,8 @@ static bool ceph_con_in_msg_alloc(struct ceph_connection *con, mutex_unlock(&con->mutex); con->in_msg = con->ops->alloc_msg(con, hdr, &skip); mutex_lock(&con->mutex); + if (con->in_msg) + con->in_msg->con = con; if (skip) con->in_msg = NULL; @@ -2615,6 +2637,7 @@ static bool ceph_con_in_msg_alloc(struct ceph_connection *con, type, front_len); return false; } + con->in_msg->con = con; con->in_msg->page_alignment = le16_to_cpu(hdr->data_off); } memcpy(&con->in_msg->hdr, &con->in_hdr, sizeof(con->in_hdr)); -- GitLab From bfd357201d3ffc6cc621e4c69fd47e7d457e5f3a Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 4 Jun 2012 14:43:33 -0500 Subject: [PATCH 1086/1799] libceph: have messages take a connection reference (cherry picked from commit 92ce034b5a740046cc643a21ea21eaad589e0043) There are essentially two types of ceph messages: incoming and outgoing. Outgoing messages are always allocated via ceph_msg_new(), and at the time of their allocation they are not associated with any particular connection. Incoming messages are always allocated via ceph_con_in_msg_alloc(), and they are initially associated with the connection from which incoming data will be placed into the message. When an outgoing message gets sent, it becomes associated with a connection and remains that way until the message is successfully sent. The association of an incoming message goes away at the point it is sent to an upper layer via a con->ops->dispatch method. This patch implements reference counting for all ceph messages, such that every message holds a reference (and a pointer) to a connection if and only if it is associated with that connection (as described above). For background, here is an explanation of the ceph message lifecycle, emphasizing when an association exists between a message and a connection. Outgoing Messages An outgoing message is "owned" by its allocator, from the time it is allocated in ceph_msg_new() up to the point it gets queued for sending in ceph_con_send(). Prior to that point the message's msg->con pointer is null; at the point it is queued for sending its message pointer is assigned to refer to the connection. At that time the message is inserted into a connection's out_queue list. When a message on the out_queue list has been sent to the socket layer to be put on the wire, it is transferred out of that list and into the connection's out_sent list. At that point it is still owned by the connection, and will remain so until an acknowledgement is received from the recipient that indicates the message was successfully transferred. When such an acknowledgement is received (in process_ack()), the message is removed from its list (in ceph_msg_remove()), at which point it is no longer associated with the connection. So basically, any time a message is on one of a connection's lists, it is associated with that connection. Reference counting outgoing messages can thus be done at the points a message is added to the out_queue (in ceph_con_send()) and the point it is removed from either its two lists (in ceph_msg_remove())--at which point its connection pointer becomes null. Incoming Messages When an incoming message on a connection is getting read (in read_partial_message()) and there is no message in con->in_msg, a new one is allocated using ceph_con_in_msg_alloc(). At that point the message is associated with the connection. Once that message has been completely and successfully read, it is passed to upper layer code using the connection's con->ops->dispatch method. At that point the association between the message and the connection no longer exists. Reference counting of connections for incoming messages can be done by taking a reference to the connection when the message gets allocated, and releasing that reference when it gets handed off using the dispatch method. We should never fail to get a connection reference for a message--the since the caller should already hold one. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 51cf73180260..9e7da4b8579c 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -415,6 +415,7 @@ static void ceph_msg_remove(struct ceph_msg *msg) { list_del_init(&msg->list_head); BUG_ON(msg->con == NULL); + ceph_con_put(msg->con); msg->con = NULL; ceph_msg_put(msg); @@ -440,6 +441,7 @@ static void reset_connection(struct ceph_connection *con) con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; + ceph_con_put(con->in_msg->con); } con->connect_seq = 0; @@ -1918,6 +1920,7 @@ static void process_message(struct ceph_connection *con) con->in_msg->con = NULL; msg = con->in_msg; con->in_msg = NULL; + ceph_con_put(con); /* if first message, set peer_name */ if (con->peer_name.type == 0) @@ -2279,6 +2282,7 @@ static void ceph_fault(struct ceph_connection *con) con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; + ceph_con_put(con); } /* Requeue anything that hasn't been acked */ @@ -2395,8 +2399,11 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) /* queue */ mutex_lock(&con->mutex); + BUG_ON(msg->con != NULL); - msg->con = con; + msg->con = ceph_con_get(con); + BUG_ON(msg->con == NULL); + BUG_ON(!list_empty(&msg->list_head)); list_add_tail(&msg->list_head, &con->out_queue); dout("----- %p to %s%lld %d=%s len %d+%d+%d -----\n", msg, @@ -2425,10 +2432,11 @@ void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg) dout("%s %p msg %p - was on queue\n", __func__, con, msg); list_del_init(&msg->list_head); BUG_ON(msg->con == NULL); + ceph_con_put(msg->con); msg->con = NULL; + msg->hdr.seq = 0; ceph_msg_put(msg); - msg->hdr.seq = 0; } if (con->out_msg == msg) { dout("%s %p msg %p - was sending\n", __func__, con, msg); @@ -2437,8 +2445,9 @@ void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg) con->out_skip = con->out_kvec_bytes; con->out_kvec_is_msg = false; } - ceph_msg_put(msg); msg->hdr.seq = 0; + + ceph_msg_put(msg); } mutex_unlock(&con->mutex); } @@ -2622,8 +2631,10 @@ static bool ceph_con_in_msg_alloc(struct ceph_connection *con, mutex_unlock(&con->mutex); con->in_msg = con->ops->alloc_msg(con, hdr, &skip); mutex_lock(&con->mutex); - if (con->in_msg) - con->in_msg->con = con; + if (con->in_msg) { + con->in_msg->con = ceph_con_get(con); + BUG_ON(con->in_msg->con == NULL); + } if (skip) con->in_msg = NULL; @@ -2637,7 +2648,8 @@ static bool ceph_con_in_msg_alloc(struct ceph_connection *con, type, front_len); return false; } - con->in_msg->con = con; + con->in_msg->con = ceph_con_get(con); + BUG_ON(con->in_msg->con == NULL); con->in_msg->page_alignment = le16_to_cpu(hdr->data_off); } memcpy(&con->in_msg->hdr, &con->in_hdr, sizeof(con->in_hdr)); -- GitLab From ae048538ab62c31f67d42e00a3183b8870809a3c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 1 Jun 2012 14:56:43 -0500 Subject: [PATCH 1087/1799] libceph: make ceph_con_revoke() a msg operation (cherry picked from commit 6740a845b2543cc46e1902ba21bac743fbadd0dc) ceph_con_revoke() is passed both a message and a ceph connection. Now that any message associated with a connection holds a pointer to that connection, there's no need to provide the connection when revoking a message. This has the added benefit of precluding the possibility of the providing the wrong connection pointer. If the message's connection pointer is null, it is not being tracked by any connection, so revoking it is a no-op. This is supported as a convenience for upper layers, so they can revoke a message that is not actually "in flight." Rename the function ceph_msg_revoke() to reflect that it is really an operation on a message, not a connection. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 3 ++- net/ceph/messenger.c | 7 ++++++- net/ceph/mon_client.c | 8 ++++---- net/ceph/osd_client.c | 4 ++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 7d48ffc02c7b..13bd9cdbeb0e 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -231,7 +231,8 @@ extern void ceph_con_open(struct ceph_connection *con, extern bool ceph_con_opened(struct ceph_connection *con); extern void ceph_con_close(struct ceph_connection *con); extern void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg); -extern void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg); + +extern void ceph_msg_revoke(struct ceph_msg *msg); extern void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg); extern void ceph_con_keepalive(struct ceph_connection *con); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 9e7da4b8579c..96d3eaec7d3c 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2425,8 +2425,13 @@ EXPORT_SYMBOL(ceph_con_send); /* * Revoke a message that was previously queued for send */ -void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg) +void ceph_msg_revoke(struct ceph_msg *msg) { + struct ceph_connection *con = msg->con; + + if (!con) + return; /* Message not in our possession */ + mutex_lock(&con->mutex); if (!list_empty(&msg->list_head)) { dout("%s %p msg %p - was on queue\n", __func__, con, msg); diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 674f191341a7..dc16595d6885 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -106,7 +106,7 @@ static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len) monc->pending_auth = 1; monc->m_auth->front.iov_len = len; monc->m_auth->hdr.front_len = cpu_to_le32(len); - ceph_con_revoke(&monc->con, monc->m_auth); + ceph_msg_revoke(monc->m_auth); ceph_msg_get(monc->m_auth); /* keep our ref */ ceph_con_send(&monc->con, monc->m_auth); } @@ -117,7 +117,7 @@ static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len) static void __close_session(struct ceph_mon_client *monc) { dout("__close_session closing mon%d\n", monc->cur_mon); - ceph_con_revoke(&monc->con, monc->m_auth); + ceph_msg_revoke(monc->m_auth); ceph_con_close(&monc->con); monc->con.private = NULL; monc->cur_mon = -1; @@ -229,7 +229,7 @@ static void __send_subscribe(struct ceph_mon_client *monc) msg->front.iov_len = p - msg->front.iov_base; msg->hdr.front_len = cpu_to_le32(msg->front.iov_len); - ceph_con_revoke(&monc->con, msg); + ceph_msg_revoke(msg); ceph_con_send(&monc->con, ceph_msg_get(msg)); monc->sub_sent = jiffies | 1; /* never 0 */ @@ -688,7 +688,7 @@ static void __resend_generic_request(struct ceph_mon_client *monc) for (p = rb_first(&monc->generic_request_tree); p; p = rb_next(p)) { req = rb_entry(p, struct ceph_mon_generic_request, node); - ceph_con_revoke(&monc->con, req->request); + ceph_msg_revoke(req->request); ceph_con_send(&monc->con, ceph_msg_get(req->request)); } } diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 24b427b1eca4..ad78705a4aff 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -852,7 +852,7 @@ static void __unregister_request(struct ceph_osd_client *osdc, if (req->r_osd) { /* make sure the original request isn't in flight. */ - ceph_con_revoke(&req->r_osd->o_con, req->r_request); + ceph_msg_revoke(req->r_request); list_del_init(&req->r_osd_item); if (list_empty(&req->r_osd->o_requests) && @@ -879,7 +879,7 @@ static void __unregister_request(struct ceph_osd_client *osdc, static void __cancel_request(struct ceph_osd_request *req) { if (req->r_sent && req->r_osd) { - ceph_con_revoke(&req->r_osd->o_con, req->r_request); + ceph_msg_revoke(req->r_request); req->r_sent = 0; } } -- GitLab From ce4516fbb42d2ad5adba4699ebc1703d4e08e821 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 1 Jun 2012 14:56:43 -0500 Subject: [PATCH 1088/1799] libceph: make ceph_con_revoke_message() a msg op (cherry picked from commit 8921d114f5574c6da2cdd00749d185633ecf88f3) ceph_con_revoke_message() is passed both a message and a ceph connection. A ceph_msg allocated for incoming messages on a connection always has a pointer to that connection, so there's no need to provide the connection when revoking such a message. Note that the existing logic does not preclude the message supplied being a null/bogus message pointer. The only user of this interface is the OSD client, and the only value an osd client passes is a request's r_reply field. That is always non-null (except briefly in an error path in ceph_osdc_alloc_request(), and that drops the only reference so the request won't ever have a reply to revoke). So we can safely assume the passed-in message is non-null, but add a BUG_ON() to make it very obvious we are imposing this restriction. Rename the function ceph_msg_revoke_incoming() to reflect that it is really an operation on an incoming message. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 4 ++-- net/ceph/messenger.c | 22 ++++++++++++++++------ net/ceph/osd_client.c | 9 ++++----- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 13bd9cdbeb0e..9c1f755e5c03 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -233,8 +233,8 @@ extern void ceph_con_close(struct ceph_connection *con); extern void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg); extern void ceph_msg_revoke(struct ceph_msg *msg); -extern void ceph_con_revoke_message(struct ceph_connection *con, - struct ceph_msg *msg); +extern void ceph_msg_revoke_incoming(struct ceph_msg *msg); + extern void ceph_con_keepalive(struct ceph_connection *con); extern struct ceph_connection *ceph_con_get(struct ceph_connection *con); extern void ceph_con_put(struct ceph_connection *con); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 96d3eaec7d3c..5ae586813f39 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2460,17 +2460,27 @@ void ceph_msg_revoke(struct ceph_msg *msg) /* * Revoke a message that we may be reading data into */ -void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg) +void ceph_msg_revoke_incoming(struct ceph_msg *msg) { + struct ceph_connection *con; + + BUG_ON(msg == NULL); + if (!msg->con) { + dout("%s msg %p null con\n", __func__, msg); + + return; /* Message not in our possession */ + } + + con = msg->con; mutex_lock(&con->mutex); - if (con->in_msg && con->in_msg == msg) { + if (con->in_msg == msg) { unsigned front_len = le32_to_cpu(con->in_hdr.front_len); unsigned middle_len = le32_to_cpu(con->in_hdr.middle_len); unsigned data_len = le32_to_cpu(con->in_hdr.data_len); /* skip rest of message */ - dout("con_revoke_pages %p msg %p revoked\n", con, msg); - con->in_base_pos = con->in_base_pos - + dout("%s %p msg %p revoked\n", __func__, con, msg); + con->in_base_pos = con->in_base_pos - sizeof(struct ceph_msg_header) - front_len - middle_len - @@ -2481,8 +2491,8 @@ void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg) con->in_tag = CEPH_MSGR_TAG_READY; con->in_seq++; } else { - dout("con_revoke_pages %p msg %p pages %p no-op\n", - con, con->in_msg, msg); + dout("%s %p in_msg %p msg %p no-op\n", + __func__, con, con->in_msg, msg); } mutex_unlock(&con->mutex); } diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index ad78705a4aff..c178c770acb4 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -140,10 +140,9 @@ void ceph_osdc_release_request(struct kref *kref) if (req->r_request) ceph_msg_put(req->r_request); if (req->r_con_filling_msg) { - dout("release_request revoking pages %p from con %p\n", + dout("%s revoking pages %p from con %p\n", __func__, req->r_pages, req->r_con_filling_msg); - ceph_con_revoke_message(req->r_con_filling_msg, - req->r_reply); + ceph_msg_revoke_incoming(req->r_reply); req->r_con_filling_msg->ops->put(req->r_con_filling_msg); } if (req->r_reply) @@ -2022,9 +2021,9 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, } if (req->r_con_filling_msg) { - dout("get_reply revoking msg %p from old con %p\n", + dout("%s revoking msg %p from old con %p\n", __func__, req->r_reply, req->r_con_filling_msg); - ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply); + ceph_msg_revoke_incoming(req->r_reply); req->r_con_filling_msg->ops->put(req->r_con_filling_msg); req->r_con_filling_msg = NULL; } -- GitLab From c66a9c7c10955499d96df63ffd87feaee6b01754 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 6 Jun 2012 19:35:55 -0500 Subject: [PATCH 1089/1799] libceph: fix overflow in __decode_pool_names() (cherry picked from commit ad3b904c07dfa88603689bf9a67bffbb9b99beb5) `len' is read from network and thus needs validation. Otherwise a large `len' would cause out-of-bounds access via the memcpy() call. In addition, len = 0xffffffff would overflow the kmalloc() size, leading to out-of-bounds write. This patch adds a check of `len' via ceph_decode_need(). Also use kstrndup rather than kmalloc/memcpy. [elder@inktank.com: added -ENOMEM return for null kstrndup() result] Signed-off-by: Xi Wang Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/osdmap.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 7173ad54d239..77abb1315866 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -495,15 +495,16 @@ static int __decode_pool_names(void **p, void *end, struct ceph_osdmap *map) ceph_decode_32_safe(p, end, pool, bad); ceph_decode_32_safe(p, end, len, bad); dout(" pool %d len %d\n", pool, len); + ceph_decode_need(p, end, len, bad); pi = __lookup_pg_pool(&map->pg_pools, pool); if (pi) { + char *name = kstrndup(*p, len, GFP_NOFS); + + if (!name) + return -ENOMEM; kfree(pi->name); - pi->name = kmalloc(len + 1, GFP_NOFS); - if (pi->name) { - memcpy(pi->name, *p, len); - pi->name[len] = '\0'; - dout(" name is %s\n", pi->name); - } + pi->name = name; + dout(" name is %s\n", pi->name); } *p += len; } -- GitLab From 6b71f61c321b1fe8d35b75ab573ff46c51e59acc Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 6 Jun 2012 19:35:55 -0500 Subject: [PATCH 1090/1799] libceph: fix overflow in osdmap_decode() (cherry picked from commit e91a9b639a691e0982088b5954eaafb5a25c8f1c) On 32-bit systems, a large `n' would overflow `n * sizeof(u32)' and bypass the check ceph_decode_need(p, end, n * sizeof(u32), bad). It would also overflow the subsequent kmalloc() size, leading to out-of-bounds write. Signed-off-by: Xi Wang Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/osdmap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 77abb1315866..a38ce3f56953 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -674,6 +674,9 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) ceph_decode_need(p, end, sizeof(u32) + sizeof(u64), bad); ceph_decode_copy(p, &pgid, sizeof(pgid)); n = ceph_decode_32(p); + err = -EINVAL; + if (n > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) + goto bad; ceph_decode_need(p, end, n * sizeof(u32), bad); err = -ENOMEM; pg = kmalloc(sizeof(*pg) + n*sizeof(u32), GFP_NOFS); -- GitLab From f4d29a959aa619f3d46e2b685cfb8acac41503db Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 6 Jun 2012 19:35:55 -0500 Subject: [PATCH 1091/1799] libceph: fix overflow in osdmap_apply_incremental() (cherry picked from commit a5506049500b30dbc5edb4d07a3577477c1f3643) On 32-bit systems, a large `pglen' would overflow `pglen*sizeof(u32)' and bypass the check ceph_decode_need(p, end, pglen*sizeof(u32), bad). It would also overflow the subsequent kmalloc() size, leading to out-of-bounds write. Signed-off-by: Xi Wang Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/osdmap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index a38ce3f56953..c77133405ff5 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -900,6 +900,10 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, (void) __remove_pg_mapping(&map->pg_temp, pgid); /* insert */ + if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) { + err = -EINVAL; + goto bad; + } pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); if (!pg) { err = -ENOMEM; -- GitLab From fccbf066b35a05606cdb96eb574eaf310c422125 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Sat, 9 Jun 2012 14:19:21 -0700 Subject: [PATCH 1092/1799] libceph: transition socket state prior to actual connect (cherry picked from commit 89a86be0ce20022f6ede8bccec078dbb3d63caaa) Once we call ->connect(), we are racing against the actual connection, and a subsequent transition from CONNECTING -> CONNECTED. Set the state to CONNECTING before that, under the protection of the mutex, to avoid the race. This was introduced in 928443cd9644e7cfd46f687dbeffda2d1a357ff9, with the original socket state code. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 5ae586813f39..59e418b3597e 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -321,6 +321,7 @@ static int ceph_tcp_connect(struct ceph_connection *con) dout("connect %s\n", ceph_pr_addr(&con->peer_addr.in_addr)); + con_sock_state_connecting(con); ret = sock->ops->connect(sock, (struct sockaddr *)paddr, sizeof(*paddr), O_NONBLOCK); if (ret == -EINPROGRESS) { @@ -336,8 +337,6 @@ static int ceph_tcp_connect(struct ceph_connection *con) return ret; } con->sock = sock; - con_sock_state_connecting(con); - return 0; } -- GitLab From 8124d55a2d2c8d738c6ac5b95e6171fe3d1b5af3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 19 Jun 2012 08:52:33 -0500 Subject: [PATCH 1093/1799] libceph: fix NULL dereference in reset_connection() (cherry picked from commit 26ce171915f348abd1f41da1ed139d93750d987f) We dereference "con->in_msg" on the line after it was set to NULL. Signed-off-by: Dan Carpenter Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 59e418b3597e..7e208969cc42 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -440,7 +440,7 @@ static void reset_connection(struct ceph_connection *con) con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; - ceph_con_put(con->in_msg->con); + ceph_con_put(con); } con->connect_seq = 0; -- GitLab From 1c623b046a6c72666d81afa004f8bf7f70cd4391 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 21 Jun 2012 12:47:08 -0700 Subject: [PATCH 1094/1799] libceph: use con get/put methods (cherry picked from commit 36eb71aa57e6a33d61fd90a2fd87f00c6844bc86) The ceph_con_get/put() helpers manipulate the embedded con ref count, which isn't used now that ceph_connections are embedded in other structures. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 7e208969cc42..eddec08e7877 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -414,7 +414,7 @@ static void ceph_msg_remove(struct ceph_msg *msg) { list_del_init(&msg->list_head); BUG_ON(msg->con == NULL); - ceph_con_put(msg->con); + msg->con->ops->put(msg->con); msg->con = NULL; ceph_msg_put(msg); @@ -440,7 +440,7 @@ static void reset_connection(struct ceph_connection *con) con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; - ceph_con_put(con); + con->ops->put(con); } con->connect_seq = 0; @@ -1919,7 +1919,7 @@ static void process_message(struct ceph_connection *con) con->in_msg->con = NULL; msg = con->in_msg; con->in_msg = NULL; - ceph_con_put(con); + con->ops->put(con); /* if first message, set peer_name */ if (con->peer_name.type == 0) @@ -2281,7 +2281,7 @@ static void ceph_fault(struct ceph_connection *con) con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; - ceph_con_put(con); + con->ops->put(con); } /* Requeue anything that hasn't been acked */ @@ -2400,7 +2400,7 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) mutex_lock(&con->mutex); BUG_ON(msg->con != NULL); - msg->con = ceph_con_get(con); + msg->con = con->ops->get(con); BUG_ON(msg->con == NULL); BUG_ON(!list_empty(&msg->list_head)); @@ -2436,7 +2436,7 @@ void ceph_msg_revoke(struct ceph_msg *msg) dout("%s %p msg %p - was on queue\n", __func__, con, msg); list_del_init(&msg->list_head); BUG_ON(msg->con == NULL); - ceph_con_put(msg->con); + msg->con->ops->put(msg->con); msg->con = NULL; msg->hdr.seq = 0; @@ -2646,7 +2646,7 @@ static bool ceph_con_in_msg_alloc(struct ceph_connection *con, con->in_msg = con->ops->alloc_msg(con, hdr, &skip); mutex_lock(&con->mutex); if (con->in_msg) { - con->in_msg->con = ceph_con_get(con); + con->in_msg->con = con->ops->get(con); BUG_ON(con->in_msg->con == NULL); } if (skip) @@ -2662,7 +2662,7 @@ static bool ceph_con_in_msg_alloc(struct ceph_connection *con, type, front_len); return false; } - con->in_msg->con = ceph_con_get(con); + con->in_msg->con = con->ops->get(con); BUG_ON(con->in_msg->con == NULL); con->in_msg->page_alignment = le16_to_cpu(hdr->data_off); } -- GitLab From 9021a42c794bf96156be9ad556ef707814a361ff Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 21 Jun 2012 12:49:23 -0700 Subject: [PATCH 1095/1799] libceph: drop ceph_con_get/put helpers and nref member (cherry picked from commit d59315ca8c0de00df9b363f94a2641a30961ca1c) These are no longer used. Every ceph_connection instance is embedded in another structure, and refcounts manipulated via the get/put ops. Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 1 - net/ceph/messenger.c | 28 +--------------------------- 2 files changed, 1 insertion(+), 28 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 9c1f755e5c03..f624b752e823 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -135,7 +135,6 @@ struct ceph_msg_pos { */ struct ceph_connection { void *private; - atomic_t nref; const struct ceph_connection_operations *ops; diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index eddec08e7877..bc43a042b3e6 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -500,30 +500,6 @@ bool ceph_con_opened(struct ceph_connection *con) return con->connect_seq > 0; } -/* - * generic get/put - */ -struct ceph_connection *ceph_con_get(struct ceph_connection *con) -{ - int nref = __atomic_add_unless(&con->nref, 1, 0); - - dout("con_get %p nref = %d -> %d\n", con, nref, nref + 1); - - return nref ? con : NULL; -} - -void ceph_con_put(struct ceph_connection *con) -{ - int nref = atomic_dec_return(&con->nref); - - BUG_ON(nref < 0); - if (nref == 0) { - BUG_ON(con->sock); - kfree(con); - } - dout("con_put %p nref = %d -> %d\n", con, nref + 1, nref); -} - /* * initialize a new connection. */ @@ -535,7 +511,6 @@ void ceph_con_init(struct ceph_connection *con, void *private, memset(con, 0, sizeof(*con)); con->private = private; con->ops = ops; - atomic_set(&con->nref, 1); con->msgr = msgr; con_sock_state_init(con); @@ -1951,8 +1926,7 @@ static int try_write(struct ceph_connection *con) { int ret = 1; - dout("try_write start %p state %lu nref %d\n", con, con->state, - atomic_read(&con->nref)); + dout("try_write start %p state %lu\n", con, con->state); more: dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes); -- GitLab From 4ecff48cef44be80eccfa0b3864d55f446006dc5 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1096/1799] libceph: encapsulate out message data setup (cherry picked from commit 739c905baa018c99003564ebc367d93aa44d4861) Move the code that prepares to write the data portion of a message into its own function. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index bc43a042b3e6..3c5e2061e196 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -565,6 +565,24 @@ static void con_out_kvec_add(struct ceph_connection *con, con->out_kvec_bytes += size; } +static void prepare_write_message_data(struct ceph_connection *con) +{ + struct ceph_msg *msg = con->out_msg; + + BUG_ON(!msg); + BUG_ON(!msg->hdr.data_len); + + /* initialize page iterator */ + con->out_msg_pos.page = 0; + if (msg->pages) + con->out_msg_pos.page_pos = msg->page_alignment; + else + con->out_msg_pos.page_pos = 0; + con->out_msg_pos.data_pos = 0; + con->out_msg_pos.did_page_crc = false; + con->out_more = 1; /* data + footer will follow */ +} + /* * Prepare footer for currently outgoing message, and finish things * off. Assumes out_kvec* are already valid.. we just add on to the end. @@ -657,26 +675,17 @@ static void prepare_write_message(struct ceph_connection *con) con->out_msg->footer.middle_crc = cpu_to_le32(crc); } else con->out_msg->footer.middle_crc = 0; - con->out_msg->footer.data_crc = 0; - dout("prepare_write_message front_crc %u data_crc %u\n", + dout("%s front_crc %u middle_crc %u\n", __func__, le32_to_cpu(con->out_msg->footer.front_crc), le32_to_cpu(con->out_msg->footer.middle_crc)); /* is there a data payload? */ - if (le32_to_cpu(m->hdr.data_len) > 0) { - /* initialize page iterator */ - con->out_msg_pos.page = 0; - if (m->pages) - con->out_msg_pos.page_pos = m->page_alignment; - else - con->out_msg_pos.page_pos = 0; - con->out_msg_pos.data_pos = 0; - con->out_msg_pos.did_page_crc = false; - con->out_more = 1; /* data + footer will follow */ - } else { + con->out_msg->footer.data_crc = 0; + if (m->hdr.data_len) + prepare_write_message_data(con); + else /* no, queue up footer too and be done */ prepare_write_message_footer(con); - } set_bit(WRITE_PENDING, &con->flags); } -- GitLab From 3c968ed12fad908a5d3676b8d3150b9ac167841c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1097/1799] libceph: encapsulate advancing msg page (cherry picked from commit 84ca8fc87fcf4ab97bb8acdb59bf97bb4820cb14) In write_partial_msg_pages(), once all the data from a page has been sent we advance to the next one. Put the code that takes care of this into its own function. While modifying write_partial_msg_pages(), make its local variable "in_trail" be Boolean, and use the local variable "msg" (which is just the connection's current out_msg pointer) consistently. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 58 ++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 3c5e2061e196..55ccd99558b9 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -891,6 +891,33 @@ static void iter_bio_next(struct bio **bio_iter, int *seg) } #endif +static void out_msg_pos_next(struct ceph_connection *con, struct page *page, + size_t len, size_t sent, bool in_trail) +{ + struct ceph_msg *msg = con->out_msg; + + BUG_ON(!msg); + BUG_ON(!sent); + + con->out_msg_pos.data_pos += sent; + con->out_msg_pos.page_pos += sent; + if (sent == len) { + con->out_msg_pos.page_pos = 0; + con->out_msg_pos.page++; + con->out_msg_pos.did_page_crc = false; + if (in_trail) + list_move_tail(&page->lru, + &msg->trail->head); + else if (msg->pagelist) + list_move_tail(&page->lru, + &msg->pagelist->head); +#ifdef CONFIG_BLOCK + else if (msg->bio) + iter_bio_next(&msg->bio_iter, &msg->bio_seg); +#endif + } +} + /* * Write as much message data payload as we can. If we finish, queue * up the footer. @@ -906,11 +933,11 @@ static int write_partial_msg_pages(struct ceph_connection *con) bool do_datacrc = !con->msgr->nocrc; int ret; int total_max_write; - int in_trail = 0; + bool in_trail = false; size_t trail_len = (msg->trail ? msg->trail->length : 0); dout("write_partial_msg_pages %p msg %p page %d/%d offset %d\n", - con, con->out_msg, con->out_msg_pos.page, con->out_msg->nr_pages, + con, msg, con->out_msg_pos.page, msg->nr_pages, con->out_msg_pos.page_pos); #ifdef CONFIG_BLOCK @@ -934,13 +961,12 @@ static int write_partial_msg_pages(struct ceph_connection *con) /* have we reached the trail part of the data? */ if (con->out_msg_pos.data_pos >= data_len - trail_len) { - in_trail = 1; + in_trail = true; total_max_write = data_len - con->out_msg_pos.data_pos; page = list_first_entry(&msg->trail->head, struct page, lru); - max_write = PAGE_SIZE; } else if (msg->pages) { page = msg->pages[con->out_msg_pos.page]; } else if (msg->pagelist) { @@ -964,14 +990,14 @@ static int write_partial_msg_pages(struct ceph_connection *con) if (do_datacrc && !con->out_msg_pos.did_page_crc) { void *base; u32 crc; - u32 tmpcrc = le32_to_cpu(con->out_msg->footer.data_crc); + u32 tmpcrc = le32_to_cpu(msg->footer.data_crc); char *kaddr; kaddr = kmap(page); BUG_ON(kaddr == NULL); base = kaddr + con->out_msg_pos.page_pos + bio_offset; crc = crc32c(tmpcrc, base, len); - con->out_msg->footer.data_crc = cpu_to_le32(crc); + msg->footer.data_crc = cpu_to_le32(crc); con->out_msg_pos.did_page_crc = true; } ret = ceph_tcp_sendpage(con->sock, page, @@ -984,30 +1010,14 @@ static int write_partial_msg_pages(struct ceph_connection *con) if (ret <= 0) goto out; - con->out_msg_pos.data_pos += ret; - con->out_msg_pos.page_pos += ret; - if (ret == len) { - con->out_msg_pos.page_pos = 0; - con->out_msg_pos.page++; - con->out_msg_pos.did_page_crc = false; - if (in_trail) - list_move_tail(&page->lru, - &msg->trail->head); - else if (msg->pagelist) - list_move_tail(&page->lru, - &msg->pagelist->head); -#ifdef CONFIG_BLOCK - else if (msg->bio) - iter_bio_next(&msg->bio_iter, &msg->bio_seg); -#endif - } + out_msg_pos_next(con, page, len, (size_t) ret, in_trail); } dout("write_partial_msg_pages %p msg %p done\n", con, msg); /* prepare and queue up footer, too */ if (!do_datacrc) - con->out_msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; + msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; con_out_kvec_reset(con); prepare_write_message_footer(con); ret = 1; -- GitLab From 3b17b0bb2b1dcfa3e8aee9ce7ee5c239b1109b72 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1098/1799] libceph: don't mark footer complete before it is (cherry picked from commit fd154f3c75465abd83b7a395033e3755908a1e6e) This is a nit, but prepare_write_message() sets the FOOTER_COMPLETE flag before the CRC for the data portion (recorded in the footer) has been completely computed. Hold off setting the complete flag until we've decided it's ready to send. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 55ccd99558b9..95f2cda3c37e 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -592,6 +592,8 @@ static void prepare_write_message_footer(struct ceph_connection *con) struct ceph_msg *m = con->out_msg; int v = con->out_kvec_left; + m->footer.flags |= CEPH_MSG_FOOTER_COMPLETE; + dout("prepare_write_message_footer %p\n", con); con->out_kvec_is_msg = true; con->out_kvec[v].iov_base = &m->footer; @@ -665,7 +667,7 @@ static void prepare_write_message(struct ceph_connection *con) /* fill in crc (except data pages), footer */ crc = crc32c(0, &m->hdr, offsetof(struct ceph_msg_header, crc)); con->out_msg->hdr.crc = cpu_to_le32(crc); - con->out_msg->footer.flags = CEPH_MSG_FOOTER_COMPLETE; + con->out_msg->footer.flags = 0; crc = crc32c(0, m->front.iov_base, m->front.iov_len); con->out_msg->footer.front_crc = cpu_to_le32(crc); -- GitLab From ec53635e8f11ddf452f69d93eb562c3c5eada75f Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1099/1799] libceph: move init_bio_*() functions up (cherry picked from commit df6ad1f97342ebc4270128222e896541405eecdb) Move init_bio_iter() and iter_bio_next() up in their source file so the'll be defined before they're needed. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 50 ++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 95f2cda3c37e..f35f0c382c6f 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -565,6 +565,31 @@ static void con_out_kvec_add(struct ceph_connection *con, con->out_kvec_bytes += size; } +#ifdef CONFIG_BLOCK +static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg) +{ + if (!bio) { + *iter = NULL; + *seg = 0; + return; + } + *iter = bio; + *seg = bio->bi_idx; +} + +static void iter_bio_next(struct bio **bio_iter, int *seg) +{ + if (*bio_iter == NULL) + return; + + BUG_ON(*seg >= (*bio_iter)->bi_vcnt); + + (*seg)++; + if (*seg == (*bio_iter)->bi_vcnt) + init_bio_iter((*bio_iter)->bi_next, bio_iter, seg); +} +#endif + static void prepare_write_message_data(struct ceph_connection *con) { struct ceph_msg *msg = con->out_msg; @@ -868,31 +893,6 @@ static int write_partial_kvec(struct ceph_connection *con) return ret; /* done! */ } -#ifdef CONFIG_BLOCK -static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg) -{ - if (!bio) { - *iter = NULL; - *seg = 0; - return; - } - *iter = bio; - *seg = bio->bi_idx; -} - -static void iter_bio_next(struct bio **bio_iter, int *seg) -{ - if (*bio_iter == NULL) - return; - - BUG_ON(*seg >= (*bio_iter)->bi_vcnt); - - (*seg)++; - if (*seg == (*bio_iter)->bi_vcnt) - init_bio_iter((*bio_iter)->bi_next, bio_iter, seg); -} -#endif - static void out_msg_pos_next(struct ceph_connection *con, struct page *page, size_t len, size_t sent, bool in_trail) { -- GitLab From 67e5007aca705782360373d36613827ebe9e2f36 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1100/1799] libceph: move init of bio_iter (cherry picked from commit 572c588edadaa3da3992bd8a0fed830bbcc861f8) If a message has a non-null bio pointer, its bio_iter field is initialized in write_partial_msg_pages() if this has not been done already. This is really a one-time setup operation for sending a message's (bio) data, so move that initialization code into prepare_write_message_data() which serves that purpose. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index f35f0c382c6f..0c097b0dba9d 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -603,6 +603,10 @@ static void prepare_write_message_data(struct ceph_connection *con) con->out_msg_pos.page_pos = msg->page_alignment; else con->out_msg_pos.page_pos = 0; +#ifdef CONFIG_BLOCK + if (msg->bio && !msg->bio_iter) + init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg); +#endif con->out_msg_pos.data_pos = 0; con->out_msg_pos.did_page_crc = false; con->out_more = 1; /* data + footer will follow */ @@ -942,11 +946,6 @@ static int write_partial_msg_pages(struct ceph_connection *con) con, msg, con->out_msg_pos.page, msg->nr_pages, con->out_msg_pos.page_pos); -#ifdef CONFIG_BLOCK - if (msg->bio && !msg->bio_iter) - init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg); -#endif - while (data_len > con->out_msg_pos.data_pos) { struct page *page = NULL; int max_write = PAGE_SIZE; -- GitLab From f8920642ec1913872f1af07aa8bcb3570bf6ec77 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1101/1799] libceph: don't use bio_iter as a flag (cherry picked from commit abdaa6a849af1d63153682c11f5bbb22dacb1f6b) Recently a bug was fixed in which the bio_iter field in a ceph message was not being properly re-initialized when a message got re-transmitted: commit 43643528cce60ca184fe8197efa8e8da7c89a037 Author: Yan, Zheng rbd: Clear ceph_msg->bio_iter for retransmitted message We are now only initializing the bio_iter field when we are about to start to write message data (in prepare_write_message_data()), rather than every time we are attempting to write any portion of the message data (in write_partial_msg_pages()). This means we no longer need to use the msg->bio_iter field as a flag. So just don't do that any more. Trust prepare_write_message_data() to ensure msg->bio_iter is properly initialized, every time we are about to begin writing (or re-writing) a message's bio data. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 0c097b0dba9d..f0499fe069a5 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -604,7 +604,7 @@ static void prepare_write_message_data(struct ceph_connection *con) else con->out_msg_pos.page_pos = 0; #ifdef CONFIG_BLOCK - if (msg->bio && !msg->bio_iter) + if (msg->bio) init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg); #endif con->out_msg_pos.data_pos = 0; @@ -672,10 +672,6 @@ static void prepare_write_message(struct ceph_connection *con) m->hdr.seq = cpu_to_le64(++con->out_seq); m->needs_out_seq = false; } -#ifdef CONFIG_BLOCK - else - m->bio_iter = NULL; -#endif dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n", m, con->out_seq, le16_to_cpu(m->hdr.type), -- GitLab From eb8c5642db57af9577ebfea7ff9e96eadbf596b8 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 20 Jun 2012 21:53:53 -0500 Subject: [PATCH 1102/1799] libceph: SOCK_CLOSED is a flag, not a state (cherry picked from commit a8d00e3cdef4c1c4f194414b72b24cd995439a05) The following commit changed it so SOCK_CLOSED bit was stored in a connection's new "flags" field rather than its "state" field. libceph: start separating connection flags from state commit 928443cd That bit is used in con_close_socket() to protect against setting an error message more than once in the socket event handler function. Unfortunately, the field being operated on in that function was not updated to be "flags" as it should have been. This fixes that error. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index f0499fe069a5..edcf5eb22b49 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -397,11 +397,11 @@ static int con_close_socket(struct ceph_connection *con) dout("con_close_socket on %p sock %p\n", con, con->sock); if (!con->sock) return 0; - set_bit(SOCK_CLOSED, &con->state); + set_bit(SOCK_CLOSED, &con->flags); rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR); sock_release(con->sock); con->sock = NULL; - clear_bit(SOCK_CLOSED, &con->state); + clear_bit(SOCK_CLOSED, &con->flags); con_sock_state_closed(con); return rc; } -- GitLab From 54942c5326f039a40c407a251175cd3925ce2951 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 20 Jun 2012 21:53:53 -0500 Subject: [PATCH 1103/1799] libceph: don't change socket state on sock event (cherry picked from commit 188048bce311ee41e5178bc3255415d0eae28423) Currently the socket state change event handler records an error message on a connection to distinguish a close while connecting from a close while a connection was already established. Changing connection information during handling of a socket event is not very clean, so instead move this assignment inside con_work(), where it can be done during normal connection-level processing (and under protection of the connection mutex as well). Move the handling of a socket closed event up to the top of the processing loop in con_work(); there's no point in handling backoff etc. if we have a newly-closed socket to take care of. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index edcf5eb22b49..ed922b7c05be 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -261,13 +261,8 @@ static void ceph_sock_state_change(struct sock *sk) case TCP_CLOSE_WAIT: dout("%s TCP_CLOSE_WAIT\n", __func__); con_sock_state_closing(con); - if (test_and_set_bit(SOCK_CLOSED, &con->flags) == 0) { - if (test_bit(CONNECTING, &con->state)) - con->error_msg = "connection failed"; - else - con->error_msg = "socket closed"; + if (!test_and_set_bit(SOCK_CLOSED, &con->flags)) queue_con(con); - } break; case TCP_ESTABLISHED: dout("%s TCP_ESTABLISHED\n", __func__); @@ -2187,6 +2182,14 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: + if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { + if (test_bit(CONNECTING, &con->state)) + con->error_msg = "connection failed"; + else + con->error_msg = "socket closed"; + goto fault; + } + if (test_and_clear_bit(BACKOFF, &con->flags)) { dout("con_work %p backing off\n", con); if (queue_delayed_work(ceph_msgr_wq, &con->work, @@ -2216,9 +2219,6 @@ static void con_work(struct work_struct *work) con_close_socket(con); } - if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) - goto fault; - ret = try_read(con); if (ret == -EAGAIN) goto restart; -- GitLab From 70b06043cd9aebf15319ce3917196ff032dc20dd Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 20 Jun 2012 21:53:53 -0500 Subject: [PATCH 1104/1799] libceph: just set SOCK_CLOSED when state changes (cherry picked from commit d65c9e0b9eb43d14ece9dd843506ccba06162ee7) When a TCP_CLOSE or TCP_CLOSE_WAIT event occurs, the SOCK_CLOSED connection flag bit is set, and if it had not been previously set queue_con() is called to ensure con_work() will get a chance to handle the changed state. con_work() atomically checks--and if set, clears--the SOCK_CLOSED bit if it was set. This means that even if the bit were set repeatedly, the related processing in con_work() only gets called once per transition of the bit from 0 to 1. What's important then is that we ensure con_work() gets called *at least* once when a socket close event occurs, not that it gets called *exactly* once. The work queue mechanism already takes care of queueing work only if it is not already queued, so there's no need for us to call queue_con() conditionally. So this patch just makes it so the SOCK_CLOSED flag gets set unconditionally in ceph_sock_state_change(). Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index ed922b7c05be..f8ca57805b18 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -261,8 +261,8 @@ static void ceph_sock_state_change(struct sock *sk) case TCP_CLOSE_WAIT: dout("%s TCP_CLOSE_WAIT\n", __func__); con_sock_state_closing(con); - if (!test_and_set_bit(SOCK_CLOSED, &con->flags)) - queue_con(con); + set_bit(SOCK_CLOSED, &con->flags); + queue_con(con); break; case TCP_ESTABLISHED: dout("%s TCP_ESTABLISHED\n", __func__); -- GitLab From 8a62c3339d5455c46c1da1e9fb9b60df20e59905 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 20 Jun 2012 21:53:53 -0500 Subject: [PATCH 1105/1799] libceph: don't touch con state in con_close_socket() (cherry picked from commit 456ea46865787283088b23a8a7f69244513b95f0) In con_close_socket(), a connection's SOCK_CLOSED flag gets set and then cleared while its shutdown method is called and its reference gets dropped. Previously, that flag got set only if it had not already been set, so setting it in con_close_socket() might have prevented additional processing being done on a socket being shut down. We no longer set SOCK_CLOSED in the socket event routine conditionally, so setting that bit here no longer provides whatever benefit it might have provided before. A race condition could still leave the SOCK_CLOSED bit set even after we've issued the call to con_close_socket(), so we still clear that bit after shutting the socket down. Add a comment explaining the reason for this. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index f8ca57805b18..8edd3052d344 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -392,10 +392,16 @@ static int con_close_socket(struct ceph_connection *con) dout("con_close_socket on %p sock %p\n", con, con->sock); if (!con->sock) return 0; - set_bit(SOCK_CLOSED, &con->flags); rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR); sock_release(con->sock); con->sock = NULL; + + /* + * Forcibly clear the SOCK_CLOSE flag. It gets set + * independent of the connection mutex, and we could have + * received a socket close event before we had the chance to + * shut the socket down. + */ clear_bit(SOCK_CLOSED, &con->flags); con_sock_state_closed(con); return rc; -- GitLab From 2a281c7aa696af085db44154d053a169e4b07449 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 20 Jun 2012 21:53:53 -0500 Subject: [PATCH 1106/1799] libceph: clear CONNECTING in ceph_con_close() (cherry picked from commit bb9e6bba5d8b85b631390f8dbe8a24ae1ff5b48a) A connection that is closed will no longer be connecting. So clear the CONNECTING state bit in ceph_con_close(). Similarly, if the socket has been closed we no longer are in connecting state (a new connect sequence will need to be initiated). Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 8edd3052d344..7d3ce898e6d0 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -462,6 +462,7 @@ void ceph_con_close(struct ceph_connection *con) dout("con_close %p peer %s\n", con, ceph_pr_addr(&con->peer_addr.in_addr)); clear_bit(NEGOTIATING, &con->state); + clear_bit(CONNECTING, &con->state); clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */ set_bit(CLOSED, &con->state); @@ -2189,7 +2190,7 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { - if (test_bit(CONNECTING, &con->state)) + if (test_and_clear_bit(CONNECTING, &con->state)) con->error_msg = "connection failed"; else con->error_msg = "socket closed"; -- GitLab From abb46df87f784b398bcdb5091175d24456e42f11 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 23 May 2012 14:35:23 -0500 Subject: [PATCH 1107/1799] libceph: clear NEGOTIATING when done (cherry picked from commit 3ec50d1868a9e0493046400bb1fdd054c7f64ebd) A connection state's NEGOTIATING bit gets set while in CONNECTING state after we have successfully exchanged a ceph banner and IP addresses with the connection's peer (the server). But that bit is not cleared again--at least not until another connection attempt is initiated. Instead, clear it as soon as the connection is fully established. Also, clear it when a socket connection gets prematurely closed in the midst of establishing a ceph connection (in case we had reached the point where it was set). Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 7d3ce898e6d0..aa911e22edbf 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1562,6 +1562,7 @@ static int process_connect(struct ceph_connection *con) fail_protocol(con); return -1; } + clear_bit(NEGOTIATING, &con->state); clear_bit(CONNECTING, &con->state); con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); con->connect_seq++; @@ -1951,7 +1952,6 @@ static int try_write(struct ceph_connection *con) /* open the socket first? */ if (con->sock == NULL) { - clear_bit(NEGOTIATING, &con->state); set_bit(CONNECTING, &con->state); con_out_kvec_reset(con); @@ -2190,10 +2190,12 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { - if (test_and_clear_bit(CONNECTING, &con->state)) + if (test_and_clear_bit(CONNECTING, &con->state)) { + clear_bit(NEGOTIATING, &con->state); con->error_msg = "connection failed"; - else + } else { con->error_msg = "socket closed"; + } goto fault; } -- GitLab From a94af04be86f81d5e3973a37e6a861f329418f1e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 23 May 2012 14:35:23 -0500 Subject: [PATCH 1108/1799] libceph: define and use an explicit CONNECTED state (cherry picked from commit e27947c767f5bed15048f4e4dad3e2eb69133697) There is no state explicitly defined when a ceph connection is fully operational. So define one. It's set when the connection sequence completes successfully, and is cleared when the connection gets closed. Be a little more careful when examining the old state when a socket disconnect event is reported. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 1 + net/ceph/messenger.c | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index f624b752e823..6a00acc61d47 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -120,6 +120,7 @@ struct ceph_msg_pos { */ #define CONNECTING 1 #define NEGOTIATING 2 +#define CONNECTED 5 #define STANDBY 8 /* no outgoing messages, socket closed. we keep * the ceph_connection around to maintain shared * state with the peer. */ diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index aa911e22edbf..2a78d5c47b1e 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -463,6 +463,7 @@ void ceph_con_close(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr)); clear_bit(NEGOTIATING, &con->state); clear_bit(CONNECTING, &con->state); + clear_bit(CONNECTED, &con->state); clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */ set_bit(CLOSED, &con->state); @@ -1564,6 +1565,7 @@ static int process_connect(struct ceph_connection *con) } clear_bit(NEGOTIATING, &con->state); clear_bit(CONNECTING, &con->state); + set_bit(CONNECTED, &con->state); con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); con->connect_seq++; con->peer_features = server_feat; @@ -2114,6 +2116,7 @@ static int try_read(struct ceph_connection *con) prepare_read_ack(con); break; case CEPH_MSGR_TAG_CLOSE: + clear_bit(CONNECTED, &con->state); set_bit(CLOSED, &con->state); /* fixme */ goto out; default: @@ -2190,11 +2193,13 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { - if (test_and_clear_bit(CONNECTING, &con->state)) { + if (test_and_clear_bit(CONNECTED, &con->state)) + con->error_msg = "socket closed"; + else if (test_and_clear_bit(CONNECTING, &con->state)) { clear_bit(NEGOTIATING, &con->state); con->error_msg = "connection failed"; } else { - con->error_msg = "socket closed"; + con->error_msg = "unrecognized con state"; } goto fault; } -- GitLab From 05a24ecce18262f17aa0b28a6bf1191a2a456975 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 31 May 2012 11:37:29 -0500 Subject: [PATCH 1109/1799] libceph: separate banner and connect writes (cherry picked from commit ab166d5aa3bc036fba7efaca6e4e43a7e9510acf) There are two phases in the process of linking together the two ends of a ceph connection. The first involves exchanging a banner and IP addresses, and if that is successful a second phase exchanges some detail about each side's connection capabilities. When initiating a connection, the client side now queues to send its information for both phases of this process at the same time. This is probably a bit more efficient, but it is slightly messier from a layering perspective in the code. So rearrange things so that the client doesn't send the connection information until it has received and processed the response in the initial banner phase (in process_banner()). Move the code (in the (con->sock == NULL) case in try_write()) that prepares for writing the connection information, delaying doing that until the banner exchange has completed. Move the code that begins the transition to this second "NEGOTIATING" phase out of process_banner() and into its caller, so preparing to write the connection information and preparing to read the response are adjacent to each other. Finally, preparing to write the connection information now requires the output kvec to be reset in all cases, so move that into the prepare_write_connect() and delete it from all callers. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 2a78d5c47b1e..7df64aed5f14 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -841,6 +841,7 @@ static int prepare_write_connect(struct ceph_connection *con) con->out_connect.authorizer_len = auth ? cpu_to_le32(auth->authorizer_buf_len) : 0; + con_out_kvec_reset(con); con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); if (auth && auth->authorizer_buf_len) @@ -1430,8 +1431,6 @@ static int process_banner(struct ceph_connection *con) ceph_pr_addr(&con->msgr->inst.addr.in_addr)); } - set_bit(NEGOTIATING, &con->state); - prepare_read_connect(con); return 0; } @@ -1481,7 +1480,6 @@ static int process_connect(struct ceph_connection *con) return -1; } con->auth_retry = 1; - con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1502,7 +1500,6 @@ static int process_connect(struct ceph_connection *con) ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr)); reset_connection(con); - con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1528,7 +1525,6 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->out_connect.connect_seq), le32_to_cpu(con->in_reply.connect_seq)); con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); - con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1545,7 +1541,6 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_reply.global_seq)); get_global_seq(con->msgr, le32_to_cpu(con->in_reply.global_seq)); - con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1958,9 +1953,6 @@ static int try_write(struct ceph_connection *con) con_out_kvec_reset(con); prepare_write_banner(con); - ret = prepare_write_connect(con); - if (ret < 0) - goto out; prepare_read_banner(con); BUG_ON(con->in_msg); @@ -2073,6 +2065,16 @@ static int try_read(struct ceph_connection *con) ret = process_banner(con); if (ret < 0) goto out; + + /* Banner is good, exchange connection info */ + ret = prepare_write_connect(con); + if (ret < 0) + goto out; + prepare_read_connect(con); + set_bit(NEGOTIATING, &con->state); + + /* Send connection info before awaiting response */ + goto out; } ret = read_partial_connect(con); if (ret <= 0) -- GitLab From 8a0566f6aac534a20ed436e3bed56b736cef4c40 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 24 May 2012 11:55:03 -0500 Subject: [PATCH 1110/1799] libceph: distinguish two phases of connect sequence (cherry picked from commit 7593af920baac37752190a0db703d2732bed4a3b) Currently a ceph connection enters a "CONNECTING" state when it begins the process of (re-)connecting with its peer. Once the two ends have successfully exchanged their banner and addresses, an additional NEGOTIATING bit is set in the ceph connection's state to indicate the connection information exhange has begun. The CONNECTING bit/state continues to be set during this phase. Rather than have the CONNECTING state continue while the NEGOTIATING bit is set, interpret these two phases as distinct states. In other words, when NEGOTIATING is set, clear CONNECTING. That way only one of them will be active at a time. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 52 ++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 7df64aed5f14..1db6b68c2e40 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1559,7 +1559,6 @@ static int process_connect(struct ceph_connection *con) return -1; } clear_bit(NEGOTIATING, &con->state); - clear_bit(CONNECTING, &con->state); set_bit(CONNECTED, &con->state); con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); con->connect_seq++; @@ -2000,7 +1999,8 @@ static int try_write(struct ceph_connection *con) } do_next: - if (!test_bit(CONNECTING, &con->state)) { + if (!test_bit(CONNECTING, &con->state) && + !test_bit(NEGOTIATING, &con->state)) { /* is anything else pending? */ if (!list_empty(&con->out_queue)) { prepare_write_message(con); @@ -2057,25 +2057,29 @@ static int try_read(struct ceph_connection *con) } if (test_bit(CONNECTING, &con->state)) { - if (!test_bit(NEGOTIATING, &con->state)) { - dout("try_read connecting\n"); - ret = read_partial_banner(con); - if (ret <= 0) - goto out; - ret = process_banner(con); - if (ret < 0) - goto out; - - /* Banner is good, exchange connection info */ - ret = prepare_write_connect(con); - if (ret < 0) - goto out; - prepare_read_connect(con); - set_bit(NEGOTIATING, &con->state); - - /* Send connection info before awaiting response */ + dout("try_read connecting\n"); + ret = read_partial_banner(con); + if (ret <= 0) goto out; - } + ret = process_banner(con); + if (ret < 0) + goto out; + + clear_bit(CONNECTING, &con->state); + set_bit(NEGOTIATING, &con->state); + + /* Banner is good, exchange connection info */ + ret = prepare_write_connect(con); + if (ret < 0) + goto out; + prepare_read_connect(con); + + /* Send connection info before awaiting response */ + goto out; + } + + if (test_bit(NEGOTIATING, &con->state)) { + dout("try_read negotiating\n"); ret = read_partial_connect(con); if (ret <= 0) goto out; @@ -2197,12 +2201,12 @@ static void con_work(struct work_struct *work) if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { if (test_and_clear_bit(CONNECTED, &con->state)) con->error_msg = "socket closed"; - else if (test_and_clear_bit(CONNECTING, &con->state)) { - clear_bit(NEGOTIATING, &con->state); + else if (test_and_clear_bit(NEGOTIATING, &con->state)) + con->error_msg = "negotiation failed"; + else if (test_and_clear_bit(CONNECTING, &con->state)) con->error_msg = "connection failed"; - } else { + else con->error_msg = "unrecognized con state"; - } goto fault; } -- GitLab From a8651271bb5d77402251bf35554d1f320463c949 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 Jun 2012 14:57:13 -0500 Subject: [PATCH 1111/1799] libceph: small changes to messenger.c (cherry picked from commit 5821bd8ccdf5d17ab2c391c773756538603838c3) This patch gathers a few small changes in "net/ceph/messenger.c": out_msg_pos_next() - small logic change that mostly affects indentation write_partial_msg_pages(). - use a local variable trail_off to represent the offset into a message of the trail portion of the data (if present) - once we are in the trail portion we will always be there, so we don't always need to check against our data position - avoid computing len twice after we've reached the trail - get rid of the variable tmpcrc, which is not needed - trail_off and trail_len never change so mark them const - update some comments read_partial_message_bio() - bio_iovec_idx() will never return an error, so don't bother checking for it Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 63 ++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 1db6b68c2e40..73e2ee847be2 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -907,21 +907,23 @@ static void out_msg_pos_next(struct ceph_connection *con, struct page *page, con->out_msg_pos.data_pos += sent; con->out_msg_pos.page_pos += sent; - if (sent == len) { - con->out_msg_pos.page_pos = 0; - con->out_msg_pos.page++; - con->out_msg_pos.did_page_crc = false; - if (in_trail) - list_move_tail(&page->lru, - &msg->trail->head); - else if (msg->pagelist) - list_move_tail(&page->lru, - &msg->pagelist->head); + if (sent < len) + return; + + BUG_ON(sent != len); + con->out_msg_pos.page_pos = 0; + con->out_msg_pos.page++; + con->out_msg_pos.did_page_crc = false; + if (in_trail) + list_move_tail(&page->lru, + &msg->trail->head); + else if (msg->pagelist) + list_move_tail(&page->lru, + &msg->pagelist->head); #ifdef CONFIG_BLOCK - else if (msg->bio) - iter_bio_next(&msg->bio_iter, &msg->bio_seg); + else if (msg->bio) + iter_bio_next(&msg->bio_iter, &msg->bio_seg); #endif - } } /* @@ -940,30 +942,31 @@ static int write_partial_msg_pages(struct ceph_connection *con) int ret; int total_max_write; bool in_trail = false; - size_t trail_len = (msg->trail ? msg->trail->length : 0); + const size_t trail_len = (msg->trail ? msg->trail->length : 0); + const size_t trail_off = data_len - trail_len; dout("write_partial_msg_pages %p msg %p page %d/%d offset %d\n", con, msg, con->out_msg_pos.page, msg->nr_pages, con->out_msg_pos.page_pos); + /* + * Iterate through each page that contains data to be + * written, and send as much as possible for each. + * + * If we are calculating the data crc (the default), we will + * need to map the page. If we have no pages, they have + * been revoked, so use the zero page. + */ while (data_len > con->out_msg_pos.data_pos) { struct page *page = NULL; int max_write = PAGE_SIZE; int bio_offset = 0; - total_max_write = data_len - trail_len - - con->out_msg_pos.data_pos; - - /* - * if we are calculating the data crc (the default), we need - * to map the page. if our pages[] has been revoked, use the - * zero page. - */ - - /* have we reached the trail part of the data? */ - if (con->out_msg_pos.data_pos >= data_len - trail_len) { - in_trail = true; + in_trail = in_trail || con->out_msg_pos.data_pos >= trail_off; + if (!in_trail) + total_max_write = trail_off - con->out_msg_pos.data_pos; + if (in_trail) { total_max_write = data_len - con->out_msg_pos.data_pos; page = list_first_entry(&msg->trail->head, @@ -990,14 +993,13 @@ static int write_partial_msg_pages(struct ceph_connection *con) if (do_datacrc && !con->out_msg_pos.did_page_crc) { void *base; - u32 crc; - u32 tmpcrc = le32_to_cpu(msg->footer.data_crc); + u32 crc = le32_to_cpu(msg->footer.data_crc); char *kaddr; kaddr = kmap(page); BUG_ON(kaddr == NULL); base = kaddr + con->out_msg_pos.page_pos + bio_offset; - crc = crc32c(tmpcrc, base, len); + crc = crc32c(crc, base, len); msg->footer.data_crc = cpu_to_le32(crc); con->out_msg_pos.did_page_crc = true; } @@ -1702,9 +1704,6 @@ static int read_partial_message_bio(struct ceph_connection *con, void *p; int ret, left; - if (IS_ERR(bv)) - return PTR_ERR(bv); - left = min((int)(data_len - con->in_msg_pos.data_pos), (int)(bv->bv_len - con->in_msg_pos.page_pos)); -- GitLab From db90f992eb77188ce3e2b95d36f99ba194e04e66 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 20 Jun 2012 21:53:53 -0500 Subject: [PATCH 1112/1799] libceph: add some fine ASCII art (cherry picked from commit bc18f4b1c850ab355e38373fbb60fd28568d84b5) Sage liked the state diagram I put in my commit description so I'm putting it in with the code. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 73e2ee847be2..c40d1d5b3048 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -29,7 +29,47 @@ * the sender. */ -/* State values for ceph_connection->sock_state; NEW is assumed to be 0 */ +/* + * We track the state of the socket on a given connection using + * values defined below. The transition to a new socket state is + * handled by a function which verifies we aren't coming from an + * unexpected state. + * + * -------- + * | NEW* | transient initial state + * -------- + * | con_sock_state_init() + * v + * ---------- + * | CLOSED | initialized, but no socket (and no + * ---------- TCP connection) + * ^ \ + * | \ con_sock_state_connecting() + * | ---------------------- + * | \ + * + con_sock_state_closed() \ + * |\ \ + * | \ \ + * | ----------- \ + * | | CLOSING | socket event; \ + * | ----------- await close \ + * | ^ | + * | | | + * | + con_sock_state_closing() | + * | / \ | + * | / --------------- | + * | / \ v + * | / -------------- + * | / -----------------| CONNECTING | socket created, TCP + * | | / -------------- connect initiated + * | | | con_sock_state_connected() + * | | v + * ------------- + * | CONNECTED | TCP connection established + * ------------- + * + * State values for ceph_connection->sock_state; NEW is assumed to be 0. + */ #define CON_SOCK_STATE_NEW 0 /* -> CLOSED */ #define CON_SOCK_STATE_CLOSED 1 /* -> CONNECTING */ -- GitLab From 638ba1765d03bdc3a972bfca69fd0a4a4eda717c Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 27 Jun 2012 12:24:08 -0700 Subject: [PATCH 1113/1799] libceph: set peer name on con_open, not init (cherry picked from commit b7a9e5dd40f17a48a72f249b8bbc989b63bae5fd) The peer name may change on each open attempt, even when the connection is reused. Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/mds_client.c | 7 ++++--- include/linux/ceph/messenger.h | 4 ++-- net/ceph/messenger.c | 12 +++++++----- net/ceph/mon_client.c | 4 ++-- net/ceph/osd_client.c | 10 ++++++---- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index ecd7f15741c1..5ac6434185ae 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -394,8 +394,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, s->s_seq = 0; mutex_init(&s->s_mutex); - ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr, - CEPH_ENTITY_TYPE_MDS, mds); + ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr); spin_lock_init(&s->s_gen_ttl_lock); s->s_cap_gen = 0; @@ -437,7 +436,8 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, mdsc->sessions[mds] = s; atomic_inc(&s->s_ref); /* one ref to sessions[], one to caller */ - ceph_con_open(&s->s_con, ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); + ceph_con_open(&s->s_con, CEPH_ENTITY_TYPE_MDS, mds, + ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); return s; @@ -2529,6 +2529,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, session->s_seq = 0; ceph_con_open(&session->s_con, + CEPH_ENTITY_TYPE_MDS, mds, ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); /* replay unsafe requests */ diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 6a00acc61d47..ec22abd51fa0 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -224,9 +224,9 @@ extern void ceph_messenger_init(struct ceph_messenger *msgr, extern void ceph_con_init(struct ceph_connection *con, void *private, const struct ceph_connection_operations *ops, - struct ceph_messenger *msgr, __u8 entity_type, - __u64 entity_num); + struct ceph_messenger *msgr); extern void ceph_con_open(struct ceph_connection *con, + __u8 entity_type, __u64 entity_num, struct ceph_entity_addr *addr); extern bool ceph_con_opened(struct ceph_connection *con); extern void ceph_con_close(struct ceph_connection *con); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index c40d1d5b3048..e7cb279162f4 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -523,12 +523,17 @@ EXPORT_SYMBOL(ceph_con_close); /* * Reopen a closed connection, with a new peer address. */ -void ceph_con_open(struct ceph_connection *con, struct ceph_entity_addr *addr) +void ceph_con_open(struct ceph_connection *con, + __u8 entity_type, __u64 entity_num, + struct ceph_entity_addr *addr) { dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); set_bit(OPENING, &con->state); WARN_ON(!test_and_clear_bit(CLOSED, &con->state)); + con->peer_name.type = (__u8) entity_type; + con->peer_name.num = cpu_to_le64(entity_num); + memcpy(&con->peer_addr, addr, sizeof(*addr)); con->delay = 0; /* reset backoff memory */ queue_con(con); @@ -548,7 +553,7 @@ bool ceph_con_opened(struct ceph_connection *con) */ void ceph_con_init(struct ceph_connection *con, void *private, const struct ceph_connection_operations *ops, - struct ceph_messenger *msgr, __u8 entity_type, __u64 entity_num) + struct ceph_messenger *msgr) { dout("con_init %p\n", con); memset(con, 0, sizeof(*con)); @@ -558,9 +563,6 @@ void ceph_con_init(struct ceph_connection *con, void *private, con_sock_state_init(con); - con->peer_name.type = (__u8) entity_type; - con->peer_name.num = cpu_to_le64(entity_num); - mutex_init(&con->mutex); INIT_LIST_HEAD(&con->out_queue); INIT_LIST_HEAD(&con->out_sent); diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index dc16595d6885..39d772fdfab4 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -143,11 +143,11 @@ static int __open_session(struct ceph_mon_client *monc) monc->want_next_osdmap = !!monc->want_next_osdmap; ceph_con_init(&monc->con, monc, &mon_con_ops, - &monc->client->msgr, - CEPH_ENTITY_TYPE_MON, monc->cur_mon); + &monc->client->msgr); dout("open_session mon%d opening\n", monc->cur_mon); ceph_con_open(&monc->con, + CEPH_ENTITY_TYPE_MON, monc->cur_mon, &monc->monmap->mon_inst[monc->cur_mon].addr); /* initiatiate authentication handshake */ diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index c178c770acb4..474a52d9b4a8 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -639,8 +639,7 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum) INIT_LIST_HEAD(&osd->o_osd_lru); osd->o_incarnation = 1; - ceph_con_init(&osd->o_con, osd, &osd_con_ops, &osdc->client->msgr, - CEPH_ENTITY_TYPE_OSD, onum); + ceph_con_init(&osd->o_con, osd, &osd_con_ops, &osdc->client->msgr); INIT_LIST_HEAD(&osd->o_keepalive_item); return osd; @@ -750,7 +749,8 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) ret = -EAGAIN; } else { ceph_con_close(&osd->o_con); - ceph_con_open(&osd->o_con, &osdc->osdmap->osd_addr[osd->o_osd]); + ceph_con_open(&osd->o_con, CEPH_ENTITY_TYPE_OSD, osd->o_osd, + &osdc->osdmap->osd_addr[osd->o_osd]); osd->o_incarnation++; } return ret; @@ -1005,7 +1005,9 @@ static int __map_request(struct ceph_osd_client *osdc, dout("map_request osd %p is osd%d\n", req->r_osd, o); __insert_osd(osdc, req->r_osd); - ceph_con_open(&req->r_osd->o_con, &osdc->osdmap->osd_addr[o]); + ceph_con_open(&req->r_osd->o_con, + CEPH_ENTITY_TYPE_OSD, o, + &osdc->osdmap->osd_addr[o]); } if (req->r_osd) { -- GitLab From a5b0662bb814837139bb73249463e199528101b5 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 27 Jun 2012 12:24:34 -0700 Subject: [PATCH 1114/1799] libceph: initialize mon_client con only once (cherry picked from commit 735a72ef952d42a256f79ae3e6dc1c17a45c041b) Do not re-initialize the con on every connection attempt. When we ceph_con_close, there may still be work queued on the socket (e.g., to close it), and re-initializing will clobber the work_struct state. Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/mon_client.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 39d772fdfab4..9f00d6cd93e2 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -119,7 +119,6 @@ static void __close_session(struct ceph_mon_client *monc) dout("__close_session closing mon%d\n", monc->cur_mon); ceph_msg_revoke(monc->m_auth); ceph_con_close(&monc->con); - monc->con.private = NULL; monc->cur_mon = -1; monc->pending_auth = 0; ceph_auth_reset(monc->auth); @@ -142,9 +141,6 @@ static int __open_session(struct ceph_mon_client *monc) monc->sub_renew_after = jiffies; /* i.e., expired */ monc->want_next_osdmap = !!monc->want_next_osdmap; - ceph_con_init(&monc->con, monc, &mon_con_ops, - &monc->client->msgr); - dout("open_session mon%d opening\n", monc->cur_mon); ceph_con_open(&monc->con, CEPH_ENTITY_TYPE_MON, monc->cur_mon, @@ -798,6 +794,9 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) if (!monc->m_auth) goto out_auth_reply; + ceph_con_init(&monc->con, monc, &mon_con_ops, + &monc->client->msgr); + monc->cur_mon = -1; monc->hunting = true; monc->sub_renew_after = jiffies; -- GitLab From d92d11da1dd8531150823ff429ae29a0cf5e438d Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 27 Jun 2012 12:31:02 -0700 Subject: [PATCH 1115/1799] libceph: allow sock transition from CONNECTING to CLOSED (cherry picked from commit fbb85a478f6d4cce6942f1c25c6a68ec5b1e7e7f) It is possible to close a socket that is in the OPENING state. For example, it can happen if ceph_con_close() is called on the con before the TCP connection is established. con_work() will come around and shut down the socket. Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index e7cb279162f4..866645fa857f 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -48,17 +48,17 @@ * | ---------------------- * | \ * + con_sock_state_closed() \ - * |\ \ - * | \ \ - * | ----------- \ - * | | CLOSING | socket event; \ - * | ----------- await close \ - * | ^ | - * | | | - * | + con_sock_state_closing() | - * | / \ | - * | / --------------- | - * | / \ v + * |+--------------------------- \ + * | \ \ \ + * | ----------- \ \ + * | | CLOSING | socket event; \ \ + * | ----------- await close \ \ + * | ^ \ | + * | | \ | + * | + con_sock_state_closing() \ | + * | / \ | | + * | / --------------- | | + * | / \ v v * | / -------------- * | / -----------------| CONNECTING | socket created, TCP * | | / -------------- connect initiated @@ -241,7 +241,8 @@ static void con_sock_state_closed(struct ceph_connection *con) old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTED && - old_state != CON_SOCK_STATE_CLOSING)) + old_state != CON_SOCK_STATE_CLOSING && + old_state != CON_SOCK_STATE_CONNECTING)) printk("%s: unexpected old state %d\n", __func__, old_state); } -- GitLab From 9beb73fcb83317786226b4203d7e56c6b0f43adb Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 9 Jul 2012 14:22:34 -0700 Subject: [PATCH 1116/1799] libceph: initialize msgpool message types (cherry picked from commit d50b409fb8698571d8209e5adfe122e287e31290) Initialize the type field for messages in a msgpool. The caller was doing this for osd ops, but not for the reply messages. Reported-by: Alex Elder Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/msgpool.h | 3 ++- net/ceph/msgpool.c | 7 ++++--- net/ceph/osd_client.c | 7 ++++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/include/linux/ceph/msgpool.h b/include/linux/ceph/msgpool.h index a362605f9368..09fa96b43436 100644 --- a/include/linux/ceph/msgpool.h +++ b/include/linux/ceph/msgpool.h @@ -11,10 +11,11 @@ struct ceph_msgpool { const char *name; mempool_t *pool; + int type; /* preallocated message type */ int front_len; /* preallocated payload size */ }; -extern int ceph_msgpool_init(struct ceph_msgpool *pool, +extern int ceph_msgpool_init(struct ceph_msgpool *pool, int type, int front_len, int size, bool blocking, const char *name); extern void ceph_msgpool_destroy(struct ceph_msgpool *pool); diff --git a/net/ceph/msgpool.c b/net/ceph/msgpool.c index 11d5f4196a73..ddec1c10ac80 100644 --- a/net/ceph/msgpool.c +++ b/net/ceph/msgpool.c @@ -12,7 +12,7 @@ static void *msgpool_alloc(gfp_t gfp_mask, void *arg) struct ceph_msgpool *pool = arg; struct ceph_msg *msg; - msg = ceph_msg_new(0, pool->front_len, gfp_mask, true); + msg = ceph_msg_new(pool->type, pool->front_len, gfp_mask, true); if (!msg) { dout("msgpool_alloc %s failed\n", pool->name); } else { @@ -32,10 +32,11 @@ static void msgpool_free(void *element, void *arg) ceph_msg_put(msg); } -int ceph_msgpool_init(struct ceph_msgpool *pool, +int ceph_msgpool_init(struct ceph_msgpool *pool, int type, int front_len, int size, bool blocking, const char *name) { dout("msgpool %s init\n", name); + pool->type = type; pool->front_len = front_len; pool->pool = mempool_create(size, msgpool_alloc, msgpool_free, pool); if (!pool->pool) @@ -61,7 +62,7 @@ struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool, WARN_ON(1); /* try to alloc a fresh message */ - return ceph_msg_new(0, front_len, GFP_NOFS, false); + return ceph_msg_new(pool->type, front_len, GFP_NOFS, false); } msg = mempool_alloc(pool->pool, GFP_NOFS); diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 474a52d9b4a8..408ca51ffcf8 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -242,6 +242,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, } ceph_pagelist_init(req->r_trail); } + /* create request message; allow space for oid */ msg_size += MAX_OBJ_NAME_SIZE; if (snapc) @@ -255,7 +256,6 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, return NULL; } - msg->hdr.type = cpu_to_le16(CEPH_MSG_OSD_OP); memset(msg->front.iov_base, 0, msg->front.iov_len); req->r_request = msg; @@ -1837,11 +1837,12 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client) if (!osdc->req_mempool) goto out; - err = ceph_msgpool_init(&osdc->msgpool_op, OSD_OP_FRONT_LEN, 10, true, + err = ceph_msgpool_init(&osdc->msgpool_op, CEPH_MSG_OSD_OP, + OSD_OP_FRONT_LEN, 10, true, "osd_op"); if (err < 0) goto out_mempool; - err = ceph_msgpool_init(&osdc->msgpool_op_reply, + err = ceph_msgpool_init(&osdc->msgpool_op_reply, CEPH_MSG_OSD_OPREPLY, OSD_OPREPLY_FRONT_LEN, 10, true, "osd_op_reply"); if (err < 0) -- GitLab From 59d02721bb2838893596d5617659fe907dd45518 Mon Sep 17 00:00:00 2001 From: Guanjun He Date: Sun, 8 Jul 2012 19:50:33 -0700 Subject: [PATCH 1117/1799] libceph: prevent the race of incoming work during teardown (cherry picked from commit a2a3258417eb6a1799cf893350771428875a8287) Add an atomic variable 'stopping' as flag in struct ceph_messenger, set this flag to 1 in function ceph_destroy_client(), and add the condition code in function ceph_data_ready() to test the flag value, if true(1), just return. Signed-off-by: Guanjun He Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 1 + net/ceph/ceph_common.c | 2 ++ net/ceph/messenger.c | 5 +++++ 3 files changed, 8 insertions(+) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index ec22abd51fa0..de39cda6bd58 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -50,6 +50,7 @@ struct ceph_messenger { struct ceph_entity_inst inst; /* my name+address */ struct ceph_entity_addr my_enc_addr; + atomic_t stopping; bool nocrc; /* diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index c815f31a1a3f..52fe52cde606 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -495,6 +495,8 @@ void ceph_destroy_client(struct ceph_client *client) { dout("destroy_client %p\n", client); + atomic_set(&client->msgr.stopping, 1); + /* unmount */ ceph_osdc_stop(&client->osdc); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 866645fa857f..edd51321ae18 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -254,6 +254,9 @@ static void con_sock_state_closed(struct ceph_connection *con) static void ceph_sock_data_ready(struct sock *sk, int count_unused) { struct ceph_connection *con = sk->sk_user_data; + if (atomic_read(&con->msgr->stopping)) { + return; + } if (sk->sk_state != TCP_CLOSE_WAIT) { dout("%s on %p state = %lu, queueing work\n", __func__, @@ -2413,6 +2416,8 @@ void ceph_messenger_init(struct ceph_messenger *msgr, encode_my_addr(msgr); msgr->nocrc = nocrc; + atomic_set(&msgr->stopping, 0); + dout("%s %p\n", __func__, msgr); } EXPORT_SYMBOL(ceph_messenger_init); -- GitLab From b3fd00b73452353444c768b19bb175ec95410c8f Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:24:21 -0700 Subject: [PATCH 1118/1799] libceph: report socket read/write error message (cherry picked from commit 3a140a0d5c4b9e35373b016e41dfc85f1e526bdb) We need to set error_msg to something useful before calling ceph_fault(); do so here for try_{read,write}(). This is more informative than libceph: osd0 192.168.106.220:6801 (null) Signed-off-by: Sage Weil Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index edd51321ae18..96d9c9960aa7 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2287,14 +2287,18 @@ static void con_work(struct work_struct *work) ret = try_read(con); if (ret == -EAGAIN) goto restart; - if (ret < 0) + if (ret < 0) { + con->error_msg = "socket error on read"; goto fault; + } ret = try_write(con); if (ret == -EAGAIN) goto restart; - if (ret < 0) + if (ret < 0) { + con->error_msg = "socket error on write"; goto fault; + } done: mutex_unlock(&con->mutex); -- GitLab From 7621822a64ee40c0ab4181e7281ef06f241782cb Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:24:37 -0700 Subject: [PATCH 1119/1799] libceph: fix mutex coverage for ceph_con_close (cherry picked from commit 8c50c817566dfa4581f82373aac39f3e608a7dc8) Hold the mutex while twiddling all of the state bits to avoid possible races. While we're here, make not of why we cannot close the socket directly. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 96d9c9960aa7..7ccecf3915a1 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -503,6 +503,7 @@ static void reset_connection(struct ceph_connection *con) */ void ceph_con_close(struct ceph_connection *con) { + mutex_lock(&con->mutex); dout("con_close %p peer %s\n", con, ceph_pr_addr(&con->peer_addr.in_addr)); clear_bit(NEGOTIATING, &con->state); @@ -515,11 +516,16 @@ void ceph_con_close(struct ceph_connection *con) clear_bit(KEEPALIVE_PENDING, &con->flags); clear_bit(WRITE_PENDING, &con->flags); - mutex_lock(&con->mutex); reset_connection(con); con->peer_global_seq = 0; cancel_delayed_work(&con->work); mutex_unlock(&con->mutex); + + /* + * We cannot close the socket directly from here because the + * work threads use it without holding the mutex. Instead, let + * con_work() do it. + */ queue_con(con); } EXPORT_SYMBOL(ceph_con_close); -- GitLab From d43841ef768a78f2cbc7e819f1a2838a4838f566 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:19:28 -0700 Subject: [PATCH 1120/1799] libceph: resubmit linger ops when pg mapping changes (cherry picked from commit 6194ea895e447fdf4adfd23f67873a32bf4f15ae) The linger op registration (i.e., watch) modifies the object state. As such, the OSD will reply with success if it has already applied without doing the associated side-effects (setting up the watch session state). If we lose the ACK and resubmit, we will see success but the watch will not be correctly registered and we won't get notifies. To fix this, always resubmit the linger op with a new tid. We accomplish this by re-registering as a linger (i.e., 'registered') if we are not yet registered. Then the second loop will treat this just like a normal case of re-registering. This mirrors a similar fix on the userland ceph.git, commit 5dd68b95, and ceph bug #2796. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh Signed-off-by: Greg Kroah-Hartman --- net/ceph/osd_client.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 408ca51ffcf8..56fd974b7656 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -888,7 +888,9 @@ static void __register_linger_request(struct ceph_osd_client *osdc, { dout("__register_linger_request %p\n", req); list_add_tail(&req->r_linger_item, &osdc->req_linger); - list_add_tail(&req->r_linger_osd, &req->r_osd->o_linger_requests); + if (req->r_osd) + list_add_tail(&req->r_linger_osd, + &req->r_osd->o_linger_requests); } static void __unregister_linger_request(struct ceph_osd_client *osdc, @@ -1302,8 +1304,9 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) dout("kick_requests %s\n", force_resend ? " (force resend)" : ""); mutex_lock(&osdc->request_mutex); - for (p = rb_first(&osdc->requests); p; p = rb_next(p)) { + for (p = rb_first(&osdc->requests); p; ) { req = rb_entry(p, struct ceph_osd_request, r_node); + p = rb_next(p); err = __map_request(osdc, req, force_resend); if (err < 0) continue; /* error */ @@ -1311,10 +1314,23 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) dout("%p tid %llu maps to no osd\n", req, req->r_tid); needmap++; /* request a newer map */ } else if (err > 0) { - dout("%p tid %llu requeued on osd%d\n", req, req->r_tid, - req->r_osd ? req->r_osd->o_osd : -1); - if (!req->r_linger) + if (!req->r_linger) { + dout("%p tid %llu requeued on osd%d\n", req, + req->r_tid, + req->r_osd ? req->r_osd->o_osd : -1); req->r_flags |= CEPH_OSD_FLAG_RETRY; + } + } + if (req->r_linger && list_empty(&req->r_linger_item)) { + /* + * register as a linger so that we will + * re-submit below and get a new tid + */ + dout("%p tid %llu restart on osd%d\n", + req, req->r_tid, + req->r_osd ? req->r_osd->o_osd : -1); + __register_linger_request(osdc, req); + __unregister_request(osdc, req); } } -- GitLab From 175c4c20d29322b9e882c052025e72644ca00e2d Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:20:25 -0700 Subject: [PATCH 1121/1799] libceph: (re)initialize bio_iter on start of message receive (cherry picked from commit a4107026976f06c9a6ce8cc84a763564ee39d901) Previously, we were opportunistically initializing the bio_iter if it appeared to be uninitialized in the middle of the read path. The problem is that a sequence like: - start reading message - initialize bio_iter - read half a message - messenger fault, reconnect - restart reading message - ** bio_iter now non-NULL, not reinitialized ** - read past end of bio, crash Instead, initialize the bio_iter unconditionally when we allocate/claim the message for read. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 7ccecf3915a1..c5df88364f27 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1872,6 +1872,11 @@ static int read_partial_message(struct ceph_connection *con) else con->in_msg_pos.page_pos = 0; con->in_msg_pos.data_pos = 0; + +#ifdef CONFIG_BLOCK + if (m->bio) + init_bio_iter(m->bio, &m->bio_iter, &m->bio_seg); +#endif } /* front */ @@ -1888,10 +1893,6 @@ static int read_partial_message(struct ceph_connection *con) if (ret <= 0) return ret; } -#ifdef CONFIG_BLOCK - if (m->bio && !m->bio_iter) - init_bio_iter(m->bio, &m->bio_iter, &m->bio_seg); -#endif /* (page) data */ while (con->in_msg_pos.data_pos < data_len) { @@ -1902,7 +1903,7 @@ static int read_partial_message(struct ceph_connection *con) return ret; #ifdef CONFIG_BLOCK } else if (m->bio) { - + BUG_ON(!m->bio_iter); ret = read_partial_message_bio(con, &m->bio_iter, &m->bio_seg, data_len, do_datacrc); -- GitLab From eea8ed97626254429d4679c567035effdf9983a8 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:21:40 -0700 Subject: [PATCH 1122/1799] libceph: protect ceph_con_open() with mutex (cherry picked from commit 5469155f2bc83bb2c88b0a0370c3d54d87eed06e) Take the con mutex while we are initiating a ceph open. This is necessary because the may have previously been in use and then closed, which could result in a racing workqueue running con_work(). Signed-off-by: Sage Weil Reviewed-by: Yehuda Sadeh Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index c5df88364f27..b59e64a7b24b 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -537,6 +537,7 @@ void ceph_con_open(struct ceph_connection *con, __u8 entity_type, __u64 entity_num, struct ceph_entity_addr *addr) { + mutex_lock(&con->mutex); dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); set_bit(OPENING, &con->state); WARN_ON(!test_and_clear_bit(CLOSED, &con->state)); @@ -546,6 +547,7 @@ void ceph_con_open(struct ceph_connection *con, memcpy(&con->peer_addr, addr, sizeof(*addr)); con->delay = 0; /* reset backoff memory */ + mutex_unlock(&con->mutex); queue_con(con); } EXPORT_SYMBOL(ceph_con_open); -- GitLab From ed447f04ee3240371aa8a199588107fd521240d3 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:22:05 -0700 Subject: [PATCH 1123/1799] libceph: reset connection retry on successfully negotiation (cherry picked from commit 85effe183dd45854d1ad1a370b88cddb403c4c91) We exponentially back off when we encounter connection errors. If several errors accumulate, we will eventually wait ages before even trying to reconnect. Fix this by resetting the backoff counter after a successful negotiation/ connection with the remote node. Fixes ceph issue #2802. Signed-off-by: Sage Weil Reviewed-by: Yehuda Sadeh Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index b59e64a7b24b..9da18929c588 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1629,6 +1629,8 @@ static int process_connect(struct ceph_connection *con) if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY) set_bit(LOSSYTX, &con->flags); + con->delay = 0; /* reset backoff memory */ + prepare_read_tag(con); break; -- GitLab From da6a81eb5a2671f12551953d1843a0f53416d185 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 15:22:53 -0700 Subject: [PATCH 1124/1799] libceph: fix fault locking; close socket on lossy fault (cherry picked from commit 3b5ede07b55b52c3be27749d183d87257d032065) If we fault on a lossy connection, we should still close the socket immediately, and do so under the con mutex. We should also take the con mutex before printing out the state bits in the debug output. Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 9da18929c588..d769a73e080a 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2330,22 +2330,23 @@ static void con_work(struct work_struct *work) */ static void ceph_fault(struct ceph_connection *con) { + mutex_lock(&con->mutex); + pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg); dout("fault %p state %lu to peer %s\n", con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); - if (test_bit(LOSSYTX, &con->flags)) { - dout("fault on LOSSYTX channel\n"); - goto out; - } - - mutex_lock(&con->mutex); if (test_bit(CLOSED, &con->state)) goto out_unlock; con_close_socket(con); + if (test_bit(LOSSYTX, &con->flags)) { + dout("fault on LOSSYTX channel\n"); + goto out_unlock; + } + if (con->in_msg) { BUG_ON(con->in_msg->con != con); con->in_msg->con = NULL; @@ -2392,7 +2393,6 @@ static void ceph_fault(struct ceph_connection *con) out_unlock: mutex_unlock(&con->mutex); -out: /* * in case we faulted due to authentication, invalidate our * current tickets so that we can get new ones. -- GitLab From 67c6fc1932a705f61f98d8092375622b8dffea6a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 15:33:04 -0700 Subject: [PATCH 1125/1799] libceph: move msgr clear_standby under con mutex protection (cherry picked from commit 00650931e52e97fe64096bec167f5a6780dfd94a) Avoid dropping and retaking con->mutex in the ceph_con_send() case by leaving locking up to the caller. Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index d769a73e080a..14d24b778ca9 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2441,12 +2441,10 @@ static void clear_standby(struct ceph_connection *con) { /* come back from STANDBY? */ if (test_and_clear_bit(STANDBY, &con->state)) { - mutex_lock(&con->mutex); dout("clear_standby %p and ++connect_seq\n", con); con->connect_seq++; WARN_ON(test_bit(WRITE_PENDING, &con->flags)); WARN_ON(test_bit(KEEPALIVE_PENDING, &con->flags)); - mutex_unlock(&con->mutex); } } @@ -2483,11 +2481,12 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) le32_to_cpu(msg->hdr.front_len), le32_to_cpu(msg->hdr.middle_len), le32_to_cpu(msg->hdr.data_len)); + + clear_standby(con); mutex_unlock(&con->mutex); /* if there wasn't anything waiting to send before, queue * new work */ - clear_standby(con); if (test_and_set_bit(WRITE_PENDING, &con->flags) == 0) queue_con(con); } @@ -2574,7 +2573,9 @@ void ceph_msg_revoke_incoming(struct ceph_msg *msg) void ceph_con_keepalive(struct ceph_connection *con) { dout("con_keepalive %p\n", con); + mutex_lock(&con->mutex); clear_standby(con); + mutex_unlock(&con->mutex); if (test_and_set_bit(KEEPALIVE_PENDING, &con->flags) == 0 && test_and_set_bit(WRITE_PENDING, &con->flags) == 0) queue_con(con); -- GitLab From 5d0f354b3183d005024d43b567335701d928995a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 15:34:04 -0700 Subject: [PATCH 1126/1799] libceph: move ceph_con_send() closed check under the con mutex (cherry picked from commit a59b55a602b6c741052d79c1e3643f8440cddd27) Take the con mutex before checking whether the connection is closed to avoid racing with someone else closing it. Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 14d24b778ca9..cb871fc7286f 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2453,22 +2453,20 @@ static void clear_standby(struct ceph_connection *con) */ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) { - if (test_bit(CLOSED, &con->state)) { - dout("con_send %p closed, dropping %p\n", con, msg); - ceph_msg_put(msg); - return; - } - /* set src+dst */ msg->hdr.src = con->msgr->inst.name; - BUG_ON(msg->front.iov_len != le32_to_cpu(msg->hdr.front_len)); - msg->needs_out_seq = true; - /* queue */ mutex_lock(&con->mutex); + if (test_bit(CLOSED, &con->state)) { + dout("con_send %p closed, dropping %p\n", con, msg); + ceph_msg_put(msg); + mutex_unlock(&con->mutex); + return; + } + BUG_ON(msg->con != NULL); msg->con = con->ops->get(con); BUG_ON(msg->con == NULL); -- GitLab From 1c5b33b852ab372d4538821db998561d5e4d7212 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 15:40:04 -0700 Subject: [PATCH 1127/1799] libceph: drop gratuitous socket close calls in con_work (cherry picked from commit 2e8cb10063820af7ed7638e3fd9013eee21266e7) If the state is CLOSED or OPENING, we shouldn't have a socket. Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index cb871fc7286f..7bd757cb01af 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2284,15 +2284,15 @@ static void con_work(struct work_struct *work) dout("con_work %p STANDBY\n", con); goto done; } - if (test_bit(CLOSED, &con->state)) { /* e.g. if we are replaced */ - dout("con_work CLOSED\n"); - con_close_socket(con); + if (test_bit(CLOSED, &con->state)) { + dout("con_work %p CLOSED\n", con); + BUG_ON(con->sock); goto done; } if (test_and_clear_bit(OPENING, &con->state)) { /* reopen w/ new peer */ dout("con_work OPENING\n"); - con_close_socket(con); + BUG_ON(con->sock); } ret = try_read(con); -- GitLab From 3b5a9ead0b4845aaa7e80fcd6166f2c6740a1c6f Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 16:45:49 -0700 Subject: [PATCH 1128/1799] libceph: close socket directly from ceph_con_close() (cherry picked from commit ee76e0736db8455e3b11827d6899bd2a4e1d0584) It is simpler to do this immediately, since we already hold the con mutex. It also avoids the need to deal with a not-quite-CLOSED socket in con_work. Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 7bd757cb01af..49f78ff62478 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -519,14 +519,8 @@ void ceph_con_close(struct ceph_connection *con) reset_connection(con); con->peer_global_seq = 0; cancel_delayed_work(&con->work); + con_close_socket(con); mutex_unlock(&con->mutex); - - /* - * We cannot close the socket directly from here because the - * work threads use it without holding the mutex. Instead, let - * con_work() do it. - */ - queue_con(con); } EXPORT_SYMBOL(ceph_con_close); -- GitLab From cb9f8855591613dff0909c99d46a29e10eb39b25 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 17:19:43 -0700 Subject: [PATCH 1129/1799] libceph: drop unnecessary CLOSED check in socket state change callback (cherry picked from commit d7353dd5aaf22ed611fbcd0d4a4a12fb30659290) If we are CLOSED, the socket is closed and we won't get these. Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 49f78ff62478..7df72fff886a 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -296,9 +296,6 @@ static void ceph_sock_state_change(struct sock *sk) dout("%s %p state = %lu sk_state = %u\n", __func__, con, con->state, sk->sk_state); - if (test_bit(CLOSED, &con->state)) - return; - switch (sk->sk_state) { case TCP_CLOSE: dout("%s TCP_CLOSE\n", __func__); -- GitLab From 265fb7c177f9db75d628b3479b6223c1c8110e67 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 17:24:40 -0700 Subject: [PATCH 1130/1799] libceph: replace connection state bits with states (cherry picked from commit 8dacc7da69a491c515851e68de6036f21b5663ce) Use a simple set of 6 enumerated values for the socket states (CON_STATE_*) and use those instead of the state bits. All of the con->state checks are now under the protection of the con mutex, so this is safe. It also simplifies many of the state checks because we can check for anything other than the expected state instead of various bits for races we can think of. This appears to hold up well to stress testing both with and without socket failure injection on the server side. Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 12 --- net/ceph/messenger.c | 130 +++++++++++++++++---------------- 2 files changed, 68 insertions(+), 74 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index de39cda6bd58..dc684f6bc55f 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -116,18 +116,6 @@ struct ceph_msg_pos { #define SOCK_CLOSED 11 /* socket state changed to closed */ #define BACKOFF 15 -/* - * ceph_connection states - */ -#define CONNECTING 1 -#define NEGOTIATING 2 -#define CONNECTED 5 -#define STANDBY 8 /* no outgoing messages, socket closed. we keep - * the ceph_connection around to maintain shared - * state with the peer. */ -#define CLOSED 10 /* we've closed the connection */ -#define OPENING 13 /* open connection w/ (possibly new) peer */ - /* * A single connection with another host. * diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 7df72fff886a..8c239390c21d 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -77,6 +77,17 @@ #define CON_SOCK_STATE_CONNECTED 3 /* -> CLOSING or -> CLOSED */ #define CON_SOCK_STATE_CLOSING 4 /* -> CLOSED */ +/* + * connection states + */ +#define CON_STATE_CLOSED 1 /* -> PREOPEN */ +#define CON_STATE_PREOPEN 2 /* -> CONNECTING, CLOSED */ +#define CON_STATE_CONNECTING 3 /* -> NEGOTIATING, CLOSED */ +#define CON_STATE_NEGOTIATING 4 /* -> OPEN, CLOSED */ +#define CON_STATE_OPEN 5 /* -> STANDBY, CLOSED */ +#define CON_STATE_STANDBY 6 /* -> PREOPEN, CLOSED */ + + /* static tag bytes (protocol control messages) */ static char tag_msg = CEPH_MSGR_TAG_MSG; static char tag_ack = CEPH_MSGR_TAG_ACK; @@ -503,11 +514,7 @@ void ceph_con_close(struct ceph_connection *con) mutex_lock(&con->mutex); dout("con_close %p peer %s\n", con, ceph_pr_addr(&con->peer_addr.in_addr)); - clear_bit(NEGOTIATING, &con->state); - clear_bit(CONNECTING, &con->state); - clear_bit(CONNECTED, &con->state); - clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */ - set_bit(CLOSED, &con->state); + con->state = CON_STATE_CLOSED; clear_bit(LOSSYTX, &con->flags); /* so we retry next connect */ clear_bit(KEEPALIVE_PENDING, &con->flags); @@ -530,8 +537,9 @@ void ceph_con_open(struct ceph_connection *con, { mutex_lock(&con->mutex); dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); - set_bit(OPENING, &con->state); - WARN_ON(!test_and_clear_bit(CLOSED, &con->state)); + + BUG_ON(con->state != CON_STATE_CLOSED); + con->state = CON_STATE_PREOPEN; con->peer_name.type = (__u8) entity_type; con->peer_name.num = cpu_to_le64(entity_num); @@ -571,7 +579,7 @@ void ceph_con_init(struct ceph_connection *con, void *private, INIT_LIST_HEAD(&con->out_sent); INIT_DELAYED_WORK(&con->work, con_work); - set_bit(CLOSED, &con->state); + con->state = CON_STATE_CLOSED; } EXPORT_SYMBOL(ceph_con_init); @@ -809,27 +817,21 @@ static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection if (!con->ops->get_authorizer) { con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN; con->out_connect.authorizer_len = 0; - return NULL; } /* Can't hold the mutex while getting authorizer */ - mutex_unlock(&con->mutex); - auth = con->ops->get_authorizer(con, auth_proto, con->auth_retry); - mutex_lock(&con->mutex); if (IS_ERR(auth)) return auth; - if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->flags)) + if (con->state != CON_STATE_NEGOTIATING) return ERR_PTR(-EAGAIN); con->auth_reply_buf = auth->authorizer_reply_buf; con->auth_reply_buf_len = auth->authorizer_reply_buf_len; - - return auth; } @@ -1484,7 +1486,8 @@ static int process_banner(struct ceph_connection *con) static void fail_protocol(struct ceph_connection *con) { reset_connection(con); - set_bit(CLOSED, &con->state); /* in case there's queued work */ + BUG_ON(con->state != CON_STATE_NEGOTIATING); + con->state = CON_STATE_CLOSED; } static int process_connect(struct ceph_connection *con) @@ -1558,8 +1561,7 @@ static int process_connect(struct ceph_connection *con) if (con->ops->peer_reset) con->ops->peer_reset(con); mutex_lock(&con->mutex); - if (test_bit(CLOSED, &con->state) || - test_bit(OPENING, &con->state)) + if (con->state != CON_STATE_NEGOTIATING) return -EAGAIN; break; @@ -1605,8 +1607,10 @@ static int process_connect(struct ceph_connection *con) fail_protocol(con); return -1; } - clear_bit(NEGOTIATING, &con->state); - set_bit(CONNECTED, &con->state); + + BUG_ON(con->state != CON_STATE_NEGOTIATING); + con->state = CON_STATE_OPEN; + con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); con->connect_seq++; con->peer_features = server_feat; @@ -1994,8 +1998,9 @@ static int try_write(struct ceph_connection *con) dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes); /* open the socket first? */ - if (con->sock == NULL) { - set_bit(CONNECTING, &con->state); + if (con->state == CON_STATE_PREOPEN) { + BUG_ON(con->sock); + con->state = CON_STATE_CONNECTING; con_out_kvec_reset(con); prepare_write_banner(con); @@ -2046,8 +2051,7 @@ static int try_write(struct ceph_connection *con) } do_next: - if (!test_bit(CONNECTING, &con->state) && - !test_bit(NEGOTIATING, &con->state)) { + if (con->state == CON_STATE_OPEN) { /* is anything else pending? */ if (!list_empty(&con->out_queue)) { prepare_write_message(con); @@ -2081,29 +2085,19 @@ static int try_read(struct ceph_connection *con) { int ret = -1; - if (!con->sock) - return 0; - - if (test_bit(STANDBY, &con->state)) +more: + dout("try_read start on %p state %lu\n", con, con->state); + if (con->state != CON_STATE_CONNECTING && + con->state != CON_STATE_NEGOTIATING && + con->state != CON_STATE_OPEN) return 0; - dout("try_read start on %p\n", con); + BUG_ON(!con->sock); -more: dout("try_read tag %d in_base_pos %d\n", (int)con->in_tag, con->in_base_pos); - /* - * process_connect and process_message drop and re-take - * con->mutex. make sure we handle a racing close or reopen. - */ - if (test_bit(CLOSED, &con->state) || - test_bit(OPENING, &con->state)) { - ret = -EAGAIN; - goto out; - } - - if (test_bit(CONNECTING, &con->state)) { + if (con->state == CON_STATE_CONNECTING) { dout("try_read connecting\n"); ret = read_partial_banner(con); if (ret <= 0) @@ -2112,8 +2106,8 @@ static int try_read(struct ceph_connection *con) if (ret < 0) goto out; - clear_bit(CONNECTING, &con->state); - set_bit(NEGOTIATING, &con->state); + BUG_ON(con->state != CON_STATE_CONNECTING); + con->state = CON_STATE_NEGOTIATING; /* Banner is good, exchange connection info */ ret = prepare_write_connect(con); @@ -2125,7 +2119,7 @@ static int try_read(struct ceph_connection *con) goto out; } - if (test_bit(NEGOTIATING, &con->state)) { + if (con->state == CON_STATE_NEGOTIATING) { dout("try_read negotiating\n"); ret = read_partial_connect(con); if (ret <= 0) @@ -2136,6 +2130,8 @@ static int try_read(struct ceph_connection *con) goto more; } + BUG_ON(con->state != CON_STATE_OPEN); + if (con->in_base_pos < 0) { /* * skipping + discarding content. @@ -2169,8 +2165,8 @@ static int try_read(struct ceph_connection *con) prepare_read_ack(con); break; case CEPH_MSGR_TAG_CLOSE: - clear_bit(CONNECTED, &con->state); - set_bit(CLOSED, &con->state); /* fixme */ + con_close_socket(con); + con->state = CON_STATE_CLOSED; goto out; default: goto bad_tag; @@ -2246,14 +2242,21 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { - if (test_and_clear_bit(CONNECTED, &con->state)) - con->error_msg = "socket closed"; - else if (test_and_clear_bit(NEGOTIATING, &con->state)) - con->error_msg = "negotiation failed"; - else if (test_and_clear_bit(CONNECTING, &con->state)) + switch (con->state) { + case CON_STATE_CONNECTING: con->error_msg = "connection failed"; - else + break; + case CON_STATE_NEGOTIATING: + con->error_msg = "negotiation failed"; + break; + case CON_STATE_OPEN: + con->error_msg = "socket closed"; + break; + default: + dout("unrecognized con state %d\n", (int)con->state); con->error_msg = "unrecognized con state"; + BUG(); + } goto fault; } @@ -2271,17 +2274,16 @@ static void con_work(struct work_struct *work) } } - if (test_bit(STANDBY, &con->state)) { + if (con->state == CON_STATE_STANDBY) { dout("con_work %p STANDBY\n", con); goto done; } - if (test_bit(CLOSED, &con->state)) { + if (con->state == CON_STATE_CLOSED) { dout("con_work %p CLOSED\n", con); BUG_ON(con->sock); goto done; } - if (test_and_clear_bit(OPENING, &con->state)) { - /* reopen w/ new peer */ + if (con->state == CON_STATE_PREOPEN) { dout("con_work OPENING\n"); BUG_ON(con->sock); } @@ -2328,13 +2330,15 @@ static void ceph_fault(struct ceph_connection *con) dout("fault %p state %lu to peer %s\n", con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); - if (test_bit(CLOSED, &con->state)) - goto out_unlock; + BUG_ON(con->state != CON_STATE_CONNECTING && + con->state != CON_STATE_NEGOTIATING && + con->state != CON_STATE_OPEN); con_close_socket(con); if (test_bit(LOSSYTX, &con->flags)) { - dout("fault on LOSSYTX channel\n"); + dout("fault on LOSSYTX channel, marking CLOSED\n"); + con->state = CON_STATE_CLOSED; goto out_unlock; } @@ -2355,9 +2359,10 @@ static void ceph_fault(struct ceph_connection *con) !test_bit(KEEPALIVE_PENDING, &con->flags)) { dout("fault %p setting STANDBY clearing WRITE_PENDING\n", con); clear_bit(WRITE_PENDING, &con->flags); - set_bit(STANDBY, &con->state); + con->state = CON_STATE_STANDBY; } else { /* retry after a delay. */ + con->state = CON_STATE_PREOPEN; if (con->delay == 0) con->delay = BASE_DELAY_INTERVAL; else if (con->delay < MAX_DELAY_INTERVAL) @@ -2431,8 +2436,9 @@ EXPORT_SYMBOL(ceph_messenger_init); static void clear_standby(struct ceph_connection *con) { /* come back from STANDBY? */ - if (test_and_clear_bit(STANDBY, &con->state)) { + if (con->state == CON_STATE_STANDBY) { dout("clear_standby %p and ++connect_seq\n", con); + con->state = CON_STATE_PREOPEN; con->connect_seq++; WARN_ON(test_bit(WRITE_PENDING, &con->flags)); WARN_ON(test_bit(KEEPALIVE_PENDING, &con->flags)); @@ -2451,7 +2457,7 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) mutex_lock(&con->mutex); - if (test_bit(CLOSED, &con->state)) { + if (con->state == CON_STATE_CLOSED) { dout("con_send %p closed, dropping %p\n", con, msg); ceph_msg_put(msg); mutex_unlock(&con->mutex); -- GitLab From 63c1362476141f4fb340e8236d41674be9fc1983 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 17:29:55 -0700 Subject: [PATCH 1131/1799] libceph: clean up con flags (cherry picked from commit 4a8616920860920abaa51193146fe36b38ef09aa) Rename flags with CON_FLAG prefix, move the definitions into the c file, and (better) document their meaning. Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 10 ------ net/ceph/messenger.c | 62 ++++++++++++++++++++-------------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index dc684f6bc55f..98442411c585 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -106,16 +106,6 @@ struct ceph_msg_pos { #define BASE_DELAY_INTERVAL (HZ/2) #define MAX_DELAY_INTERVAL (5 * 60 * HZ) -/* - * ceph_connection flag bits - */ - -#define LOSSYTX 0 /* we can close channel or drop messages on errors */ -#define KEEPALIVE_PENDING 3 -#define WRITE_PENDING 4 /* we have data ready to send */ -#define SOCK_CLOSED 11 /* socket state changed to closed */ -#define BACKOFF 15 - /* * A single connection with another host. * diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 8c239390c21d..ca703f131e95 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -87,6 +87,15 @@ #define CON_STATE_OPEN 5 /* -> STANDBY, CLOSED */ #define CON_STATE_STANDBY 6 /* -> PREOPEN, CLOSED */ +/* + * ceph_connection flag bits + */ +#define CON_FLAG_LOSSYTX 0 /* we can close channel or drop + * messages on errors */ +#define CON_FLAG_KEEPALIVE_PENDING 1 /* we need to send a keepalive */ +#define CON_FLAG_WRITE_PENDING 2 /* we have data ready to send */ +#define CON_FLAG_SOCK_CLOSED 3 /* socket state changed to closed */ +#define CON_FLAG_BACKOFF 4 /* need to retry queuing delayed work */ /* static tag bytes (protocol control messages) */ static char tag_msg = CEPH_MSGR_TAG_MSG; @@ -288,7 +297,7 @@ static void ceph_sock_write_space(struct sock *sk) * buffer. See net/ipv4/tcp_input.c:tcp_check_space() * and net/core/stream.c:sk_stream_write_space(). */ - if (test_bit(WRITE_PENDING, &con->flags)) { + if (test_bit(CON_FLAG_WRITE_PENDING, &con->flags)) { if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) { dout("%s %p queueing write work\n", __func__, con); clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); @@ -313,7 +322,7 @@ static void ceph_sock_state_change(struct sock *sk) case TCP_CLOSE_WAIT: dout("%s TCP_CLOSE_WAIT\n", __func__); con_sock_state_closing(con); - set_bit(SOCK_CLOSED, &con->flags); + set_bit(CON_FLAG_SOCK_CLOSED, &con->flags); queue_con(con); break; case TCP_ESTABLISHED: @@ -449,12 +458,12 @@ static int con_close_socket(struct ceph_connection *con) con->sock = NULL; /* - * Forcibly clear the SOCK_CLOSE flag. It gets set + * Forcibly clear the SOCK_CLOSED flag. It gets set * independent of the connection mutex, and we could have * received a socket close event before we had the chance to * shut the socket down. */ - clear_bit(SOCK_CLOSED, &con->flags); + clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags); con_sock_state_closed(con); return rc; } @@ -516,9 +525,9 @@ void ceph_con_close(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr)); con->state = CON_STATE_CLOSED; - clear_bit(LOSSYTX, &con->flags); /* so we retry next connect */ - clear_bit(KEEPALIVE_PENDING, &con->flags); - clear_bit(WRITE_PENDING, &con->flags); + clear_bit(CON_FLAG_LOSSYTX, &con->flags); /* so we retry next connect */ + clear_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags); + clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); reset_connection(con); con->peer_global_seq = 0; @@ -770,7 +779,7 @@ static void prepare_write_message(struct ceph_connection *con) /* no, queue up footer too and be done */ prepare_write_message_footer(con); - set_bit(WRITE_PENDING, &con->flags); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); } /* @@ -791,7 +800,7 @@ static void prepare_write_ack(struct ceph_connection *con) &con->out_temp_ack); con->out_more = 1; /* more will follow.. eventually.. */ - set_bit(WRITE_PENDING, &con->flags); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); } /* @@ -802,7 +811,7 @@ static void prepare_write_keepalive(struct ceph_connection *con) dout("prepare_write_keepalive %p\n", con); con_out_kvec_reset(con); con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive); - set_bit(WRITE_PENDING, &con->flags); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); } /* @@ -845,7 +854,7 @@ static void prepare_write_banner(struct ceph_connection *con) &con->msgr->my_enc_addr); con->out_more = 0; - set_bit(WRITE_PENDING, &con->flags); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); } static int prepare_write_connect(struct ceph_connection *con) @@ -896,7 +905,7 @@ static int prepare_write_connect(struct ceph_connection *con) auth->authorizer_buf); con->out_more = 0; - set_bit(WRITE_PENDING, &con->flags); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); return 0; } @@ -1622,7 +1631,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_reply.connect_seq)); if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY) - set_bit(LOSSYTX, &con->flags); + set_bit(CON_FLAG_LOSSYTX, &con->flags); con->delay = 0; /* reset backoff memory */ @@ -2061,14 +2070,15 @@ static int try_write(struct ceph_connection *con) prepare_write_ack(con); goto more; } - if (test_and_clear_bit(KEEPALIVE_PENDING, &con->flags)) { + if (test_and_clear_bit(CON_FLAG_KEEPALIVE_PENDING, + &con->flags)) { prepare_write_keepalive(con); goto more; } } /* Nothing to do! */ - clear_bit(WRITE_PENDING, &con->flags); + clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); dout("try_write nothing else to write.\n"); ret = 0; out: @@ -2241,7 +2251,7 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: - if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) { + if (test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) { switch (con->state) { case CON_STATE_CONNECTING: con->error_msg = "connection failed"; @@ -2260,7 +2270,7 @@ static void con_work(struct work_struct *work) goto fault; } - if (test_and_clear_bit(BACKOFF, &con->flags)) { + if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) { dout("con_work %p backing off\n", con); if (queue_delayed_work(ceph_msgr_wq, &con->work, round_jiffies_relative(con->delay))) { @@ -2336,7 +2346,7 @@ static void ceph_fault(struct ceph_connection *con) con_close_socket(con); - if (test_bit(LOSSYTX, &con->flags)) { + if (test_bit(CON_FLAG_LOSSYTX, &con->flags)) { dout("fault on LOSSYTX channel, marking CLOSED\n"); con->state = CON_STATE_CLOSED; goto out_unlock; @@ -2356,9 +2366,9 @@ static void ceph_fault(struct ceph_connection *con) /* If there are no messages queued or keepalive pending, place * the connection in a STANDBY state */ if (list_empty(&con->out_queue) && - !test_bit(KEEPALIVE_PENDING, &con->flags)) { + !test_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags)) { dout("fault %p setting STANDBY clearing WRITE_PENDING\n", con); - clear_bit(WRITE_PENDING, &con->flags); + clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); con->state = CON_STATE_STANDBY; } else { /* retry after a delay. */ @@ -2383,7 +2393,7 @@ static void ceph_fault(struct ceph_connection *con) * that when con_work restarts we schedule the * delay then. */ - set_bit(BACKOFF, &con->flags); + set_bit(CON_FLAG_BACKOFF, &con->flags); } } @@ -2440,8 +2450,8 @@ static void clear_standby(struct ceph_connection *con) dout("clear_standby %p and ++connect_seq\n", con); con->state = CON_STATE_PREOPEN; con->connect_seq++; - WARN_ON(test_bit(WRITE_PENDING, &con->flags)); - WARN_ON(test_bit(KEEPALIVE_PENDING, &con->flags)); + WARN_ON(test_bit(CON_FLAG_WRITE_PENDING, &con->flags)); + WARN_ON(test_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags)); } } @@ -2482,7 +2492,7 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) /* if there wasn't anything waiting to send before, queue * new work */ - if (test_and_set_bit(WRITE_PENDING, &con->flags) == 0) + if (test_and_set_bit(CON_FLAG_WRITE_PENDING, &con->flags) == 0) queue_con(con); } EXPORT_SYMBOL(ceph_con_send); @@ -2571,8 +2581,8 @@ void ceph_con_keepalive(struct ceph_connection *con) mutex_lock(&con->mutex); clear_standby(con); mutex_unlock(&con->mutex); - if (test_and_set_bit(KEEPALIVE_PENDING, &con->flags) == 0 && - test_and_set_bit(WRITE_PENDING, &con->flags) == 0) + if (test_and_set_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags) == 0 && + test_and_set_bit(CON_FLAG_WRITE_PENDING, &con->flags) == 0) queue_con(con); } EXPORT_SYMBOL(ceph_con_keepalive); -- GitLab From 8992551d85934e0dc4683068612758831d1d4899 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 20 Jul 2012 17:30:40 -0700 Subject: [PATCH 1132/1799] libceph: clear all flags on con_close Signed-off-by: Sage Weil (cherry picked from commit 43c7427d100769451601b8a36988ac0528ce0124) --- net/ceph/messenger.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index ca703f131e95..e97bb59db1ac 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -528,6 +528,8 @@ void ceph_con_close(struct ceph_connection *con) clear_bit(CON_FLAG_LOSSYTX, &con->flags); /* so we retry next connect */ clear_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags); clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); + clear_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags); + clear_bit(CON_FLAG_BACKOFF, &con->flags); reset_connection(con); con->peer_global_seq = 0; -- GitLab From 6cdaef1be27bc05ab4197b3ab4e3ee1d326cf04c Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 18:16:16 -0700 Subject: [PATCH 1133/1799] libceph: fix handling of immediate socket connect failure (cherry picked from commit 8007b8d626b49c34fb146ec16dc639d8b10c862f) If the connect() call immediately fails such that sock == NULL, we still need con_close_socket() to reset our socket state to CLOSED. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index e97bb59db1ac..8edc0c14f1c1 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -224,6 +224,8 @@ static void con_sock_state_init(struct ceph_connection *con) old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); if (WARN_ON(old_state != CON_SOCK_STATE_NEW)) printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CLOSED); } static void con_sock_state_connecting(struct ceph_connection *con) @@ -233,6 +235,8 @@ static void con_sock_state_connecting(struct ceph_connection *con) old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTING); if (WARN_ON(old_state != CON_SOCK_STATE_CLOSED)) printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CONNECTING); } static void con_sock_state_connected(struct ceph_connection *con) @@ -242,6 +246,8 @@ static void con_sock_state_connected(struct ceph_connection *con) old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTED); if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTING)) printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CONNECTED); } static void con_sock_state_closing(struct ceph_connection *con) @@ -253,6 +259,8 @@ static void con_sock_state_closing(struct ceph_connection *con) old_state != CON_SOCK_STATE_CONNECTED && old_state != CON_SOCK_STATE_CLOSING)) printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CLOSING); } static void con_sock_state_closed(struct ceph_connection *con) @@ -262,8 +270,11 @@ static void con_sock_state_closed(struct ceph_connection *con) old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTED && old_state != CON_SOCK_STATE_CLOSING && - old_state != CON_SOCK_STATE_CONNECTING)) + old_state != CON_SOCK_STATE_CONNECTING && + old_state != CON_SOCK_STATE_CLOSED)) printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CLOSED); } /* @@ -448,14 +459,14 @@ static int ceph_tcp_sendpage(struct socket *sock, struct page *page, */ static int con_close_socket(struct ceph_connection *con) { - int rc; + int rc = 0; dout("con_close_socket on %p sock %p\n", con, con->sock); - if (!con->sock) - return 0; - rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR); - sock_release(con->sock); - con->sock = NULL; + if (con->sock) { + rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR); + sock_release(con->sock); + con->sock = NULL; + } /* * Forcibly clear the SOCK_CLOSED flag. It gets set @@ -464,6 +475,7 @@ static int con_close_socket(struct ceph_connection *con) * shut the socket down. */ clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags); + con_sock_state_closed(con); return rc; } -- GitLab From da75ae3c0d4c40587fa7583952b98072d811a7d2 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 18:16:40 -0700 Subject: [PATCH 1134/1799] libceph: revoke mon_client messages on session restart (cherry picked from commit 4f471e4a9c7db0256834e1b376ea50c82e345c3c) Revoke all mon_client messages when we shut down the old connection. This is mostly moot since we are re-using the same ceph_connection, but it is cleaner. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/mon_client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 9f00d6cd93e2..275aec2f1753 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -118,6 +118,9 @@ static void __close_session(struct ceph_mon_client *monc) { dout("__close_session closing mon%d\n", monc->cur_mon); ceph_msg_revoke(monc->m_auth); + ceph_msg_revoke_incoming(monc->m_auth_reply); + ceph_msg_revoke(monc->m_subscribe); + ceph_msg_revoke_incoming(monc->m_subscribe_ack); ceph_con_close(&monc->con); monc->cur_mon = -1; monc->pending_auth = 0; @@ -685,6 +688,7 @@ static void __resend_generic_request(struct ceph_mon_client *monc) for (p = rb_first(&monc->generic_request_tree); p; p = rb_next(p)) { req = rb_entry(p, struct ceph_mon_generic_request, node); ceph_msg_revoke(req->request); + ceph_msg_revoke_incoming(req->reply); ceph_con_send(&monc->con, ceph_msg_get(req->request)); } } -- GitLab From 900fbd910f53a417a6b0859bd2cde7ae48ac4bb2 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 18:16:56 -0700 Subject: [PATCH 1135/1799] libceph: verify state after retaking con lock after dispatch (cherry picked from commit 7b862e07b1a4d5c963d19027f10ea78085f27f9b) We drop the con mutex when delivering a message. When we retake the lock, we need to verify we are still in the OPEN state before preparing to read the next tag, or else we risk stepping on a connection that has been closed. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 8edc0c14f1c1..bb21e5b0fb55 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2003,7 +2003,6 @@ static void process_message(struct ceph_connection *con) con->ops->dispatch(con, msg); mutex_lock(&con->mutex); - prepare_read_tag(con); } @@ -2213,6 +2212,8 @@ static int try_read(struct ceph_connection *con) if (con->in_tag == CEPH_MSGR_TAG_READY) goto more; process_message(con); + if (con->state == CON_STATE_OPEN) + prepare_read_tag(con); goto more; } if (con->in_tag == CEPH_MSGR_TAG_ACK) { -- GitLab From 328677c24bbae17f3f91ffce3b2351a27933741c Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 18:17:13 -0700 Subject: [PATCH 1136/1799] libceph: avoid dropping con mutex before fault (cherry picked from commit 8636ea672f0c5ab7478c42c5b6705ebd1db7eb6a) The ceph_fault() function takes the con mutex, so we should avoid dropping it before calling it. This fixes a potential race with another thread calling ceph_con_close(), or _open(), or similar (we don't reverify con->state after retaking the lock). Add annotation so that lockdep realizes we will drop the mutex before returning. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index bb21e5b0fb55..c2f0ca36f4ab 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2336,7 +2336,6 @@ static void con_work(struct work_struct *work) return; fault: - mutex_unlock(&con->mutex); ceph_fault(con); /* error/fault path */ goto done_unlocked; } @@ -2347,9 +2346,8 @@ static void con_work(struct work_struct *work) * exponential backoff */ static void ceph_fault(struct ceph_connection *con) + __releases(con->mutex) { - mutex_lock(&con->mutex); - pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg); dout("fault %p state %lu to peer %s\n", -- GitLab From 7389a76f02bf56340f26fa933b9fc6a1dece9148 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 18:19:30 -0700 Subject: [PATCH 1137/1799] libceph: change ceph_con_in_msg_alloc convention to be less weird (cherry picked from commit 4740a623d20c51d167da7f752b63e2b8714b2543) This function's calling convention is very limiting. In particular, we can't return any error other than ENOMEM (and only implicitly), which is a problem (see next patch). Instead, return an normal 0 or error code, and make the skip a pointer output parameter. Drop the useless in_hdr argument (we have the con pointer). Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 56 ++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index c2f0ca36f4ab..bfd0878c5c4e 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1733,9 +1733,7 @@ static int read_partial_message_section(struct ceph_connection *con, return 1; } -static bool ceph_con_in_msg_alloc(struct ceph_connection *con, - struct ceph_msg_header *hdr); - +static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip); static int read_partial_message_pages(struct ceph_connection *con, struct page **pages, @@ -1864,9 +1862,14 @@ static int read_partial_message(struct ceph_connection *con) /* allocate message? */ if (!con->in_msg) { + int skip = 0; + dout("got hdr type %d front %d data %d\n", con->in_hdr.type, con->in_hdr.front_len, con->in_hdr.data_len); - if (ceph_con_in_msg_alloc(con, &con->in_hdr)) { + ret = ceph_con_in_msg_alloc(con, &skip); + if (ret < 0) + return ret; + if (skip) { /* skip this message */ dout("alloc_msg said skip message\n"); BUG_ON(con->in_msg); @@ -1876,12 +1879,8 @@ static int read_partial_message(struct ceph_connection *con) con->in_seq++; return 0; } - if (!con->in_msg) { - con->error_msg = - "error allocating memory for incoming message"; - return -ENOMEM; - } + BUG_ON(!con->in_msg); BUG_ON(con->in_msg->con != con); m = con->in_msg; m->front.iov_len = 0; /* haven't read it yet */ @@ -2715,43 +2714,50 @@ static int ceph_alloc_middle(struct ceph_connection *con, struct ceph_msg *msg) * connection, and save the result in con->in_msg. Uses the * connection's private alloc_msg op if available. * - * Returns true if the message should be skipped, false otherwise. - * If true is returned (skip message), con->in_msg will be NULL. - * If false is returned, con->in_msg will contain a pointer to the - * newly-allocated message, or NULL in case of memory exhaustion. + * Returns 0 on success, or a negative error code. + * + * On success, if we set *skip = 1: + * - the next message should be skipped and ignored. + * - con->in_msg == NULL + * or if we set *skip = 0: + * - con->in_msg is non-null. + * On error (ENOMEM, EAGAIN, ...), + * - con->in_msg == NULL */ -static bool ceph_con_in_msg_alloc(struct ceph_connection *con, - struct ceph_msg_header *hdr) +static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip) { + struct ceph_msg_header *hdr = &con->in_hdr; int type = le16_to_cpu(hdr->type); int front_len = le32_to_cpu(hdr->front_len); int middle_len = le32_to_cpu(hdr->middle_len); - int ret; + int ret = 0; BUG_ON(con->in_msg != NULL); if (con->ops->alloc_msg) { - int skip = 0; - mutex_unlock(&con->mutex); - con->in_msg = con->ops->alloc_msg(con, hdr, &skip); + con->in_msg = con->ops->alloc_msg(con, hdr, skip); mutex_lock(&con->mutex); if (con->in_msg) { con->in_msg->con = con->ops->get(con); BUG_ON(con->in_msg->con == NULL); } - if (skip) + if (*skip) { con->in_msg = NULL; - - if (!con->in_msg) - return skip != 0; + return 0; + } + if (!con->in_msg) { + con->error_msg = + "error allocating memory for incoming message"; + return -ENOMEM; + } } if (!con->in_msg) { con->in_msg = ceph_msg_new(type, front_len, GFP_NOFS, false); if (!con->in_msg) { pr_err("unable to allocate msg type %d len %d\n", type, front_len); - return false; + return -ENOMEM; } con->in_msg->con = con->ops->get(con); BUG_ON(con->in_msg->con == NULL); @@ -2767,7 +2773,7 @@ static bool ceph_con_in_msg_alloc(struct ceph_connection *con, } } - return false; + return ret; } -- GitLab From 59238927cc8ea6c1e4a8a1136e17598648832db0 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 18:19:45 -0700 Subject: [PATCH 1138/1799] libceph: recheck con state after allocating incoming message (cherry picked from commit 6139919133377652992a5fe134e22abce3e9c25e) We drop the lock when calling the ->alloc_msg() con op, which means we need to (a) not clobber con->in_msg without the mutex held, and (b) we need to verify that we are still in the OPEN state when we retake it to avoid causing any mayhem. If the state does change, -EAGAIN will get us back to con_work() and loop. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index bfd0878c5c4e..0de5a706f2b7 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2735,9 +2735,16 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip) BUG_ON(con->in_msg != NULL); if (con->ops->alloc_msg) { + struct ceph_msg *msg; + mutex_unlock(&con->mutex); - con->in_msg = con->ops->alloc_msg(con, hdr, skip); + msg = con->ops->alloc_msg(con, hdr, skip); mutex_lock(&con->mutex); + if (con->state != CON_STATE_OPEN) { + ceph_msg_put(msg); + return -EAGAIN; + } + con->in_msg = msg; if (con->in_msg) { con->in_msg->con = con->ops->get(con); BUG_ON(con->in_msg->con == NULL); -- GitLab From b8e03e320f9156e870f8cc66b0d9fca9f24d36c8 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Thu, 2 Aug 2012 09:12:59 -0700 Subject: [PATCH 1139/1799] libceph: fix crypto key null deref, memory leak (cherry picked from commit f0666b1ac875ff32fe290219b150ec62eebbe10e) Avoid crashing if the crypto key payload was NULL, as when it was not correctly allocated and initialized. Also, avoid leaking it. Signed-off-by: Sylvain Munaut Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/crypto.c | 1 + net/ceph/crypto.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index b780cb7947dd..9da7fdd3cd8a 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c @@ -466,6 +466,7 @@ void ceph_key_destroy(struct key *key) { struct ceph_crypto_key *ckey = key->payload.data; ceph_crypto_key_destroy(ckey); + kfree(ckey); } struct key_type key_type_ceph = { diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h index 1919d1550d75..3572dc518bc9 100644 --- a/net/ceph/crypto.h +++ b/net/ceph/crypto.h @@ -16,7 +16,8 @@ struct ceph_crypto_key { static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key) { - kfree(key->key); + if (key) + kfree(key->key); } extern int ceph_crypto_key_clone(struct ceph_crypto_key *dst, -- GitLab From 523693067608f067bcbe94f23a4feb4dfcfa2db8 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Sun, 19 Aug 2012 12:29:16 -0700 Subject: [PATCH 1140/1799] libceph: delay debugfs initialization until we learn global_id (cherry picked from commit d1c338a509cea5378df59629ad47382810c38623) The debugfs directory includes the cluster fsid and our unique global_id. We need to delay the initialization of the debug entry until we have learned both the fsid and our global_id from the monitor or else the second client can't create its debugfs entry and will fail (and multiple client instances aren't properly reflected in debugfs). Reported by: Yan, Zheng Signed-off-by: Sage Weil Reviewed-by: Yehuda Sadeh Signed-off-by: Greg Kroah-Hartman --- fs/ceph/debugfs.c | 1 + net/ceph/ceph_common.c | 1 - net/ceph/debugfs.c | 4 ++++ net/ceph/mon_client.c | 51 +++++++++++++++++++++++++++++++++++++----- 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index fb962efdacee..6d59006bfa27 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -201,6 +201,7 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) int err = -ENOMEM; dout("ceph_fs_debugfs_init\n"); + BUG_ON(!fsc->client->debugfs_dir); fsc->debugfs_congestion_kb = debugfs_create_file("writeback_congestion_kb", 0600, diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 52fe52cde606..8e74e8c5a774 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -83,7 +83,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) return -1; } } else { - pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid); memcpy(&client->fsid, fsid, sizeof(*fsid)); } return 0; diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c index 27d4ea315d12..680978d00446 100644 --- a/net/ceph/debugfs.c +++ b/net/ceph/debugfs.c @@ -189,6 +189,9 @@ int ceph_debugfs_client_init(struct ceph_client *client) snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid, client->monc.auth->global_id); + dout("ceph_debugfs_client_init %p %s\n", client, name); + + BUG_ON(client->debugfs_dir); client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir); if (!client->debugfs_dir) goto out; @@ -234,6 +237,7 @@ int ceph_debugfs_client_init(struct ceph_client *client) void ceph_debugfs_client_cleanup(struct ceph_client *client) { + dout("ceph_debugfs_client_cleanup %p\n", client); debugfs_remove(client->debugfs_osdmap); debugfs_remove(client->debugfs_monmap); debugfs_remove(client->osdc.debugfs_file); diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 275aec2f1753..89a6409b4e1d 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -310,6 +310,17 @@ int ceph_monc_open_session(struct ceph_mon_client *monc) } EXPORT_SYMBOL(ceph_monc_open_session); +/* + * We require the fsid and global_id in order to initialize our + * debugfs dir. + */ +static bool have_debugfs_info(struct ceph_mon_client *monc) +{ + dout("have_debugfs_info fsid %d globalid %lld\n", + (int)monc->client->have_fsid, monc->auth->global_id); + return monc->client->have_fsid && monc->auth->global_id > 0; +} + /* * The monitor responds with mount ack indicate mount success. The * included client ticket allows the client to talk to MDSs and OSDs. @@ -320,9 +331,12 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, struct ceph_client *client = monc->client; struct ceph_monmap *monmap = NULL, *old = monc->monmap; void *p, *end; + int had_debugfs_info, init_debugfs = 0; mutex_lock(&monc->mutex); + had_debugfs_info = have_debugfs_info(monc); + dout("handle_monmap\n"); p = msg->front.iov_base; end = p + msg->front.iov_len; @@ -344,12 +358,22 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, if (!client->have_fsid) { client->have_fsid = true; + if (!had_debugfs_info && have_debugfs_info(monc)) { + pr_info("client%lld fsid %pU\n", + ceph_client_id(monc->client), + &monc->client->fsid); + init_debugfs = 1; + } mutex_unlock(&monc->mutex); - /* - * do debugfs initialization without mutex to avoid - * creating a locking dependency - */ - ceph_debugfs_client_init(client); + + if (init_debugfs) { + /* + * do debugfs initialization without mutex to avoid + * creating a locking dependency + */ + ceph_debugfs_client_init(monc->client); + } + goto out_unlocked; } out: @@ -865,8 +889,10 @@ static void handle_auth_reply(struct ceph_mon_client *monc, { int ret; int was_auth = 0; + int had_debugfs_info, init_debugfs = 0; mutex_lock(&monc->mutex); + had_debugfs_info = have_debugfs_info(monc); if (monc->auth->ops) was_auth = monc->auth->ops->is_authenticated(monc->auth); monc->pending_auth = 0; @@ -889,7 +915,22 @@ static void handle_auth_reply(struct ceph_mon_client *monc, __send_subscribe(monc); __resend_generic_request(monc); } + + if (!had_debugfs_info && have_debugfs_info(monc)) { + pr_info("client%lld fsid %pU\n", + ceph_client_id(monc->client), + &monc->client->fsid); + init_debugfs = 1; + } mutex_unlock(&monc->mutex); + + if (init_debugfs) { + /* + * do debugfs initialization without mutex to avoid + * creating a locking dependency + */ + ceph_debugfs_client_init(monc->client); + } } static int __validate_auth(struct ceph_mon_client *monc) -- GitLab From 76cb69279f83889cf98fd9f16f5d50bcc2779442 Mon Sep 17 00:00:00 2001 From: Jim Schutt Date: Fri, 10 Aug 2012 10:37:38 -0700 Subject: [PATCH 1141/1799] libceph: avoid truncation due to racing banners (cherry picked from commit 6d4221b53707486dfad3f5bfe568d2ce7f4c9863) Because the Ceph client messenger uses a non-blocking connect, it is possible for the sending of the client banner to race with the arrival of the banner sent by the peer. When ceph_sock_state_change() notices the connect has completed, it schedules work to process the socket via con_work(). During this time the peer is writing its banner, and arrival of the peer banner races with con_work(). If con_work() calls try_read() before the peer banner arrives, there is nothing for it to do, after which con_work() calls try_write() to send the client's banner. In this case Ceph's protocol negotiation can complete succesfully. The server-side messenger immediately sends its banner and addresses after accepting a connect request, *before* actually attempting to read or verify the banner from the client. As a result, it is possible for the banner from the server to arrive before con_work() calls try_read(). If that happens, try_read() will read the banner and prepare protocol negotiation info via prepare_write_connect(). prepare_write_connect() calls con_out_kvec_reset(), which discards the as-yet-unsent client banner. Next, con_work() calls try_write(), which sends the protocol negotiation info rather than the banner that the peer is expecting. The result is that the peer sees an invalid banner, and the client reports "negotiation failed". Fix this by moving con_out_kvec_reset() out of prepare_write_connect() to its callers at all locations except the one where the banner might still need to be sent. [elder@inktak.com: added note about server-side behavior] Signed-off-by: Jim Schutt Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 0de5a706f2b7..5f312510f49c 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -911,7 +911,6 @@ static int prepare_write_connect(struct ceph_connection *con) con->out_connect.authorizer_len = auth ? cpu_to_le32(auth->authorizer_buf_len) : 0; - con_out_kvec_reset(con); con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); if (auth && auth->authorizer_buf_len) @@ -1553,6 +1552,7 @@ static int process_connect(struct ceph_connection *con) return -1; } con->auth_retry = 1; + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1573,6 +1573,7 @@ static int process_connect(struct ceph_connection *con) ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr)); reset_connection(con); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1597,6 +1598,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->out_connect.connect_seq), le32_to_cpu(con->in_reply.connect_seq)); con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -1613,6 +1615,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_reply.global_seq)); get_global_seq(con->msgr, le32_to_cpu(con->in_reply.global_seq)); + con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) return ret; @@ -2131,7 +2134,11 @@ static int try_read(struct ceph_connection *con) BUG_ON(con->state != CON_STATE_CONNECTING); con->state = CON_STATE_NEGOTIATING; - /* Banner is good, exchange connection info */ + /* + * Received banner is good, exchange connection info. + * Do not reset out_kvec, as sending our banner raced + * with receiving peer banner after connect completed. + */ ret = prepare_write_connect(con); if (ret < 0) goto out; -- GitLab From 21e292e34c48c03fb6638c2d1295ca12dac97b03 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 21 Sep 2012 17:59:58 -0500 Subject: [PATCH 1142/1799] libceph: only kunmap kmapped pages (cherry picked from commit 5ce765a540f34d1e2005e1210f49f67fdf11e997) In write_partial_msg_pages(), pages need to be kmapped in order to perform a CRC-32c calculation on them. As an artifact of the way this code used to be structured, the kunmap() call was separated from the kmap() call and both were done conditionally. But the conditions under which the kmap() and kunmap() calls were made differed, so there was a chance a kunmap() call would be done on a page that had not been mapped. The symptom of this was tripping a BUG() in kunmap_high() when pkmap_count[nr] became 0. Reported-by: Bryan K. Wright Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 5f312510f49c..6577a9fc6ce7 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1069,16 +1069,13 @@ static int write_partial_msg_pages(struct ceph_connection *con) BUG_ON(kaddr == NULL); base = kaddr + con->out_msg_pos.page_pos + bio_offset; crc = crc32c(crc, base, len); + kunmap(page); msg->footer.data_crc = cpu_to_le32(crc); con->out_msg_pos.did_page_crc = true; } ret = ceph_tcp_sendpage(con->sock, page, con->out_msg_pos.page_pos + bio_offset, len, 1); - - if (do_datacrc) - kunmap(page); - if (ret <= 0) goto out; -- GitLab From a872024581f2e73edbea6eece56361ce508ea881 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 8 Oct 2012 20:37:30 -0700 Subject: [PATCH 1143/1799] rbd: reset BACKOFF if unable to re-queue (cherry picked from commit 588377d6199034c36d335e7df5818b731fea072c) If ceph_fault() is unable to queue work after a delay, it sets the BACKOFF connection flag so con_work() will attempt to do so. In con_work(), when BACKOFF is set, if queue_delayed_work() doesn't result in newly-queued work, it simply ignores this condition and proceeds as if no backoff delay were desired. There are two problems with this--one of which is a bug. The first problem is simply that the intended behavior is to back off, and if we aren't able queue the work item to run after a delay we're not doing that. The only reason queue_delayed_work() won't queue work is if the provided work item is already queued. In the messenger, this means that con_work() is already scheduled to be run again. So if we simply set the BACKOFF flag again when this occurs, we know the next con_work() call will again attempt to hold off activity on the connection until after the delay. The second problem--the bug--is a leak of a reference count. If queue_delayed_work() returns 0 in con_work(), con->ops->put() drops the connection reference held on entry to con_work(). However, processing is (was) allowed to continue, and at the end of the function a second con->ops->put() is called. This patch fixes both problems. Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 6577a9fc6ce7..84f34c3f3e90 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2296,10 +2296,11 @@ static void con_work(struct work_struct *work) mutex_unlock(&con->mutex); return; } else { - con->ops->put(con); dout("con_work %p FAILED to back off %lu\n", con, con->delay); + set_bit(CON_FLAG_BACKOFF, &con->flags); } + goto done; } if (con->state == CON_STATE_STANDBY) { -- GitLab From 631015e45ee3bdcde1fe75e7d04fdfece6e42016 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 24 Oct 2012 16:12:58 -0700 Subject: [PATCH 1144/1799] libceph: avoid NULL kref_put when osd reset races with alloc_msg (cherry picked from commit 9bd952615a42d7e2ce3fa2c632e808e804637a1a) The ceph_on_in_msg_alloc() method drops con->mutex while it allocates a message. If that races with a timeout that resends a zillion messages and resets the connection, and the ->alloc_msg() method returns a NULL message, it will call ceph_msg_put(NULL) and BUG. Fix by only calling put if msg is non-NULL. Fixes http://tracker.newdream.net/issues/3142 Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 84f34c3f3e90..aa71a67450af 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2746,7 +2746,8 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip) msg = con->ops->alloc_msg(con, hdr, skip); mutex_lock(&con->mutex); if (con->state != CON_STATE_OPEN) { - ceph_msg_put(msg); + if (msg) + ceph_msg_put(msg); return -EAGAIN; } con->in_msg = msg; -- GitLab From 73bba6fc44591587254fec8e867a99b5a2a28ba7 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 20 Sep 2012 17:42:25 +0800 Subject: [PATCH 1145/1799] ceph: Fix oops when handling mdsmap that decreases max_mds (cherry picked from commit 3e8f43a089f06279c5f76a9ccd42578eebf7bfa5) When i >= newmap->m_max_mds, ceph_mdsmap_get_addr(newmap, i) return NULL. Passing NULL to memcmp() triggers oops. Signed-off-by: Yan, Zheng Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/mds_client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 5ac6434185ae..7f1682da29a7 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2634,7 +2634,8 @@ static void check_new_map(struct ceph_mds_client *mdsc, ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "", session_state_name(s->s_state)); - if (memcmp(ceph_mdsmap_get_addr(oldmap, i), + if (i >= newmap->m_max_mds || + memcmp(ceph_mdsmap_get_addr(oldmap, i), ceph_mdsmap_get_addr(newmap, i), sizeof(struct ceph_entity_addr))) { if (s->s_state == CEPH_MDS_SESSION_OPENING) { -- GitLab From dfae3b3451c6da14df1fa62d76c8a4345d21bdb2 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 24 Sep 2012 20:59:48 -0700 Subject: [PATCH 1146/1799] libceph: check for invalid mapping (cherry picked from commit d63b77f4c552cc3a20506871046ab0fcbc332609) If we encounter an invalid (e.g., zeroed) mapping, return an error and avoid a divide by zero. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/osd_client.h | 2 +- include/linux/ceph/osdmap.h | 6 +++--- net/ceph/osd_client.c | 32 ++++++++++++++++++++------------ net/ceph/osdmap.c | 18 ++++++++++++++++-- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h index cedfb1a8434a..d9b880e977e6 100644 --- a/include/linux/ceph/osd_client.h +++ b/include/linux/ceph/osd_client.h @@ -207,7 +207,7 @@ extern void ceph_osdc_handle_reply(struct ceph_osd_client *osdc, extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg); -extern void ceph_calc_raw_layout(struct ceph_osd_client *osdc, +extern int ceph_calc_raw_layout(struct ceph_osd_client *osdc, struct ceph_file_layout *layout, u64 snapid, u64 off, u64 *plen, u64 *bno, diff --git a/include/linux/ceph/osdmap.h b/include/linux/ceph/osdmap.h index ba4c205cbb01..11db454f7865 100644 --- a/include/linux/ceph/osdmap.h +++ b/include/linux/ceph/osdmap.h @@ -111,9 +111,9 @@ extern struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, extern void ceph_osdmap_destroy(struct ceph_osdmap *map); /* calculate mapping of a file extent to an object */ -extern void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, - u64 off, u64 *plen, - u64 *bno, u64 *oxoff, u64 *oxlen); +extern int ceph_calc_file_object_mapping(struct ceph_file_layout *layout, + u64 off, u64 *plen, + u64 *bno, u64 *oxoff, u64 *oxlen); /* calculate mapping of object to a placement group */ extern int ceph_calc_object_layout(struct ceph_object_layout *ol, diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 56fd974b7656..a79dbae3ea90 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -52,7 +52,7 @@ static int op_has_extent(int op) op == CEPH_OSD_OP_WRITE); } -void ceph_calc_raw_layout(struct ceph_osd_client *osdc, +int ceph_calc_raw_layout(struct ceph_osd_client *osdc, struct ceph_file_layout *layout, u64 snapid, u64 off, u64 *plen, u64 *bno, @@ -62,12 +62,15 @@ void ceph_calc_raw_layout(struct ceph_osd_client *osdc, struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base; u64 orig_len = *plen; u64 objoff, objlen; /* extent in object */ + int r; reqhead->snapid = cpu_to_le64(snapid); /* object extent? */ - ceph_calc_file_object_mapping(layout, off, plen, bno, - &objoff, &objlen); + r = ceph_calc_file_object_mapping(layout, off, plen, bno, + &objoff, &objlen); + if (r < 0) + return r; if (*plen < orig_len) dout(" skipping last %llu, final file extent %llu~%llu\n", orig_len - *plen, off, *plen); @@ -83,7 +86,7 @@ void ceph_calc_raw_layout(struct ceph_osd_client *osdc, dout("calc_layout bno=%llx %llu~%llu (%d pages)\n", *bno, objoff, objlen, req->r_num_pages); - + return 0; } EXPORT_SYMBOL(ceph_calc_raw_layout); @@ -112,20 +115,25 @@ EXPORT_SYMBOL(ceph_calc_raw_layout); * * fill osd op in request message. */ -static void calc_layout(struct ceph_osd_client *osdc, - struct ceph_vino vino, - struct ceph_file_layout *layout, - u64 off, u64 *plen, - struct ceph_osd_request *req, - struct ceph_osd_req_op *op) +static int calc_layout(struct ceph_osd_client *osdc, + struct ceph_vino vino, + struct ceph_file_layout *layout, + u64 off, u64 *plen, + struct ceph_osd_request *req, + struct ceph_osd_req_op *op) { u64 bno; + int r; - ceph_calc_raw_layout(osdc, layout, vino.snap, off, - plen, &bno, req, op); + r = ceph_calc_raw_layout(osdc, layout, vino.snap, off, + plen, &bno, req, op); + if (r < 0) + return r; snprintf(req->r_oid, sizeof(req->r_oid), "%llx.%08llx", vino.ino, bno); req->r_oid_len = strlen(req->r_oid); + + return r; } /* diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index c77133405ff5..430076ee938e 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -952,7 +952,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, * for now, we write only a single su, until we can * pass a stride back to the caller. */ -void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, +int ceph_calc_file_object_mapping(struct ceph_file_layout *layout, u64 off, u64 *plen, u64 *ono, u64 *oxoff, u64 *oxlen) @@ -966,11 +966,17 @@ void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, dout("mapping %llu~%llu osize %u fl_su %u\n", off, *plen, osize, su); + if (su == 0 || sc == 0) + goto invalid; su_per_object = osize / su; + if (su_per_object == 0) + goto invalid; dout("osize %u / su %u = su_per_object %u\n", osize, su, su_per_object); - BUG_ON((su & ~PAGE_MASK) != 0); + if ((su & ~PAGE_MASK) != 0) + goto invalid; + /* bl = *off / su; */ t = off; do_div(t, su); @@ -998,6 +1004,14 @@ void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, *plen = *oxlen; dout(" obj extent %llu~%llu\n", *oxoff, *oxlen); + return 0; + +invalid: + dout(" invalid layout\n"); + *ono = 0; + *oxoff = 0; + *oxlen = 0; + return -EINVAL; } EXPORT_SYMBOL(ceph_calc_file_object_mapping); -- GitLab From b7d68a7434bbfd57049927ca713d57e44e0eee04 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Oct 2012 10:25:51 -0500 Subject: [PATCH 1147/1799] ceph: avoid 32-bit page index overflow (cherry picked from commit 6285bc231277419255f3498d3eb5ddc9f8e7fe79) A pgoff_t is defined (by default) to have type (unsigned long). On architectures such as i686 that's a 32-bit type. The ceph address space code was attempting to produce 64 bit offsets by shifting a page's index by PAGE_CACHE_SHIFT, but the result was not what was desired because the shift occurred before the result got promoted to 64 bits. Fix this by converting all uses of page->index used in this way to use the page_offset() macro, which ensures the 64-bit result has the intended value. This fixes http://tracker.newdream.net/issues/3112 Reported-by: Mohamed Pakkeer Signed-off-by: Alex Elder Reviewed-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- fs/ceph/addr.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 8b67304e4b80..32ee086c259b 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -205,7 +205,7 @@ static int readpage_nounlock(struct file *filp, struct page *page) dout("readpage inode %p file %p page %p index %lu\n", inode, filp, page, page->index); err = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout, - page->index << PAGE_CACHE_SHIFT, &len, + (u64) page_offset(page), &len, ci->i_truncate_seq, ci->i_truncate_size, &page, 1, 0); if (err == -ENOENT) @@ -286,7 +286,7 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max) int nr_pages = 0; int ret; - off = page->index << PAGE_CACHE_SHIFT; + off = (u64) page_offset(page); /* count pages */ next_index = page->index; @@ -426,7 +426,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) struct ceph_inode_info *ci; struct ceph_fs_client *fsc; struct ceph_osd_client *osdc; - loff_t page_off = page->index << PAGE_CACHE_SHIFT; + loff_t page_off = page_offset(page); int len = PAGE_CACHE_SIZE; loff_t i_size; int err = 0; @@ -817,8 +817,7 @@ static int ceph_writepages_start(struct address_space *mapping, /* ok */ if (locked_pages == 0) { /* prepare async write request */ - offset = (unsigned long long)page->index - << PAGE_CACHE_SHIFT; + offset = (u64) page_offset(page); len = wsize; req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, @@ -1180,7 +1179,7 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) struct inode *inode = vma->vm_file->f_dentry->d_inode; struct page *page = vmf->page; struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; - loff_t off = page->index << PAGE_CACHE_SHIFT; + loff_t off = page_offset(page); loff_t size, len; int ret; -- GitLab From 8217df07c9d8debd39a6d8e1e2271e97a3c899c7 Mon Sep 17 00:00:00 2001 From: Igor Murzov Date: Sat, 13 Oct 2012 04:41:25 +0400 Subject: [PATCH 1148/1799] ACPI video: Ignore errors after _DOD evaluation. commit fba4e087361605d1eed63343bb08811f097c83ee upstream. There are systems where video module known to work fine regardless of broken _DOD and ignoring returned value here doesn't cause any issues later. This should fix brightness controls on some laptops. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47861 Signed-off-by: Igor Murzov Reviewed-by: Sergey V Signed-off-by: Zhang Rui Signed-off-by: Abdallah Chatila --- drivers/acpi/video.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 48b5a3cda379..62d9ee6d077a 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1345,12 +1345,15 @@ static int acpi_video_bus_get_devices(struct acpi_video_bus *video, struct acpi_device *device) { - int status; + int status = 0; struct acpi_device *dev; - status = acpi_video_device_enumerate(video); - if (status) - return status; + /* + * There are systems where video module known to work fine regardless + * of broken _DOD and ignoring returned value here doesn't cause + * any issues later. + */ + acpi_video_device_enumerate(video); list_for_each_entry(dev, &device->children, node) { -- GitLab From 51b8318a818623899f9eb24ce697d43301bbe349 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 16 Oct 2012 17:09:22 +0300 Subject: [PATCH 1149/1799] Revert "serial: omap: fix software flow control" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a4f743851f74fc3e0cc40c13082e65c24139f481 upstream. This reverts commit 957ee7270d632245b43f6feb0e70d9a5e9ea6cf6 (serial: omap: fix software flow control). As Russell has pointed out, that commit isn't fixing Software Flow Control at all, and it actually makes it even more broken. It was agreed to revert this commit and use Russell's latest UART patches instead. Signed-off-by: Felipe Balbi Cc: Russell King Acked-by: Tony Lindgren Cc: Andreas Bießmann Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-omap/include/plat/omap-serial.h | 4 ++-- drivers/tty/serial/omap-serial.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index c369c9d242a8..9ff444469f3d 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -42,10 +42,10 @@ #define OMAP_UART_WER_MOD_WKUP 0X7F /* Enable XON/XOFF flow control on output */ -#define OMAP_UART_SW_TX 0x8 +#define OMAP_UART_SW_TX 0x04 /* Enable XON/XOFF flow control on input */ -#define OMAP_UART_SW_RX 0x2 +#define OMAP_UART_SW_RX 0x04 #define OMAP_UART_SYSC_RESET 0X07 #define OMAP_UART_TCR_TRIG 0X0F diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 6189923eb193..d00b38eb268e 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -649,19 +649,19 @@ serial_omap_configure_xonxoff /* * IXON Flag: - * Flow control for OMAP.TX - * OMAP.RX should listen for XON/XOFF + * Enable XON/XOFF flow control on output. + * Transmit XON1, XOFF1 */ if (termios->c_iflag & IXON) - up->efr |= OMAP_UART_SW_RX; + up->efr |= OMAP_UART_SW_TX; /* * IXOFF Flag: - * Flow control for OMAP.RX - * OMAP.TX should send XON/XOFF + * Enable XON/XOFF flow control on input. + * Receiver compares XON1, XOFF1. */ if (termios->c_iflag & IXOFF) - up->efr |= OMAP_UART_SW_TX; + up->efr |= OMAP_UART_SW_RX; serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); -- GitLab From d0e85e04fb57a65a6096a0b18c97ba5892d676d9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 21 Jun 2012 12:49:23 -0700 Subject: [PATCH 1150/1799] libceph: drop declaration of ceph_con_get() commit 261030215d970c62f799e6e508e3c68fc7ec2aa9 upstream. For some reason the declaration of ceph_con_get() and ceph_con_put() did not get deleted in this commit: d59315ca libceph: drop ceph_con_get/put helpers and nref member Clean that up. Signed-off-by: Alex Elder Cc: Herton Ronaldo Krzesinski Signed-off-by: Greg Kroah-Hartman --- include/linux/ceph/messenger.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 98442411c585..189ae0637634 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -215,8 +215,6 @@ extern void ceph_msg_revoke(struct ceph_msg *msg); extern void ceph_msg_revoke_incoming(struct ceph_msg *msg); extern void ceph_con_keepalive(struct ceph_connection *con); -extern struct ceph_connection *ceph_con_get(struct ceph_connection *con); -extern void ceph_con_put(struct ceph_connection *con); extern struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags, bool can_fail); -- GitLab From 0f4475cfaaf80e34ea5496a93ce579fe8c6950d5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 26 Nov 2012 11:40:05 -0800 Subject: [PATCH 1151/1799] Linux 3.4.20 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e264929291ec..9c895596748c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 19 +SUBLEVEL = 20 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 32e11d55e7997fe45c452b71014ee934054a1245 Mon Sep 17 00:00:00 2001 From: Alexandre Pereira da Silva Date: Mon, 25 Jun 2012 17:47:49 -0300 Subject: [PATCH 1152/1799] UBIFS: fix compilation warning commit 782759b9f5f5223e0962af60c3457c912fab755f upstream. Fix the following compilation warning: fs/ubifs/dir.c: In function 'ubifs_rename': fs/ubifs/dir.c:972:15: warning: 'saved_nlink' may be used uninitialized in this function Use the 'uninitialized_var()' macro to get rid of this false-positive. Artem: massaged the patch a bit. Signed-off-by: Alexandre Pereira da Silva Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- fs/ubifs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index ec9f1870ab7f..8640a12f0650 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -977,7 +977,7 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, struct ubifs_budget_req ino_req = { .dirtied_ino = 1, .dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) }; struct timespec time; - unsigned int saved_nlink; + unsigned int uninitialized_var(saved_nlink); /* * Budget request settings: deletion direntry, new direntry, removing -- GitLab From 4f442c50be050521667a8974fcc80cc8b881b2a6 Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Fri, 27 Jul 2012 11:53:28 -0600 Subject: [PATCH 1153/1799] NVMe: Fix uninitialized iod compiler warning commit c7d36ab8fa04c213328119a9c0d66985fe204ee5 upstream. Signed-off-by: Keith Busch Signed-off-by: Matthew Wilcox Signed-off-by: Greg Kroah-Hartman --- drivers/block/nvme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 38a2d0631882..9782340b6692 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1153,7 +1153,7 @@ static int nvme_user_admin_cmd(struct nvme_ns *ns, struct nvme_admin_cmd cmd; struct nvme_command c; int status, length; - struct nvme_iod *iod; + struct nvme_iod *uninitialized_var(iod); if (!capable(CAP_SYS_ADMIN)) return -EACCES; -- GitLab From 2214cc8d585df2bbfc894d0a3acc5a629fa1a985 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 8 Jun 2012 11:33:33 +0200 Subject: [PATCH 1154/1799] Bluetooth: Fix using uninitialized option in RFCMode commit 8f321f853ea33330c7141977cd34804476e2e07e upstream. If remote device sends bogus RFC option with invalid length, undefined options values are used. Fix this by using defaults when remote misbehaves. This also fixes the following warning reported by gcc 4.7.0: net/bluetooth/l2cap_core.c: In function 'l2cap_config_rsp': net/bluetooth/l2cap_core.c:3302:13: warning: 'rfc.max_pdu_size' may be used uninitialized in this function [-Wmaybe-uninitialized] net/bluetooth/l2cap_core.c:3266:24: note: 'rfc.max_pdu_size' was declared here net/bluetooth/l2cap_core.c:3298:25: warning: 'rfc.monitor_timeout' may be used uninitialized in this function [-Wmaybe-uninitialized] net/bluetooth/l2cap_core.c:3266:24: note: 'rfc.monitor_timeout' was declared here net/bluetooth/l2cap_core.c:3297:25: warning: 'rfc.retrans_timeout' may be used uninitialized in this function [-Wmaybe-uninitialized] net/bluetooth/l2cap_core.c:3266:24: note: 'rfc.retrans_timeout' was declared here net/bluetooth/l2cap_core.c:3295:2: warning: 'rfc.mode' may be used uninitialized in this function [-Wmaybe-uninitialized] net/bluetooth/l2cap_core.c:3266:24: note: 'rfc.mode' was declared here Signed-off-by: Szymon Janc Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/l2cap_core.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 627c35445a13..fa07aed3983b 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -2585,12 +2585,14 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) while (len >= L2CAP_CONF_OPT_SIZE) { len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); - switch (type) { - case L2CAP_CONF_RFC: - if (olen == sizeof(rfc)) - memcpy(&rfc, (void *)val, olen); - goto done; - } + if (type != L2CAP_CONF_RFC) + continue; + + if (olen != sizeof(rfc)) + break; + + memcpy(&rfc, (void *)val, olen); + goto done; } /* Use sane default values in case a misbehaving remote device -- GitLab From d4cad86a445a5229b58bbb7beaa0753f09314855 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 18 Jun 2012 21:16:31 +0200 Subject: [PATCH 1155/1799] ALSA: snd-usb-caiaq: initialize card pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit da185443c12f5ef7416af50293833a5654854186 upstream. Fixes the following warning: CC [M] sound/usb/caiaq/device.o sound/usb/caiaq/device.c: In function ‘snd_probe’: sound/usb/caiaq/device.c:500:16: warning: ‘card’ may be used uninitialized in this function [-Wmaybe-uninitialized] Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/caiaq/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index 64aed432ae22..7da0d0aa72cb 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -485,7 +485,7 @@ static int __devinit snd_probe(struct usb_interface *intf, const struct usb_device_id *id) { int ret; - struct snd_card *card; + struct snd_card *card = NULL; struct usb_device *device = interface_to_usbdev(intf); ret = create_card(device, intf, &card); -- GitLab From 896c631494d7ed4e609ef7b7b312b8a19b21f394 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 29 May 2012 15:07:26 -0700 Subject: [PATCH 1156/1799] drivers/leds/leds-lp5521.c: fix lp5521_read() error handling commit 5bc9ad774c063f6b41965e7314f2c26aa5e465a0 upstream. Gcc 4.6.2 complains that: drivers/leds/leds-lp5521.c: In function `lp5521_load_program': drivers/leds/leds-lp5521.c:214:21: warning: `mode' may be used uninitialized in this function [-Wuninitialized] drivers/leds/leds-lp5521.c: In function `lp5521_probe': drivers/leds/leds-lp5521.c:788:5: warning: `buf' may be used uninitialized in this function [-Wuninitialized] drivers/leds/leds-lp5521.c:740:6: warning: `ret' may be used uninitialized in this function [-Wuninitialized] These are real problems if lp5521_read() returns an error. When that happens we should handle it, instead of ignoring it or doing a bitwise OR with all the other error codes and continuing. Signed-off-by: Dan Carpenter Cc: Milo Cc: Richard Purdie Cc: Bryan Wu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/leds/leds-lp5521.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 410a723b8691..23815624f35e 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -193,9 +193,14 @@ static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern) /* move current engine to direct mode and remember the state */ ret = lp5521_set_engine_mode(eng, LP5521_CMD_DIRECT); + if (ret) + return ret; + /* Mode change requires min 500 us delay. 1 - 2 ms with margin */ usleep_range(1000, 2000); - ret |= lp5521_read(client, LP5521_REG_OP_MODE, &mode); + ret = lp5521_read(client, LP5521_REG_OP_MODE, &mode); + if (ret) + return ret; /* For loading, all the engines to load mode */ lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT); @@ -211,8 +216,7 @@ static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern) LP5521_PROG_MEM_SIZE, pattern); - ret |= lp5521_write(client, LP5521_REG_OP_MODE, mode); - return ret; + return lp5521_write(client, LP5521_REG_OP_MODE, mode); } static int lp5521_set_led_current(struct lp5521_chip *chip, int led, u8 curr) @@ -785,7 +789,7 @@ static int __devinit lp5521_probe(struct i2c_client *client, * LP5521_REG_ENABLE register will not have any effect - strange! */ ret = lp5521_read(client, LP5521_REG_R_CURRENT, &buf); - if (buf != LP5521_REG_R_CURR_DEFAULT) { + if (ret || buf != LP5521_REG_R_CURR_DEFAULT) { dev_err(&client->dev, "error in resetting chip\n"); goto fail2; } -- GitLab From cbe6d9bd065c64cb9eac67d9a12001e095f875b9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 21 Jun 2012 23:36:35 -0700 Subject: [PATCH 1157/1799] mvsas: remove unused variable in mvs_task_exec() commit cca85013ef54f66eb4616e6f3860549a96c8338b upstream. We don't use "dev" any more after 07ec747a5f ("libsas: remove ata_port.lock management duties from lldds") and it causes a compile warning. Signed-off-by: Dan Carpenter Cc: Xiangliang Yu Signed-off-by: Dan Williams Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/mvsas/mv_sas.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index fd3b2839843b..3006ec9aa690 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -885,7 +885,6 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags, struct completion *completion, int is_tmf, struct mvs_tmf_task *tmf) { - struct domain_device *dev = task->dev; struct mvs_info *mvi = NULL; u32 rc = 0; u32 pass = 0; -- GitLab From 6df5eea2553e9b66c2ef1f68dfd4b8867e2ff740 Mon Sep 17 00:00:00 2001 From: Krzysztof Wilczynski Date: Wed, 2 May 2012 11:34:01 +0100 Subject: [PATCH 1158/1799] scsi: aha152x: Fix sparse warning and make printing pointer address more portable. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b631cf1f899f9d2e449884dbccc34940637c639f upstream. This is to change use of "0x%08x" in favour of "%p" as per ../Documentation/printk-formats.txt, which also takes care about the following warning during compilation time: drivers/scsi/aha152x.c: In function ‘get_command’: drivers/scsi/aha152x.c:2987: warning: cast from pointer to integer of different size Signed-off-by: Krzysztof Wilczynski Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/aha152x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 19a36945e6fd..dd4547bf6881 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -2984,8 +2984,8 @@ static int get_command(char *pos, Scsi_Cmnd * ptr) char *start = pos; int i; - SPRINTF("0x%08x: target=%d; lun=%d; cmnd=( ", - (unsigned int) ptr, ptr->device->id, ptr->device->lun); + SPRINTF("%p: target=%d; lun=%d; cmnd=( ", + ptr, ptr->device->id, ptr->device->lun); for (i = 0; i < COMMAND_SIZE(ptr->cmnd[0]); i++) SPRINTF("0x%02x ", ptr->cmnd[i]); -- GitLab From 3ec1dc266051fc58d977a269f9807b4f987a93ef Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 20 Jun 2012 11:47:26 -0500 Subject: [PATCH 1159/1799] rtlwifi: rtl8192se: Fix gcc 4.7.x warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f761b6947dde42890beea59b020e1be87491809e upstream. With gcc 4.7.x, the following warning is issued as the routine that sets the array has the possibility of not initializing the values: CC [M] drivers/net/wireless/rtlwifi/rtl8192se/phy.o drivers/net/wireless/rtlwifi/rtl8192se/phy.c: In function ‘rtl92s_phy_set_txpower’: drivers/net/wireless/rtlwifi/rtl8192se/phy.c:1268:23: warning: ‘ofdmpowerLevel[0]’ may be used uninitialized in this function [-Wuninitialized] Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/rtl8192se/phy.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c index 4a499928e4c6..a2a5c92a1807 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c @@ -1247,6 +1247,9 @@ static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel, /* Read HT 40 OFDM TX power */ ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index]; ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index]; + } else { + ofdmpowerLevel[0] = 0; + ofdmpowerLevel[1] = 0; } } -- GitLab From 9d4f96299744ee7b8e2c4ad30ee915f1671e9fba Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 3 Sep 2012 20:54:48 +0200 Subject: [PATCH 1160/1799] x86-32: Fix invalid stack address while in softirq commit 1022623842cb72ee4d0dbf02f6937f38c92c3f41 upstream. In 32 bit the stack address provided by kernel_stack_pointer() may point to an invalid range causing NULL pointer access or page faults while in NMI (see trace below). This happens if called in softirq context and if the stack is empty. The address at ®s->sp is then out of range. Fixing this by checking if regs and ®s->sp are in the same stack context. Otherwise return the previous stack pointer stored in struct thread_info. If that address is invalid too, return address of regs. BUG: unable to handle kernel NULL pointer dereference at 0000000a IP: [] print_context_stack+0x6e/0x8d *pde = 00000000 Oops: 0000 [#1] SMP Modules linked in: Pid: 4434, comm: perl Not tainted 3.6.0-rc3-oprofile-i386-standard-g4411a05 #4 Hewlett-Packard HP xw9400 Workstation/0A1Ch EIP: 0060:[] EFLAGS: 00010093 CPU: 0 EIP is at print_context_stack+0x6e/0x8d EAX: ffffe000 EBX: 0000000a ECX: f4435f94 EDX: 0000000a ESI: f4435f94 EDI: f4435f94 EBP: f5409ec0 ESP: f5409ea0 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 CR0: 8005003b CR2: 0000000a CR3: 34ac9000 CR4: 000007d0 DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 DR6: ffff0ff0 DR7: 00000400 Process perl (pid: 4434, ti=f5408000 task=f5637850 task.ti=f4434000) Stack: 000003e8 ffffe000 00001ffc f4e39b00 00000000 0000000a f4435f94 c155198c f5409ef0 c1003723 c155198c f5409f04 00000000 f5409edc 00000000 00000000 f5409ee8 f4435f94 f5409fc4 00000001 f5409f1c c12dce1c 00000000 c155198c Call Trace: [] dump_trace+0x7b/0xa1 [] x86_backtrace+0x40/0x88 [] ? oprofile_add_sample+0x56/0x84 [] oprofile_add_sample+0x75/0x84 [] op_amd_check_ctrs+0x46/0x260 [] profile_exceptions_notify+0x23/0x4c [] nmi_handle+0x31/0x4a [] ? ftrace_define_fields_irq_handler_entry+0x45/0x45 [] do_nmi+0xa0/0x2ff [] ? ftrace_define_fields_irq_handler_entry+0x45/0x45 [] nmi_stack_correct+0x28/0x2d [] ? ftrace_define_fields_irq_handler_entry+0x45/0x45 [] ? do_softirq+0x4b/0x7f [] irq_exit+0x35/0x5b [] smp_apic_timer_interrupt+0x6c/0x7a [] apic_timer_interrupt+0x2a/0x30 Code: 89 fe eb 08 31 c9 8b 45 0c ff 55 ec 83 c3 04 83 7d 10 00 74 0c 3b 5d 10 73 26 3b 5d e4 73 0c eb 1f 3b 5d f0 76 1a 3b 5d e8 73 15 <8b> 13 89 d0 89 55 e0 e8 ad 42 03 00 85 c0 8b 55 e0 75 a6 eb cc EIP: [] print_context_stack+0x6e/0x8d SS:ESP 0068:f5409ea0 CR2: 000000000000000a ---[ end trace 62afee3481b00012 ]--- Kernel panic - not syncing: Fatal exception in interrupt V2: * add comments to kernel_stack_pointer() * always return a valid stack address by falling back to the address of regs Reported-by: Yang Wei Signed-off-by: Robert Richter Link: http://lkml.kernel.org/r/20120912135059.GZ8285@erda.amd.com Signed-off-by: H. Peter Anvin Cc: Jun Zhang Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/ptrace.h | 15 ++++----------- arch/x86/kernel/ptrace.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index dcfde52979c3..19f16ebaf4fa 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -205,21 +205,14 @@ static inline bool user_64bit_mode(struct pt_regs *regs) } #endif -/* - * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode - * when it traps. The previous stack will be directly underneath the saved - * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'. - * - * This is valid only for kernel mode traps. - */ -static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) -{ #ifdef CONFIG_X86_32 - return (unsigned long)(®s->sp); +extern unsigned long kernel_stack_pointer(struct pt_regs *regs); #else +static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ return regs->sp; -#endif } +#endif #define GET_IP(regs) ((regs)->ip) #define GET_FP(regs) ((regs)->bp) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index cf1178332bc0..d3e115297fe2 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -165,6 +165,34 @@ static inline bool invalid_selector(u16 value) #define FLAG_MASK FLAG_MASK_32 +/* + * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode + * when it traps. The previous stack will be directly underneath the saved + * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'. + * + * Now, if the stack is empty, '®s->sp' is out of range. In this + * case we try to take the previous stack. To always return a non-null + * stack pointer we fall back to regs as stack if no previous stack + * exists. + * + * This is valid only for kernel mode traps. + */ +unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ + unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1); + unsigned long sp = (unsigned long)®s->sp; + struct thread_info *tinfo; + + if (context == (sp & ~(THREAD_SIZE - 1))) + return sp; + + tinfo = (struct thread_info *)context; + if (tinfo->previous_esp) + return tinfo->previous_esp; + + return (unsigned long)regs; +} + static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno) { BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0); -- GitLab From 8433fcce61cd330b1096e2e4d7601d5251d95b6c Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 20 Nov 2012 13:07:46 +0000 Subject: [PATCH 1161/1799] x86, efi: Fix processor-specific memcpy() build error commit 0f905a43ce955b638139bd84486194770a6a2c08 upstream. Building for Athlon/Duron/K7 results in the following build error, arch/x86/boot/compressed/eboot.o: In function `__constant_memcpy3d': eboot.c:(.text+0x385): undefined reference to `_mmx_memcpy' arch/x86/boot/compressed/eboot.o: In function `efi_main': eboot.c:(.text+0x1a22): undefined reference to `_mmx_memcpy' because the boot stub code doesn't link with the kernel proper, and therefore doesn't have access to the 3DNow version of memcpy. So, follow the example of misc.c and #undef memcpy so that we use the version provided by misc.c. See https://bugzilla.kernel.org/show_bug.cgi?id=50391 Reported-by: Al Viro Reported-by: Ryan Underwood Cc: H. Peter Anvin Signed-off-by: Matt Fleming Signed-off-by: Greg Kroah-Hartman --- arch/x86/boot/compressed/eboot.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 0cdfc0d2315e..8bb90707cb55 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -12,6 +12,8 @@ #include #include +#undef memcpy /* Use memcpy from misc.c */ + #include "eboot.h" static efi_system_table_t *sys_table; -- GitLab From 82c0abae22f37f93655b8adfa304e207f2ffbfa3 Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Thu, 15 Nov 2012 13:41:50 -0500 Subject: [PATCH 1162/1799] x86, microcode, AMD: Add support for family 16h processors commit 36c46ca4f322a7bf89aad5462a3a1f61713edce7 upstream. Add valid patch size for family 16h processors. [ hpa: promoting to urgent/stable since it is hw enabling and trivial ] Signed-off-by: Boris Ostrovsky Acked-by: Andreas Herrmann Link: http://lkml.kernel.org/r/1353004910-2204-1-git-send-email-boris.ostrovsky@amd.com Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/microcode_amd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 82746f942cd8..5d8cf0d6796c 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -97,6 +97,7 @@ static unsigned int verify_ucode_size(int cpu, u32 patch_size, #define F1XH_MPB_MAX_SIZE 2048 #define F14H_MPB_MAX_SIZE 1824 #define F15H_MPB_MAX_SIZE 4096 +#define F16H_MPB_MAX_SIZE 3458 switch (c->x86) { case 0x14: @@ -105,6 +106,9 @@ static unsigned int verify_ucode_size(int cpu, u32 patch_size, case 0x15: max_size = F15H_MPB_MAX_SIZE; break; + case 0x16: + max_size = F16H_MPB_MAX_SIZE; + break; default: max_size = F1XH_MPB_MAX_SIZE; break; -- GitLab From 383072079d8f54041bf183a2fa70144bebb82ed8 Mon Sep 17 00:00:00 2001 From: Albert Pool Date: Tue, 30 Oct 2012 20:58:06 +0100 Subject: [PATCH 1163/1799] rtlwifi: rtl8192cu: Add new USB ID commit a485e827f07bfdd0762059386e6e787bed6e81ee upstream. This is an ISY IWL 2000. Probably a clone of Belkin F7D1102 050d:1102. Its FCC ID is the same. Signed-off-by: Albert Pool Acked-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 5bd408566350..61e57689a058 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -297,6 +297,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { /*=== Customer ID ===*/ /****** 8188CU ********/ {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/ + {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/ {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/ {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ -- GitLab From 6966e1b95a3b866bf076176f7cd3f6898e00ee68 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Thu, 15 Nov 2012 15:58:48 -0800 Subject: [PATCH 1164/1799] mwifiex: report error to MMC core if we cannot suspend commit dd321acddc3be1371263b8c9e6c6f2af89f63d57 upstream. When host_sleep_config command fails we should return error to MMC core to indicate the failure for our device. The misspelled variable is also removed as it's redundant. Signed-off-by: Bing Zhao Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mwifiex/sdio.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index f8012e2b7f7c..7d00a87e9a14 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -158,7 +158,6 @@ static int mwifiex_sdio_suspend(struct device *dev) struct sdio_mmc_card *card; struct mwifiex_adapter *adapter; mmc_pm_flag_t pm_flag = 0; - int hs_actived = 0; int i; int ret = 0; @@ -185,12 +184,14 @@ static int mwifiex_sdio_suspend(struct device *dev) adapter = card->adapter; /* Enable the Host Sleep */ - hs_actived = mwifiex_enable_hs(adapter); - if (hs_actived) { - pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n"); - ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + if (!mwifiex_enable_hs(adapter)) { + dev_err(adapter->dev, "cmd: failed to suspend\n"); + return -EFAULT; } + dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n"); + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + /* Indicate device suspended */ adapter->is_suspended = true; -- GitLab From 8d8c210794bb574b1d04492332a399e679caaa63 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Thu, 15 Nov 2012 15:58:47 -0800 Subject: [PATCH 1165/1799] mwifiex: fix system hang issue in cmd timeout error case commit b1a47aa5e1e159e2cb06d7dfcc17ef5149b09299 upstream. Reported by Tim Shepard: I was seeing sporadic failures (wedgeups), and the majority of those failures I saw printed the printouts in mwifiex_cmd_timeout_func with cmd = 0xe5 which is CMD_802_11_HS_CFG_ENH. When this happens, two minutes later I get notified that the rtcwake thread is blocked, like this: INFO: task rtcwake:3495 blocked for more than 120 seconds. To get the hung thread unblocked we wake up the cmd wait queue and cancel the ioctl. Reported-by: Tim Shepard Signed-off-by: Bing Zhao Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mwifiex/cmdevt.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 07f6e0092552..2977a12410c0 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -816,9 +816,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context) return; } cmd_node = adapter->curr_cmd; - if (cmd_node->wait_q_enabled) - adapter->cmd_wait_q.status = -ETIMEDOUT; - if (cmd_node) { adapter->dbg.timeout_cmd_id = adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; @@ -864,6 +861,14 @@ mwifiex_cmd_timeout_func(unsigned long function_context) dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n", adapter->ps_mode, adapter->ps_state); + + if (cmd_node->wait_q_enabled) { + adapter->cmd_wait_q.status = -ETIMEDOUT; + wake_up_interruptible(&adapter->cmd_wait_q.wait); + mwifiex_cancel_pending_ioctl(adapter); + /* reset cmd_sent flag to unblock new commands */ + adapter->cmd_sent = false; + } } if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) mwifiex_init_fw_complete(adapter); -- GitLab From 6417635908e7643800141fc1d6cf7fe43f4fb5e3 Mon Sep 17 00:00:00 2001 From: Maciej Patelczyk Date: Mon, 15 Oct 2012 14:29:03 +0200 Subject: [PATCH 1166/1799] SCSI: isci: copy fis 0x34 response into proper buffer commit 49bd665c5407a453736d3232ee58f2906b42e83c upstream. SATA MICROCODE DOWNALOAD fails on isci driver. After receiving Register Device to Host (FIS 0x34) frame Initiator resets phy. In the frame handler routine response (FIS 0x34) was copied into wrong buffer and upper layer did not receive any answer which resulted in timeout and reset. This patch corrects this bug. Signed-off-by: Maciej Patelczyk Signed-off-by: Lukasz Dorau Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/isci/request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 2def1e3960f6..05c3fc0ce27f 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -1970,7 +1970,7 @@ sci_io_request_frame_handler(struct isci_request *ireq, frame_index, (void **)&frame_buffer); - sci_controller_copy_sata_response(&ireq->stp.req, + sci_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); -- GitLab From 9cbecb443503ba3dd6a620e8e43a0273e14dc204 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 21 Nov 2012 18:37:38 -0500 Subject: [PATCH 1167/1799] drm/radeon: add new SI pci id commit 0181bd5dea2ed0696f84591a92da0b6a1f1a2e62 upstream. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- include/drm/drm_pciids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index efc66f2d096c..7207a99bdf86 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -214,6 +214,7 @@ {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ -- GitLab From 75c23fc13e0f252cc4f3e52d45116b8642c6c61a Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 31 Oct 2012 16:35:30 +0100 Subject: [PATCH 1168/1799] ALSA: ua101, usx2y: fix broken MIDI output commit e99ddfde6ae0dd2662bb40435696002b590e4057 upstream. Commit 88a8516a2128 (ALSA: usbaudio: implement USB autosuspend) added autosuspend code to all files making up the snd-usb-audio driver. However, midi.c is part of snd-usb-lib and is also used by other drivers, not all of which support autosuspend. Thus, calls to usb_autopm_get_interface() could fail, and this unexpected error would result in the MIDI output being completely unusable. Make it work by ignoring the error that is expected with drivers that do not support autosuspend. Reported-by: Colin Fletcher Reported-by: Devin Venable Reported-by: Dr Nick Bailey Reported-by: Jannis Achstetter Reported-by: Rui Nuno Capela Cc: Oliver Neukum Signed-off-by: Clemens Ladisch Signed-off-by: Greg Kroah-Hartman --- sound/usb/midi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/usb/midi.c b/sound/usb/midi.c index c83f6143c0eb..eeefbce3873c 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -148,6 +148,7 @@ struct snd_usb_midi_out_endpoint { struct snd_usb_midi_out_endpoint* ep; struct snd_rawmidi_substream *substream; int active; + bool autopm_reference; uint8_t cable; /* cable number << 4 */ uint8_t state; #define STATE_UNKNOWN 0 @@ -1076,7 +1077,8 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) return -ENXIO; } err = usb_autopm_get_interface(umidi->iface); - if (err < 0) + port->autopm_reference = err >= 0; + if (err < 0 && err != -EACCES) return -EIO; substream->runtime->private_data = port; port->state = STATE_UNKNOWN; @@ -1087,9 +1089,11 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) { struct snd_usb_midi* umidi = substream->rmidi->private_data; + struct usbmidi_out_port *port = substream->runtime->private_data; substream_open(substream, 0); - usb_autopm_put_interface(umidi->iface); + if (port->autopm_reference) + usb_autopm_put_interface(umidi->iface); return 0; } -- GitLab From de134053d4084ef640a44f9fd848cb607d2d0457 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 21 Nov 2012 10:03:10 +0100 Subject: [PATCH 1169/1799] ALSA: hda - Cirrus: Correctly clear line_out_pins when moving to speaker commit 34c3d1926bdaf45d3a891dd577482abcdd9faa34 upstream. If this array is not cleared, the jack related code later might fail to create "Internal Speaker Phantom Jack" on Dell Inspiron 3420 and Dell Vostro 2420. BugLink: https://bugs.launchpad.net/bugs/1076840 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- 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 057f95a2bbb0..3605fbb6ef15 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -460,6 +460,7 @@ static int parse_output(struct hda_codec *codec) memcpy(cfg->speaker_pins, cfg->line_out_pins, sizeof(cfg->speaker_pins)); cfg->line_outs = 0; + memset(cfg->line_out_pins, 0, sizeof(cfg->line_out_pins)); } return 0; -- GitLab From 7c06237754a52bb98462ee787f9b001854d884df Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 2 Nov 2012 12:30:53 +0000 Subject: [PATCH 1170/1799] PARISC: fix virtual aliasing issue in get_shared_area() commit 949a05d03490e39e773e8652ccab9157e6f595b4 upstream. On Thu, 2012-11-01 at 16:45 -0700, Michel Lespinasse wrote: > Looking at the arch/parisc/kernel/sys_parisc.c implementation of > get_shared_area(), I do have a concern though. The function basically > ignores the pgoff argument, so that if one creates a shared mapping of > pages 0-N of a file, and then a separate shared mapping of pages 1-N > of that same file, both will have the same cache offset for their > starting address. > > This looks like this would create obvious aliasing issues. Am I > misreading this ? I can't understand how this could work good enough > to be undetected, so there must be something I'm missing here ??? This turns out to be correct and we need to pay attention to the pgoff as well as the address when creating the virtual address for the area. Fortunately, the bug is rarely triggered as most applications which use pgoff tend to use large values (git being the primary one, and it uses pgoff in multiples of 16MB) which are larger than our cache coherency modulus, so the problem isn't often seen in practise. Reported-by: Michel Lespinasse Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/sys_parisc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index c9b932260f47..7ea75d14aa65 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -73,6 +73,8 @@ static unsigned long get_shared_area(struct address_space *mapping, struct vm_area_struct *vma; int offset = mapping ? get_offset(mapping) : 0; + offset = (offset + (pgoff << PAGE_SHIFT)) & 0x3FF000; + addr = DCACHE_ALIGN(addr - offset) + offset; for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { -- GitLab From e939e24a7d18f47001ca2e16c4028807120337b3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 21 Nov 2012 19:27:23 +0000 Subject: [PATCH 1171/1799] PARISC: fix user-triggerable panic on parisc commit 441a179dafc0f99fc8b3a8268eef66958621082e upstream. int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset, unsigned int sigsetsize) { sigset_t old_set, new_set; int ret; if (set && get_sigset32(set, &new_set, sigsetsize)) ... static int get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) { compat_sigset_t s; int r; if (sz != sizeof *set) panic("put_sigset32()"); In other words, rt_sigprocmask(69, (void *)69, 69) done by 32bit process will promptly panic the box. Signed-off-by: Al Viro Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/signal32.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index e14132430762..d0ea054bd3d2 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c @@ -67,7 +67,8 @@ put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) { compat_sigset_t s; - if (sz != sizeof *set) panic("put_sigset32()"); + if (sz != sizeof *set) + return -EINVAL; sigset_64to32(&s, set); return copy_to_user(up, &s, sizeof s); @@ -79,7 +80,8 @@ get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) compat_sigset_t s; int r; - if (sz != sizeof *set) panic("put_sigset32()"); + if (sz != sizeof *set) + return -EINVAL; if ((r = copy_from_user(&s, up, sz)) == 0) { sigset_32to64(set, &s); -- GitLab From 02bbebe27638111d18f63fa7438231def916bd15 Mon Sep 17 00:00:00 2001 From: Jiri Engelthaler Date: Thu, 20 Sep 2012 16:49:50 +0200 Subject: [PATCH 1172/1799] mtd: slram: invalid checking of absolute end address commit c36a7ff4578ab6294885aef5ef241aeec4cdb1f0 upstream. Fixed parsing end absolute address. Signed-off-by: Jiri Engelthaler Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/devices/slram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index 8f52fc858e48..5a5cd2ace4a6 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) if (*(szlength) != '+') { devlength = simple_strtoul(szlength, &buffer, 0); - devlength = handle_unit(devlength, buffer) - devstart; + devlength = handle_unit(devlength, buffer); if (devlength < devstart) goto err_out; -- GitLab From 11371ec0a92756cbaa84b86fbbaa3aeae7457658 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 25 Sep 2012 15:27:13 +0530 Subject: [PATCH 1173/1799] mtd: ofpart: Fix incorrect NULL check in parse_ofoldpart_partitions() commit 5a6ea4af0907f995dc06df21a9c9ef764c7cd3bc upstream. The pointer returned by kzalloc should be tested for NULL to avoid potential NULL pointer dereference later. Incorrect pointer was being tested for NULL. Bug introduced by commit fbcf62a3 (mtd: physmap_of: move parse_obsolete_partitions to become separate parser). This patch fixes this bug. Signed-off-by: Sachin Kamat Cc: Dmitry Eremin-Solenikov Cc: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/ofpart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 64be8f0848b0..d9127e2ed808 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -121,7 +121,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, nr_parts = plen / sizeof(part[0]); *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL); - if (!pparts) + if (!*pparts) return -ENOMEM; names = of_get_property(dp, "partition-names", &plen); -- GitLab From 262a70e8fbf870359ced2059becf116a249bb2d5 Mon Sep 17 00:00:00 2001 From: Thomas Betker Date: Wed, 17 Oct 2012 22:59:30 +0200 Subject: [PATCH 1174/1799] jffs2: Fix lock acquisition order bug in jffs2_write_begin commit 5ffd3412ae5536a4c57469cb8ea31887121dcb2e upstream. jffs2_write_begin() first acquires the page lock, then f->sem. This causes an AB-BA deadlock with jffs2_garbage_collect_live(), which first acquires f->sem, then the page lock: jffs2_garbage_collect_live mutex_lock(&f->sem) (A) jffs2_garbage_collect_dnode jffs2_gc_fetch_page read_cache_page_async do_read_cache_page lock_page(page) (B) jffs2_write_begin grab_cache_page_write_begin find_lock_page lock_page(page) (B) mutex_lock(&f->sem) (A) We fix this by restructuring jffs2_write_begin() to take f->sem before the page lock. However, we make sure that f->sem is not held when calling jffs2_reserve_space(), as this is not permitted by the locking rules. The deadlock above was observed multiple times on an SoC with a dual ARMv7 (Cortex-A9), running the long-term 3.4.11 kernel; it occurred when using scp to copy files from a host system to the ARM target system. The fix was heavily tested on the same target system. Signed-off-by: Thomas Betker Acked-by: Joakim Tjernlund Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- fs/jffs2/file.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index db3889ba8818..8608f8779143 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, struct page *pg; struct inode *inode = mapping->host; struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + struct jffs2_raw_inode ri; + uint32_t alloc_len = 0; pgoff_t index = pos >> PAGE_CACHE_SHIFT; uint32_t pageofs = index << PAGE_CACHE_SHIFT; int ret = 0; + jffs2_dbg(1, "%s()\n", __func__); + + if (pageofs > inode->i_size) { + ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); + if (ret) + return ret; + } + + mutex_lock(&f->sem); pg = grab_cache_page_write_begin(mapping, index, flags); - if (!pg) + if (!pg) { + if (alloc_len) + jffs2_complete_reservation(c); + mutex_unlock(&f->sem); return -ENOMEM; + } *pagep = pg; - jffs2_dbg(1, "%s()\n", __func__); - - if (pageofs > inode->i_size) { + if (alloc_len) { /* Make new hole frag from old EOF to new page */ - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); - struct jffs2_raw_inode ri; struct jffs2_full_dnode *fn; - uint32_t alloc_len; jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", (unsigned int)inode->i_size, pageofs); - ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, - ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); - if (ret) - goto out_page; - - mutex_lock(&f->sem); memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -191,7 +197,6 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, if (IS_ERR(fn)) { ret = PTR_ERR(fn); jffs2_complete_reservation(c); - mutex_unlock(&f->sem); goto out_page; } ret = jffs2_add_full_dnode_to_inode(c, f, fn); @@ -206,12 +211,10 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, jffs2_mark_node_obsolete(c, fn->raw); jffs2_free_full_dnode(fn); jffs2_complete_reservation(c); - mutex_unlock(&f->sem); goto out_page; } jffs2_complete_reservation(c); inode->i_size = pageofs; - mutex_unlock(&f->sem); } /* @@ -220,18 +223,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, * case of a short-copy. */ if (!PageUptodate(pg)) { - mutex_lock(&f->sem); ret = jffs2_do_readpage_nolock(inode, pg); - mutex_unlock(&f->sem); if (ret) goto out_page; } + mutex_unlock(&f->sem); jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags); return ret; out_page: unlock_page(pg); page_cache_release(pg); + mutex_unlock(&f->sem); return ret; } -- GitLab From 45bc5c6913e04f1346bfe3401d2f52ad2164b3b2 Mon Sep 17 00:00:00 2001 From: majianpeng Date: Tue, 6 Nov 2012 17:13:44 +0800 Subject: [PATCH 1175/1799] md: Reassigned the parameters if read_seqretry returned true in func md_is_badblock. commit ab05613a0646dcc11049692d54bae76ca9ffa910 upstream. This bug was introduced by commit(v3.0-rc7-126-g2230dfe). So fix is suitable for 3.0.y thru 3.6.y. Signed-off-by: Jianpeng Ma Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 529ce89b30bc..2b399da4bbae 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7694,9 +7694,9 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors, sector_t *first_bad, int *bad_sectors) { int hi; - int lo = 0; + int lo; u64 *p = bb->page; - int rv = 0; + int rv; sector_t target = s + sectors; unsigned seq; @@ -7711,7 +7711,8 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors, retry: seq = read_seqbegin(&bb->lock); - + lo = 0; + rv = 0; hi = bb->count; /* Binary search between lo and hi for 'target' -- GitLab From 8c98fbaa55508732bb5a9f46b3c6cf60daa8e526 Mon Sep 17 00:00:00 2001 From: majianpeng Date: Thu, 8 Nov 2012 08:56:27 +0800 Subject: [PATCH 1176/1799] md: Avoid write invalid address if read_seqretry returned true. commit 35f9ac2dcec8f79d7059ce174fd7b7ee3290d620 upstream. If read_seqretry returned true and bbp was changed, it will write invalid address which can cause some serious problem. This bug was introduced by commit v3.0-rc7-130-g2699b67. So fix is suitable for 3.0.y thru 3.6.y. Reported-by: zhuwenfeng@kedacom.com Tested-by: zhuwenfeng@kedacom.com Signed-off-by: Jianpeng Ma Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- 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 2b399da4bbae..0a447a1be2ca 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1805,10 +1805,10 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev) memset(bbp, 0xff, PAGE_SIZE); for (i = 0 ; i < bb->count ; i++) { - u64 internal_bb = *p++; + u64 internal_bb = p[i]; u64 store_bb = ((BB_OFFSET(internal_bb) << 10) | BB_LEN(internal_bb)); - *bbp++ = cpu_to_le64(store_bb); + bbp[i] = cpu_to_le64(store_bb); } bb->changed = 0; if (read_seqretry(&bb->lock, seq)) -- GitLab From ecf049ce86e1d93bc9a3376facf31d7244338089 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 22 Nov 2012 15:12:09 +1100 Subject: [PATCH 1177/1799] md/raid10: decrement correct pending counter when writing to replacement. commit 884162df2aadd7414bef4935e1a54976fd4e3988 upstream. When a write to a replacement device completes, we carefully and correctly found the rdev that the write actually went to and the blithely called rdev_dec_pending on the primary rdev, even if this write was to the replacement. This means that any writes to an array while a replacement was ongoing would cause the nr_pending count for the primary device to go negative, so it could never be removed. This bug has been present since replacement was introduced in 3.3, so it is suitable for any -stable kernel since then. Reported-by: "George Spelvin" Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 4a038cdc0b54..a2b5304b4eb8 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -476,7 +476,7 @@ static void raid10_end_write_request(struct bio *bio, int error) */ one_write_done(r10_bio); if (dec_rdev) - rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev); + rdev_dec_pending(rdev, conf->mddev); } /* -- GitLab From f42513b9fd98a0f3afa8fe9bc23700b4226e1f6f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 6 Nov 2012 12:24:26 +0100 Subject: [PATCH 1178/1799] dm: fix deadlock with request based dm and queue request_fn recursion commit a8c32a5c98943d370ea606a2e7dc04717eb92206 upstream. Request based dm attempts to re-run the request queue off the request completion path. If used with a driver that potentially does end_io from its request_fn, we could deadlock trying to recurse back into request dispatch. Fix this by punting the request queue run to kblockd. Tested to fix a quickly reproducible deadlock in such a scenario. Acked-by: Alasdair G Kergon Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 9ff3019790d7..32370ea32e22 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -754,8 +754,14 @@ static void rq_completed(struct mapped_device *md, int rw, int run_queue) if (!md_in_flight(md)) wake_up(&md->wait); + /* + * Run this off this callpath, as drivers could invoke end_io while + * inside their request_fn (and holding the queue lock). Calling + * back into ->request_fn() could deadlock attempting to grab the + * queue lock again. + */ if (run_queue) - blk_run_queue(md->queue); + blk_run_queue_async(md->queue); /* * dm_put() must be at the end of this function. See the comment above -- GitLab From fceca5e72e787dd0a8ea29e22a874e363389356c Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Mon, 26 Nov 2012 16:29:56 -0800 Subject: [PATCH 1179/1799] futex: avoid wake_futex() for a PI futex_q commit aa10990e028cac3d5e255711fb9fb47e00700e35 upstream. Dave Jones reported a bug with futex_lock_pi() that his trinity test exposed. Sometime between queue_me() and taking the q.lock_ptr, the lock_ptr became NULL, resulting in a crash. While futex_wake() is careful to not call wake_futex() on futex_q's with a pi_state or an rt_waiter (which are either waiting for a futex_unlock_pi() or a PI futex_requeue()), futex_wake_op() and futex_requeue() do not perform the same test. Update futex_wake_op() and futex_requeue() to test for q.pi_state and q.rt_waiter and abort with -EINVAL if detected. To ensure any future breakage is caught, add a WARN() to wake_futex() if the same condition is true. This fix has seen 3 hours of testing with "trinity -c futex" on an x86_64 VM with 4 CPUS. [akpm@linux-foundation.org: tidy up the WARN()] Signed-off-by: Darren Hart Reported-by: Dave Jones Cc: Thomas Gleixner Cc: Peter Zijlstra Cc: Ingo Molnar Cc: John Kacur Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/kernel/futex.c b/kernel/futex.c index 20ef219bbe9b..19eb089ca003 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -843,6 +843,9 @@ static void wake_futex(struct futex_q *q) { struct task_struct *p = q->task; + if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n")) + return; + /* * We set q->lock_ptr = NULL _before_ we wake up the task. If * a non-futex wake up happens on another CPU then the task @@ -1078,6 +1081,10 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2, plist_for_each_entry_safe(this, next, head, list) { if (match_futex (&this->key, &key1)) { + if (this->pi_state || this->rt_waiter) { + ret = -EINVAL; + goto out_unlock; + } wake_futex(this); if (++ret >= nr_wake) break; @@ -1090,6 +1097,10 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2, op_ret = 0; plist_for_each_entry_safe(this, next, head, list) { if (match_futex (&this->key, &key2)) { + if (this->pi_state || this->rt_waiter) { + ret = -EINVAL; + goto out_unlock; + } wake_futex(this); if (++op_ret >= nr_wake2) break; @@ -1098,6 +1109,7 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2, ret += op_ret; } +out_unlock: double_unlock_hb(hb1, hb2); out_put_keys: put_futex_key(&key2); @@ -1387,9 +1399,13 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags, /* * FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always * be paired with each other and no other futex ops. + * + * We should never be requeueing a futex_q with a pi_state, + * which is awaiting a futex_unlock_pi(). */ if ((requeue_pi && !this->rt_waiter) || - (!requeue_pi && this->rt_waiter)) { + (!requeue_pi && this->rt_waiter) || + this->pi_state) { ret = -EINVAL; break; } -- GitLab From e41cd8f166f6b9a0767dce3cbce65d1f4941b8ba Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Tue, 13 Nov 2012 18:43:03 +0100 Subject: [PATCH 1180/1799] mac80211: deinitialize ibss-internals after emptiness check commit b78a4932f5fb11fadf41e69c606a33fa6787574c upstream. The check whether the IBSS is active and can be removed should be performed before deinitializing the fields used for the check/search. Otherwise, the configured BSS will not be found and removed properly. To make it more clear for the future, rename sdata->u.ibss to the local pointer ifibss which is used within the checks. This behaviour was introduced by f3209bea110cade12e2b133da8b8499689cb0e2e ("mac80211: fix IBSS teardown race") Signed-off-by: Simon Wunderlich Cc: Ignacy Gawedzki Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ibss.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 4a3666b678ea..7c51bae7f1ca 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -1153,10 +1153,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) mutex_lock(&sdata->u.ibss.mtx); - sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; - memset(sdata->u.ibss.bssid, 0, ETH_ALEN); - sdata->u.ibss.ssid_len = 0; - active_ibss = ieee80211_sta_active_ibss(sdata); if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { @@ -1177,6 +1173,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) } } + ifibss->state = IEEE80211_IBSS_MLME_SEARCH; + memset(ifibss->bssid, 0, ETH_ALEN); + ifibss->ssid_len = 0; + sta_info_flush(sdata->local, sdata); spin_lock_bh(&ifibss->incomplete_lock); -- GitLab From d6e782e1275740a5ca4c1a32cc9acfe1b6f82203 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Mon, 19 Nov 2012 21:17:31 +0100 Subject: [PATCH 1181/1799] radeon: add AGPMode 1 quirk for RV250 commit 45171002b01b2e2ec4f991eca81ffd8430fd0aec upstream. The Intel 82855PM host bridge / Mobility FireGL 9000 RV250 combination in an (outdated) ThinkPad T41 needs AGPMode 1 for suspend/resume (under KMS, that is). So add a quirk for it. (Change R250 to RV250 in comment for preceding quirk too.) Signed-off-by: Paul Bolle Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_agp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index bd2f33e5c91a..bc6b64fe0e09 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c @@ -70,9 +70,12 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = { /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/ { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59, PCI_VENDOR_ID_DELL, 0x00e3, 2}, - /* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */ + /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */ { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66, PCI_VENDOR_ID_DELL, 0x0149, 1}, + /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */ + { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66, + PCI_VENDOR_ID_IBM, 0x0531, 1}, /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */ { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, 0x1025, 0x0061, 1}, -- GitLab From 5e937c8ffe7d6ba56a699684a4bc5f6b3edd05a5 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Wed, 21 Nov 2012 22:43:59 +0100 Subject: [PATCH 1182/1799] can: peak_usb: fix hwtstamp assignment commit c9faaa09e2a1335678f09c70a0d0eda095564bab upstream. The skb->tstamp is set to the hardware timestamp when available in the USB urb message. This leads to user visible timestamps which contain the 'uptime' of the USB adapter - and not the usual system generated timestamp. Fix this wrong assignment by applying the available hardware timestamp to the skb_shared_hwtstamps data structure - which is intended for this purpose. Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/usb/peak_usb/pcan_usb.c | 8 ++++++-- drivers/net/can/usb/peak_usb/pcan_usb_pro.c | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 86f26a1ede4c..25723d8ee201 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -519,8 +519,10 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, mc->pdev->dev.can.state = new_state; if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) { + struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb); + peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv); - skb->tstamp = timeval_to_ktime(tv); + hwts->hwtstamp = timeval_to_ktime(tv); } netif_rx(skb); @@ -605,6 +607,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) struct sk_buff *skb; struct can_frame *cf; struct timeval tv; + struct skb_shared_hwtstamps *hwts; skb = alloc_can_skb(mc->netdev, &cf); if (!skb) @@ -652,7 +655,8 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) /* convert timestamp into kernel time */ peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv); - skb->tstamp = timeval_to_ktime(tv); + hwts = skb_hwtstamps(skb); + hwts->hwtstamp = timeval_to_ktime(tv); /* push the skb */ netif_rx(skb); diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index 629c4ba5d49d..c95913a09737 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -532,6 +532,7 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if, struct can_frame *can_frame; struct sk_buff *skb; struct timeval tv; + struct skb_shared_hwtstamps *hwts; skb = alloc_can_skb(netdev, &can_frame); if (!skb) @@ -549,7 +550,8 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if, memcpy(can_frame->data, rx->data, can_frame->can_dlc); peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(rx->ts32), &tv); - skb->tstamp = timeval_to_ktime(tv); + hwts = skb_hwtstamps(skb); + hwts->hwtstamp = timeval_to_ktime(tv); netif_rx(skb); netdev->stats.rx_packets++; @@ -570,6 +572,7 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if, u8 err_mask = 0; struct sk_buff *skb; struct timeval tv; + struct skb_shared_hwtstamps *hwts; /* nothing should be sent while in BUS_OFF state */ if (dev->can.state == CAN_STATE_BUS_OFF) @@ -664,7 +667,8 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if, dev->can.state = new_state; peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(er->ts32), &tv); - skb->tstamp = timeval_to_ktime(tv); + hwts = skb_hwtstamps(skb); + hwts->hwtstamp = timeval_to_ktime(tv); netif_rx(skb); netdev->stats.rx_packets++; netdev->stats.rx_bytes += can_frame->can_dlc; -- GitLab From c9fa3f41a91e5c279968e5c9962b578aca003c98 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Mon, 26 Nov 2012 22:24:23 +0100 Subject: [PATCH 1183/1799] can: bcm: initialize ifindex for timeouts without previous frame reception commit 81b401100c01d2357031e874689f89bd788d13cd upstream. Set in the rx_ifindex to pass the correct interface index in the case of a message timeout detection. Usually the rx_ifindex value is set at receive time. But when no CAN frame has been received the RX_TIMEOUT notification did not contain a valid value. Reported-by: Andre Naujoks Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- net/can/bcm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/can/bcm.c b/net/can/bcm.c index 151b7730c12c..3910c1fefd04 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1084,6 +1084,9 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, op->sk = sk; op->ifindex = ifindex; + /* ifindex for timeout events w/o previous frame reception */ + op->rx_ifindex = ifindex; + /* initialize uninitialized (kzalloc) structure */ hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); op->timer.function = bcm_rx_timeout_handler; -- GitLab From acaf0ed4bdd03d31d0df0bf33816bdaceecbe7cc Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 23 Nov 2012 14:03:04 +0100 Subject: [PATCH 1184/1799] jbd: Fix lock ordering bug in journal_unmap_buffer() commit 25389bb207987b5774182f763b9fb65ff08761c8 upstream. Commit 09e05d48 introduced a wait for transaction commit into journal_unmap_buffer() in the case we are truncating a buffer undergoing commit in the page stradding i_size on a filesystem with blocksize < pagesize. Sadly we forgot to drop buffer lock before waiting for transaction commit and thus deadlock is possible when kjournald wants to lock the buffer. Fix the problem by dropping the buffer lock before waiting for transaction commit. Since we are still holding page lock (and that is OK), buffer cannot disappear under us. Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/jbd/transaction.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 841cabc94df8..ee959a9fed62 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1963,7 +1963,9 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh, spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); spin_unlock(&journal->j_state_lock); + unlock_buffer(bh); log_wait_commit(journal, tid); + lock_buffer(bh); goto retry; } /* -- GitLab From 98165e2b0d355759c16bae8d9ae09b445149cfbd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 18 Nov 2012 22:27:03 -0500 Subject: [PATCH 1185/1799] sparc64: not any error from do_sigaltstack() should fail rt_sigreturn() commit fae2ae2a900a5c7bb385fe4075f343e7e2d5daa2 upstream. If a signal handler is executed on altstack and another signal comes, we will end up with rt_sigreturn() on return from the second handler getting -EPERM from do_sigaltstack(). It's perfectly OK, since we are not asking to change the settings; in fact, they couldn't have been changed during the second handler execution exactly because we'd been on altstack all along. 64bit sigreturn on sparc treats any error from do_sigaltstack() as "SIGSEGV now"; we need to switch to the same semantics we are using on other architectures. Signed-off-by: Al Viro Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/signal_64.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 48b0f57b65f7..40837f071432 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -309,9 +309,7 @@ void do_rt_sigreturn(struct pt_regs *regs) err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); - err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf); - - if (err) + if (err || do_sigaltstack(&sf->stack, NULL, (unsigned long)sf) == -EFAULT) goto segv; err |= __get_user(rwin_save, &sf->rwin_save); -- GitLab From c4e9e580078376f7fd53fcf3a27f3a1259ebe463 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 23 Nov 2012 20:55:06 +0100 Subject: [PATCH 1186/1799] PM / QoS: fix wrong error-checking condition commit a7227a0faa117d0bc532aea546ae5ac5f89e8ed7 upstream. dev_pm_qos_add_request() can return 0, 1, or a negative error code, therefore the correct error test is "if (error < 0)." Checking just for non-zero return code leads to erroneous setting of the req->dev pointer to NULL, which then leads to a repeated call to dev_pm_qos_add_ancestor_request() in st1232_ts_irq_handler(). This in turn leads to an Oops, when the I2C host adapter is unloaded and reloaded again because of the inconsistent state of its QoS request list. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/qos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 71855570922d..c365c93abe1f 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -446,7 +446,7 @@ int dev_pm_qos_add_ancestor_request(struct device *dev, if (ancestor) error = dev_pm_qos_add_request(ancestor, req, value); - if (error) + if (error < 0) req->dev = NULL; return error; -- GitLab From e5f56030f487d3dbcc28be40cdecb8e43888dfa0 Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Sat, 6 Oct 2012 17:02:30 +0200 Subject: [PATCH 1187/1799] ALSA: hda - Add new codec ALC283 ALC290 support commit 7ff34ad80b7080fafaac8efa9ef0061708eddd51 upstream. These are compatible with standard ALC269 parser. Signed-off-by: Kailang Yang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 257fe87c4c0f..e6e44205bb25 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7035,6 +7035,8 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 }, { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, + { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 }, + { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", .patch = patch_alc861 }, { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, -- GitLab From 510add68ecdbc4ec3731248acf575753945f43ac Mon Sep 17 00:00:00 2001 From: Duncan Roe Date: Wed, 10 Oct 2012 14:19:50 +0200 Subject: [PATCH 1188/1799] ALSA: hda - Fix missing beep on ASUS X43U notebook commit 7110005e8d5c3cd418fc4b64f9f124f004422a9a upstream. Signed-off-by: Duncan Roe 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 e6e44205bb25..d297fa737707 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4322,6 +4322,7 @@ static void alc_auto_init_std(struct hda_codec *codec) ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) static const struct snd_pci_quirk beep_white_list[] = { + SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1), SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1), -- GitLab From 06096cf239242e915ee13c48c10306828c828527 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 21 Nov 2012 08:57:58 +0100 Subject: [PATCH 1189/1799] ALSA: hda - Add support for Realtek ALC292 commit af02dde8a609d8d071c4b31a82df811a55690a4a upstream. We found a new codec ID 292, and that just a simple quirk would enable sound output/input on this ALC292 chip. BugLink: https://bugs.launchpad.net/bugs/1081466 Tested-by: Acelan Kao 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 d297fa737707..29774e22bdad 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7038,6 +7038,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 }, { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 }, + { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", .patch = patch_alc861 }, { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, -- GitLab From 6495a1b5bc6f9e55eff414975609fef9e4a73662 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Wed, 24 Oct 2012 08:44:32 +0000 Subject: [PATCH 1190/1799] bas_gigaset: fix pre_reset handling commit c6fdd8e5d0c65bb8821dc6da26ee1a2ddd58b3cc upstream. The delayed work function int_in_work() may call usb_reset_device() and thus, indirectly, the driver's pre_reset method. Trying to cancel the work synchronously in that situation would deadlock. Fix by avoiding cancel_work_sync() in the pre_reset method. If the reset was NOT initiated by int_in_work() this might cause int_in_work() to run after the post_reset method, with urb_int_in already resubmitted, so handle that case gracefully. Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/gigaset/bas-gigaset.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index afa080258bfa..5e1bf61e80e0 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -616,7 +616,13 @@ static void int_in_work(struct work_struct *work) if (rc == 0) /* success, resubmit interrupt read URB */ rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc != 0 && rc != -ENODEV) { + + switch (rc) { + case 0: /* success */ + case -ENODEV: /* device gone */ + case -EINVAL: /* URB already resubmitted, or terminal badness */ + break; + default: /* failure: try to recover by resetting the device */ dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc)); rc = usb_lock_device_for_reset(ucs->udev, ucs->interface); if (rc == 0) { @@ -2437,7 +2443,9 @@ static void gigaset_disconnect(struct usb_interface *interface) } /* gigaset_suspend - * This function is called before the USB connection is suspended. + * This function is called before the USB connection is suspended + * or before the USB device is reset. + * In the latter case, message == PMSG_ON. */ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) { @@ -2493,7 +2501,12 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) del_timer_sync(&ucs->timer_atrdy); del_timer_sync(&ucs->timer_cmd_in); del_timer_sync(&ucs->timer_int_in); - cancel_work_sync(&ucs->int_in_wq); + + /* don't try to cancel int_in_wq from within reset as it + * might be the one requesting the reset + */ + if (message.event != PM_EVENT_ON) + cancel_work_sync(&ucs->int_in_wq); gig_dbg(DEBUG_SUSPEND, "suspend complete"); return 0; -- GitLab From 5042a551a4805f73c82b5fba0a3c4cc2e372665c Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 15 Jun 2012 12:52:46 +0200 Subject: [PATCH 1191/1799] scsi: Silence unnecessary warnings about ioctl to partition commit 6d9359280753d2955f86d6411047516a9431eb51 upstream. Sometimes, warnings about ioctls to partition happen often enough that they form majority of the warnings in the kernel log and users complain. In some cases warnings are about ioctls such as SG_IO so it's not good to get rid of the warnings completely as they can ease debugging of userspace problems when ioctl is refused. Since I have seen warnings from lots of commands, including some proprietary userspace applications, I don't think disallowing the ioctls for processes with CAP_SYS_RAWIO will happen in the near future if ever. So lets just stop warning for processes with CAP_SYS_RAWIO for which ioctl is allowed. Acked-by: Paolo Bonzini CC: Paolo Bonzini CC: James Bottomley Signed-off-by: Jan Kara Signed-off-by: Jens Axboe Cc: satoru takeuchi Signed-off-by: Greg Kroah-Hartman --- block/scsi_ioctl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 260fa80ef575..9a87daa6f4fb 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -721,11 +721,14 @@ int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd) break; } + if (capable(CAP_SYS_RAWIO)) + return 0; + /* In particular, rule out all resets and host-specific ioctls. */ printk_ratelimited(KERN_WARNING "%s: sending ioctl %x to a partition!\n", current->comm, cmd); - return capable(CAP_SYS_RAWIO) ? 0 : -ENOIOCTLCMD; + return -ENOIOCTLCMD; } EXPORT_SYMBOL(scsi_verify_blk_ioctl); -- GitLab From 865c6f7f4ddc972735cb6bc34a70370df537c650 Mon Sep 17 00:00:00 2001 From: Petr Matousek Date: Tue, 6 Nov 2012 19:24:07 +0100 Subject: [PATCH 1192/1799] KVM: x86: invalid opcode oops on SET_SREGS with OSXSAVE bit set (CVE-2012-4461) commit 6d1068b3a98519247d8ba4ec85cd40ac136dbdf9 upstream. On hosts without the XSAVE support unprivileged local user can trigger oops similar to the one below by setting X86_CR4_OSXSAVE bit in guest cr4 register using KVM_SET_SREGS ioctl and later issuing KVM_RUN ioctl. invalid opcode: 0000 [#2] SMP Modules linked in: tun ip6table_filter ip6_tables ebtable_nat ebtables ... Pid: 24935, comm: zoog_kvm_monito Tainted: G D 3.2.0-3-686-pae EIP: 0060:[] EFLAGS: 00210246 CPU: 0 EIP is at kvm_arch_vcpu_ioctl_run+0x92a/0xd13 [kvm] EAX: 00000001 EBX: 000f387e ECX: 00000000 EDX: 00000000 ESI: 00000000 EDI: 00000000 EBP: ef5a0060 ESP: d7c63e70 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 Process zoog_kvm_monito (pid: 24935, ti=d7c62000 task=ed84a0c0 task.ti=d7c62000) Stack: 00000001 f70a1200 f8b940a9 ef5a0060 00000000 00200202 f8769009 00000000 ef5a0060 000f387e eda5c020 8722f9c8 00015bae 00000000 ed84a0c0 ed84a0c0 c12bf02d 0000ae80 ef7f8740 fffffffb f359b740 ef5a0060 f8b85dc1 0000ae80 Call Trace: [] ? kvm_arch_vcpu_ioctl_set_sregs+0x2fe/0x308 [kvm] ... [] ? syscall_call+0x7/0xb Code: 89 e8 e8 14 ee ff ff ba 00 00 04 00 89 e8 e8 98 48 ff ff 85 c0 74 1e 83 7d 48 00 75 18 8b 85 08 07 00 00 31 c9 8b 95 0c 07 00 00 <0f> 01 d1 c7 45 48 01 00 00 00 c7 45 1c 01 00 00 00 0f ae f0 89 EIP: [] kvm_arch_vcpu_ioctl_run+0x92a/0xd13 [kvm] SS:ESP 0068:d7c63e70 QEMU first retrieves the supported features via KVM_GET_SUPPORTED_CPUID and then sets them later. So guest's X86_FEATURE_XSAVE should be masked out on hosts without X86_FEATURE_XSAVE, making kvm_set_cr4 with X86_CR4_OSXSAVE fail. Userspaces that allow specifying guest cpuid with X86_FEATURE_XSAVE even on hosts that do not support it, might be susceptible to this attack from inside the guest as well. Allow setting X86_CR4_OSXSAVE bit only if host has XSAVE support. Signed-off-by: Petr Matousek Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/cpuid.h | 3 +++ arch/x86/kvm/x86.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index 26d1fb437eb5..638de3efd7a3 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -23,6 +23,9 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu) { struct kvm_cpuid_entry2 *best; + if (!static_cpu_has(X86_FEATURE_XSAVE)) + return 0; + best = kvm_find_cpuid_entry(vcpu, 1, 0); return best && (best->ecx & bit(X86_FEATURE_XSAVE)); } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 185a2b823a2d..e28fb97a1a88 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5697,6 +5697,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, int pending_vec, max_bits, idx; struct desc_ptr dt; + if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE)) + return -EINVAL; + dt.size = sregs->idt.limit; dt.address = sregs->idt.base; kvm_x86_ops->set_idt(vcpu, &dt); -- GitLab From 65c03b4c0598a71e125a96985f5a402347f7ffb3 Mon Sep 17 00:00:00 2001 From: "joshua.a.hay@intel.com" Date: Fri, 21 Sep 2012 00:08:21 +0000 Subject: [PATCH 1193/1799] ixgbe: add support for X540-AT1 commit df376f0de167754da9b3ece4afdb5bb8bf3fbf3e upstream. This patch adds device support for Ethernet Controller X540-AT1. Signed-off-by: Josh Hay Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher Signed-off-by: Abdallah Chatila Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 1 + 4 files changed, 5 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 49aa41fe7b84..ab4d4d219e37 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -3216,6 +3216,7 @@ static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) switch (hw->device_id) { case IXGBE_DEV_ID_X540T: + case IXGBE_DEV_ID_X540T1: return 0; case IXGBE_DEV_ID_82599_T3_LOM: return 0; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index cfe7d269590c..6757d6c30fe7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2006,6 +2006,7 @@ static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter, retval = 0; break; case IXGBE_DEV_ID_X540T: + case IXGBE_DEV_ID_X540T1: /* check eeprom to see if enabled wol */ if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) || ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) && diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index a66c2159b1f6..6d1f6c512626 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -114,6 +114,7 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS), board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599EN_SFP), board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF_QP), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T1), board_X540 }, /* required last entry */ {0, } }; @@ -7060,6 +7061,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, adapter->wol = IXGBE_WUFC_MAG; break; case IXGBE_DEV_ID_X540T: + case IXGBE_DEV_ID_X540T1: /* Check eeprom to see if it is enabled */ hw->eeprom.ops.read(hw, 0x2c, &adapter->eeprom_cap); wol_cap = adapter->eeprom_cap & IXGBE_DEVICE_CAPS_WOL_MASK; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 8636e8344fc9..37eb39c013a0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -67,6 +67,7 @@ #define IXGBE_DEV_ID_82599_LS 0x154F #define IXGBE_DEV_ID_X540T 0x1528 #define IXGBE_DEV_ID_82599_SFP_SF_QP 0x154A +#define IXGBE_DEV_ID_X540T1 0x1560 /* VF Device IDs */ #define IXGBE_DEV_ID_82599_VF 0x10ED -- GitLab From 08ecfb7dd2e41f8aa9bd57468e09fdc5bbbc2ec6 Mon Sep 17 00:00:00 2001 From: David Milburn Date: Mon, 29 Oct 2012 18:00:22 -0500 Subject: [PATCH 1194/1799] sata_svw: check DMA start bit before reset commit b03e66a6be91f8389fcd902ab6c1563db1c9c06b upstream. If kdump is triggered with pending IO, controller may not respond causing kdump to fail. http://marc.info/?l=linux-ide&m=133032255424658&w=2 During error recovery ata_do_dev_read_id never completes due hang in mmio_insw. ata_do_dev_read_id ata_sff_data_xfer ioread16_rep mmio_insw if DMA start bit is cleared before reset, PIO command is successful and kdump succeeds. Signed-off-by: David Milburn Signed-off-by: Jeff Garzik Cc: CAI Qian Signed-off-by: Greg Kroah-Hartman --- drivers/ata/sata_svw.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index c646118943ff..833607f5ae43 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link, return 0; } +static int k2_sata_softreset(struct ata_link *link, + unsigned int *class, unsigned long deadline) +{ + u8 dmactl; + void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + + dmactl = readb(mmio + ATA_DMA_CMD); + + /* Clear the start bit */ + if (dmactl & ATA_DMA_START) { + dmactl &= ~ATA_DMA_START; + writeb(dmactl, mmio + ATA_DMA_CMD); + } + + return ata_sff_softreset(link, class, deadline); +} + +static int k2_sata_hardreset(struct ata_link *link, + unsigned int *class, unsigned long deadline) +{ + u8 dmactl; + void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + + dmactl = readb(mmio + ATA_DMA_CMD); + + /* Clear the start bit */ + if (dmactl & ATA_DMA_START) { + dmactl &= ~ATA_DMA_START; + writeb(dmactl, mmio + ATA_DMA_CMD); + } + + return sata_sff_hardreset(link, class, deadline); +} static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) { @@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = { static struct ata_port_operations k2_sata_ops = { .inherits = &ata_bmdma_port_ops, + .softreset = k2_sata_softreset, + .hardreset = k2_sata_hardreset, .sff_tf_load = k2_sata_tf_load, .sff_tf_read = k2_sata_tf_read, .sff_check_status = k2_stat_check_status, -- GitLab From 9cfb66219d6e5840df9c4cf06fff70e072be1409 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 28 Sep 2012 16:16:00 -0300 Subject: [PATCH 1195/1799] get_dvb_firmware: fix download site for tda10046 firmware commit 25ec43d3e6306978cf66060ed18c4160ce8fc302 upstream. The previous website doesn't exist anymore. Update it to one site that actually exists. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- Documentation/dvb/get_dvb_firmware | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index d1d4a179a382..b361e08570f7 100755 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -115,7 +115,7 @@ sub tda10045 { sub tda10046 { my $sourcefile = "TT_PCI_2.19h_28_11_2006.zip"; - my $url = "http://www.tt-download.com/download/updates/219/$sourcefile"; + my $url = "http://technotrend.com.ua/download/software/219/$sourcefile"; my $hash = "6a7e1e2f2644b162ff0502367553c72d"; my $outfile = "dvb-fe-tda10046.fw"; my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); -- GitLab From c09221cefdbd669883f94ff62f055d270df85feb Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 29 Oct 2012 14:04:43 +0100 Subject: [PATCH 1196/1799] NFC: pn533: Fix use after free commit 770f750bc2b8312489c8e45306f551d08a319d3c upstream. cmd was freed in pn533_dep_link_up regardless of pn533_send_cmd_frame_async return code. Cmd is passed as argument to pn533_in_dep_link_up_complete callback and should be freed there. Signed-off-by: Szymon Janc Signed-off-by: Samuel Ortiz Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/nfc/pn533.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index cb6204f78300..eeb0d59e17fd 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1385,12 +1385,8 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx, rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, dev->in_maxlen, pn533_in_dep_link_up_complete, cmd, GFP_KERNEL); - if (rc) - goto out; - - -out: - kfree(cmd); + if (rc < 0) + kfree(cmd); return rc; } -- GitLab From b127f3f930bbeedc3b10b150a4f43a6abeb75836 Mon Sep 17 00:00:00 2001 From: Waldemar Rymarkiewicz Date: Thu, 11 Oct 2012 14:04:00 +0200 Subject: [PATCH 1197/1799] NFC: pn533: Fix mem leak in pn533_in_dep_link_up commit 70418e6efcf4f8652cc08e3f2ab8ae35f0948fd9 upstream. cmd is allocated in pn533_dep_link_up and passed as an arg to pn533_send_cmd_frame_async together with a complete cb. arg is passed to the cb and must be kfreed there. Signed-off-by: Waldemar Rymarkiewicz Signed-off-by: Samuel Ortiz Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/nfc/pn533.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index eeb0d59e17fd..692bd1e8d6b1 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1278,11 +1278,14 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, u32 target_idx) static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, u8 *params, int params_len) { - struct pn533_cmd_jump_dep *cmd; struct pn533_cmd_jump_dep_response *resp; struct nfc_target nfc_target; u8 target_gt_len; int rc; + struct pn533_cmd_jump_dep *cmd = (struct pn533_cmd_jump_dep *)arg; + u8 active = cmd->active; + + kfree(arg); if (params_len == -ENOENT) { nfc_dev_dbg(&dev->interface->dev, ""); @@ -1304,7 +1307,6 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, } resp = (struct pn533_cmd_jump_dep_response *) params; - cmd = (struct pn533_cmd_jump_dep *) arg; rc = resp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { nfc_dev_err(&dev->interface->dev, @@ -1334,7 +1336,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (rc == 0) rc = nfc_dep_link_is_up(dev->nfc_dev, dev->nfc_dev->targets[0].idx, - !cmd->active, NFC_RF_INITIATOR); + !active, NFC_RF_INITIATOR); return 0; } -- GitLab From 47abf714aab1e2f5c293f54a3bd3f0ef7534c38e Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Fri, 12 Oct 2012 15:25:43 +0200 Subject: [PATCH 1198/1799] NFC: Fix nfc_llcp_local chained list insertion commit 16a78e9fed5e8baa8480ae3413f4328c4537c599 upstream. list_add was called with swapped parameters Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- net/nfc/llcp/llcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 17a578f641f1..c40112c39e15 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c @@ -966,7 +966,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) local->remote_lto = LLCP_DEFAULT_LTO; local->remote_rw = LLCP_DEFAULT_RW; - list_add(&llcp_devices, &local->list); + list_add(&local->list, &llcp_devices); return 0; -- GitLab From 368c8c73d4648843bece41f7c083f11fa4d1aa36 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Oct 2012 10:29:14 +0200 Subject: [PATCH 1199/1799] USB: mct_u232: fix broken close commit 5260e458f5eff269a43e4f1e9c47186c57b88ddb upstream. Make sure generic close is called at close. The driver relies on the generic write implementation but did not call generic close. Note that the call to kill the read urb is not redundant, as mct_u232 uses an interrupt urb from the second port as the read urb and that generic close therefore fails to kill it. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings --- drivers/usb/serial/mct_u232.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index ef4d7adfbd9d..d0bf56dba07e 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -533,12 +533,14 @@ static void mct_u232_close(struct usb_serial_port *port) { dbg("%s port %d", __func__, port->number); - 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); - } + /* + * Must kill the read urb as it is actually an interrupt urb, which + * generic close thus fails to kill. + */ + usb_kill_urb(port->read_urb); + usb_kill_urb(port->interrupt_in_urb); + + usb_serial_generic_close(port); } /* mct_u232_close */ -- GitLab From 53b360c604575070c83d2da83636af4e5c5de35a Mon Sep 17 00:00:00 2001 From: Chuansheng Liu Date: Mon, 26 Nov 2012 16:29:54 -0800 Subject: [PATCH 1200/1799] watchdog: using u64 in get_sample_period() commit 8ffeb9b0e6369135bf03a073514f571ef10606b9 upstream. In get_sample_period(), unsigned long is not enough: watchdog_thresh * 2 * (NSEC_PER_SEC / 5) case1: watchdog_thresh is 10 by default, the sample value will be: 0xEE6B2800 case2: set watchdog_thresh is 20, the sample value will be: 0x1 DCD6 5000 In case2, we need use u64 to express the sample period. Otherwise, changing the threshold thru proc often can not be successful. Signed-off-by: liu chuansheng Acked-by: Don Zickus Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- kernel/watchdog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/watchdog.c b/kernel/watchdog.c index df30ee08bdd4..991aa9381a44 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -112,7 +112,7 @@ static unsigned long get_timestamp(int this_cpu) return cpu_clock(this_cpu) >> 30LL; /* 2^30 ~= 10^9 */ } -static unsigned long get_sample_period(void) +static u64 get_sample_period(void) { /* * convert watchdog_thresh from seconds to ns @@ -121,7 +121,7 @@ static unsigned long get_sample_period(void) * and hard thresholds) to increment before the * hardlockup detector generates a warning */ - return get_softlockup_thresh() * (NSEC_PER_SEC / 5); + return get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5); } /* Commands for resetting the watchdog */ -- GitLab From 7da2f8907ba51acd7d13dd62e71f14972e9b5161 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Thu, 22 Nov 2012 11:58:22 +0100 Subject: [PATCH 1201/1799] MPI: Fix compilation on MIPS with GCC 4.4 and newer commit a3cea9894157c20a5b1ec08b7e0b5f2019740c10 upstream. Since 4.4 GCC on MIPS no longer recognizes the "h" constraint, leading to this build failure: CC lib/mpi/generic_mpih-mul1.o lib/mpi/generic_mpih-mul1.c: In function 'mpihelp_mul_1': lib/mpi/generic_mpih-mul1.c:50:3: error: impossible constraint in 'asm' This patch updates MPI with the latest umul_ppm implementations for MIPS. Signed-off-by: Manuel Lauss Cc: Linux-MIPS Cc: Dmitry Kasatkin Cc: James Morris Patchwork: https://patchwork.linux-mips.org/patch/4612/ Signed-off-by: Ralf Baechle Cc: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- lib/mpi/longlong.h | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h index 29f98624ef93..280405b47e71 100644 --- a/lib/mpi/longlong.h +++ b/lib/mpi/longlong.h @@ -703,7 +703,14 @@ do { \ ************** MIPS ***************** ***************************************/ #if defined(__mips__) && W_TYPE_SIZE == 32 -#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 +#define umul_ppmm(w1, w0, u, v) \ +do { \ + UDItype __ll = (UDItype)(u) * (v); \ + w1 = __ll >> 32; \ + w0 = __ll; \ +} while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 #define umul_ppmm(w1, w0, u, v) \ __asm__ ("multu %2,%3" \ : "=l" ((USItype)(w0)), \ @@ -728,7 +735,15 @@ do { \ ************** MIPS/64 ************** ***************************************/ #if (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64 -#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 +#define umul_ppmm(w1, w0, u, v) \ +do { \ + typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \ + __ll_UTItype __ll = (__ll_UTItype)(u) * (v); \ + w1 = __ll >> 64; \ + w0 = __ll; \ +} while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 #define umul_ppmm(w1, w0, u, v) \ __asm__ ("dmultu %2,%3" \ : "=l" ((UDItype)(w0)), \ -- GitLab From ee746ff6943cea07e9866e78307154f539440c57 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Mon, 17 Sep 2012 04:34:27 +0000 Subject: [PATCH 1202/1799] powerpc/eeh: Lock module while handling EEH event commit feadf7c0a1a7c08c74bebb4a13b755f8c40e3bbc upstream. The EEH core is talking with the PCI device driver to determine the action (purely reset, or PCI device removal). During the period, the driver might be unloaded and in turn causes kernel crash as follows: EEH: Detected PCI bus error on PHB#4-PE#10000 EEH: This PCI device has failed 3 times in the last hour lpfc 0004:01:00.0: 0:2710 PCI channel disable preparing for reset Unable to handle kernel paging request for data at address 0x00000490 Faulting instruction address: 0xd00000000e682c90 cpu 0x1: Vector: 300 (Data Access) at [c000000fc75ffa20] pc: d00000000e682c90: .lpfc_io_error_detected+0x30/0x240 [lpfc] lr: d00000000e682c8c: .lpfc_io_error_detected+0x2c/0x240 [lpfc] sp: c000000fc75ffca0 msr: 8000000000009032 dar: 490 dsisr: 40000000 current = 0xc000000fc79b88b0 paca = 0xc00000000edb0380 softe: 0 irq_happened: 0x00 pid = 3386, comm = eehd enter ? for help [c000000fc75ffca0] c000000fc75ffd30 (unreliable) [c000000fc75ffd30] c00000000004fd3c .eeh_report_error+0x7c/0xf0 [c000000fc75ffdc0] c00000000004ee00 .eeh_pe_dev_traverse+0xa0/0x180 [c000000fc75ffe70] c00000000004ffd8 .eeh_handle_event+0x68/0x300 [c000000fc75fff00] c0000000000503a0 .eeh_event_handler+0x130/0x1a0 [c000000fc75fff90] c000000000020138 .kernel_thread+0x54/0x70 1:mon> The patch increases the reference of the corresponding driver modules while EEH core does the negotiation with PCI device driver so that the corresponding driver modules can't be unloaded during the period and we're safe to refer the callbacks. Reported-by: Alexey Kardashevskiy Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt [ herton: backported for 3.5, adjusted driver assignments, return 0 instead of NULL, assume dev is not NULL ] Signed-off-by: Herton Ronaldo Krzesinski Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/pseries/eeh_driver.c | 95 ++++++++++++++++----- 1 file changed, 74 insertions(+), 21 deletions(-) diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index baf92cd9dfab..041e28d0e702 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,41 @@ static inline const char *eeh_pcid_name(struct pci_dev *pdev) return ""; } +/** + * eeh_pcid_get - Get the PCI device driver + * @pdev: PCI device + * + * The function is used to retrieve the PCI device driver for + * the indicated PCI device. Besides, we will increase the reference + * of the PCI device driver to prevent that being unloaded on + * the fly. Otherwise, kernel crash would be seen. + */ +static inline struct pci_driver *eeh_pcid_get(struct pci_dev *pdev) +{ + if (!pdev || !pdev->driver) + return NULL; + + if (!try_module_get(pdev->driver->driver.owner)) + return NULL; + + return pdev->driver; +} + +/** + * eeh_pcid_put - Dereference on the PCI device driver + * @pdev: PCI device + * + * The function is called to do dereference on the PCI device + * driver of the indicated PCI device. + */ +static inline void eeh_pcid_put(struct pci_dev *pdev) +{ + if (!pdev || !pdev->driver) + return; + + module_put(pdev->driver->driver.owner); +} + #if 0 static void print_device_node_tree(struct pci_dn *pdn, int dent) { @@ -126,18 +162,20 @@ static void eeh_enable_irq(struct pci_dev *dev) static int eeh_report_error(struct pci_dev *dev, void *userdata) { enum pci_ers_result rc, *res = userdata; - struct pci_driver *driver = dev->driver; + struct pci_driver *driver; dev->error_state = pci_channel_io_frozen; - if (!driver) - return 0; + driver = eeh_pcid_get(dev); + if (!driver) return 0; eeh_disable_irq(dev); if (!driver->err_handler || - !driver->err_handler->error_detected) + !driver->err_handler->error_detected) { + eeh_pcid_put(dev); return 0; + } rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen); @@ -145,6 +183,7 @@ static int eeh_report_error(struct pci_dev *dev, void *userdata) if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; if (*res == PCI_ERS_RESULT_NONE) *res = rc; + eeh_pcid_put(dev); return 0; } @@ -160,12 +199,16 @@ static int eeh_report_error(struct pci_dev *dev, void *userdata) static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) { enum pci_ers_result rc, *res = userdata; - struct pci_driver *driver = dev->driver; + struct pci_driver *driver; + + driver = eeh_pcid_get(dev); + if (!driver) return 0; - if (!driver || - !driver->err_handler || - !driver->err_handler->mmio_enabled) + if (!driver->err_handler || + !driver->err_handler->mmio_enabled) { + eeh_pcid_put(dev); return 0; + } rc = driver->err_handler->mmio_enabled(dev); @@ -173,6 +216,7 @@ static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; if (*res == PCI_ERS_RESULT_NONE) *res = rc; + eeh_pcid_put(dev); return 0; } @@ -189,18 +233,20 @@ static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) static int eeh_report_reset(struct pci_dev *dev, void *userdata) { enum pci_ers_result rc, *res = userdata; - struct pci_driver *driver = dev->driver; - - if (!driver) - return 0; + struct pci_driver *driver; dev->error_state = pci_channel_io_normal; + driver = eeh_pcid_get(dev); + if (!driver) return 0; + eeh_enable_irq(dev); if (!driver->err_handler || - !driver->err_handler->slot_reset) + !driver->err_handler->slot_reset) { + eeh_pcid_put(dev); return 0; + } rc = driver->err_handler->slot_reset(dev); if ((*res == PCI_ERS_RESULT_NONE) || @@ -208,6 +254,7 @@ static int eeh_report_reset(struct pci_dev *dev, void *userdata) if (*res == PCI_ERS_RESULT_DISCONNECT && rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; + eeh_pcid_put(dev); return 0; } @@ -222,21 +269,24 @@ static int eeh_report_reset(struct pci_dev *dev, void *userdata) */ static int eeh_report_resume(struct pci_dev *dev, void *userdata) { - struct pci_driver *driver = dev->driver; + struct pci_driver *driver; dev->error_state = pci_channel_io_normal; - if (!driver) - return 0; + driver = eeh_pcid_get(dev); + if (!driver) return 0; eeh_enable_irq(dev); if (!driver->err_handler || - !driver->err_handler->resume) + !driver->err_handler->resume) { + eeh_pcid_put(dev); return 0; + } driver->err_handler->resume(dev); + eeh_pcid_put(dev); return 0; } @@ -250,21 +300,24 @@ static int eeh_report_resume(struct pci_dev *dev, void *userdata) */ static int eeh_report_failure(struct pci_dev *dev, void *userdata) { - struct pci_driver *driver = dev->driver; + struct pci_driver *driver; dev->error_state = pci_channel_io_perm_failure; - if (!driver) - return 0; + driver = eeh_pcid_get(dev); + if (!driver) return 0; eeh_disable_irq(dev); if (!driver->err_handler || - !driver->err_handler->error_detected) + !driver->err_handler->error_detected) { + eeh_pcid_put(dev); return 0; + } driver->err_handler->error_detected(dev, pci_channel_io_perm_failure); + eeh_pcid_put(dev); return 0; } -- GitLab From fc6058e1a4cc1f76aab5c580322e109cf448ec9b Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Wed, 19 Sep 2012 14:43:33 +0800 Subject: [PATCH 1203/1799] mmc: sdhci-s3c: fix the wrong number of max bus clocks commit 5feb54a1ab91a237e247c013b8c4fb100ea347b1 upstream. We can use up to four bus-clocks; but on module remove, we didn't disable the fourth bus clock. Signed-off-by: Jaehoon Chung Signed-off-by: Kyungmin Park Signed-off-by: Chris Ball Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sdhci-s3c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 55a164fcaa15..9e2c5585efaa 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -656,7 +656,7 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); - for (ptr = 0; ptr < 3; ptr++) { + for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { if (sc->clk_bus[ptr]) { clk_disable(sc->clk_bus[ptr]); clk_put(sc->clk_bus[ptr]); -- GitLab From e84ad739d8a2143e5cd284a4c0462278587e4aa3 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 8 Oct 2012 14:01:12 -0700 Subject: [PATCH 1204/1799] ARM: OMAP: counter: add locking to read_persistent_clock commit 9d7d6e363b06934221b81a859d509844c97380df upstream. read_persistent_clock uses a global variable, use a spinlock to ensure non-atomic updates to the variable don't overlap and cause time to move backwards. Signed-off-by: Colin Cross Signed-off-by: R Sricharan Signed-off-by: Tony Lindgren [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-omap/counter_32k.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index 5068fe5a6910..fd433e7a25fd 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c @@ -50,22 +50,29 @@ static u32 notrace omap_32k_read_sched_clock(void) * nsecs and adds to a monotonically increasing timespec. */ static struct timespec persistent_ts; -static cycles_t cycles, last_cycles; +static cycles_t cycles; static unsigned int persistent_mult, persistent_shift; +static DEFINE_SPINLOCK(read_persistent_clock_lock); + void read_persistent_clock(struct timespec *ts) { unsigned long long nsecs; - cycles_t delta; - struct timespec *tsp = &persistent_ts; + cycles_t last_cycles; + unsigned long flags; + + spin_lock_irqsave(&read_persistent_clock_lock, flags); last_cycles = cycles; cycles = timer_32k_base ? __raw_readl(timer_32k_base) : 0; - delta = cycles - last_cycles; - nsecs = clocksource_cyc2ns(delta, persistent_mult, persistent_shift); + nsecs = clocksource_cyc2ns(cycles - last_cycles, + persistent_mult, persistent_shift); + + timespec_add_ns(&persistent_ts, nsecs); + + *ts = persistent_ts; - timespec_add_ns(tsp, nsecs); - *ts = *tsp; + spin_unlock_irqrestore(&read_persistent_clock_lock, flags); } int __init omap_init_clocksource_32k(void) -- GitLab From 1103ef8e70a1725b7fd9e0cb18a8b1edb6e5c42d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 9 Oct 2012 10:18:23 +0300 Subject: [PATCH 1205/1799] timekeeping: Cast raw_interval to u64 to avoid shift overflow commit 5b3900cd409466c0070b234d941650685ad0c791 upstream. We fixed a bunch of integer overflows in timekeeping code during the 3.6 cycle. I did an audit based on that and found this potential overflow. Signed-off-by: Dan Carpenter Acked-by: John Stultz Link: http://lkml.kernel.org/r/20121009071823.GA19159@elgon.mountain Signed-off-by: Thomas Gleixner Cc: Ben Hutchings [ herton: adapt for 3.5, timekeeper instead of tk pointer ] Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Greg Kroah-Hartman --- kernel/time/timekeeping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 12843e9f6d59..eff0b1e96331 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1014,7 +1014,7 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) } /* Accumulate raw time */ - raw_nsecs = timekeeper.raw_interval << shift; + raw_nsecs = (u64)timekeeper.raw_interval << shift; raw_nsecs += timekeeper.raw_time.tv_nsec; if (raw_nsecs >= NSEC_PER_SEC) { u64 raw_secs = raw_nsecs; -- GitLab From bffeb2a91830ad2ad841b3d1203d6c7724099d8d Mon Sep 17 00:00:00 2001 From: Stanislav Yakovlev Date: Mon, 15 Oct 2012 14:14:32 +0000 Subject: [PATCH 1206/1799] net/wireless: ipw2200: Fix panic occurring in ipw_handle_promiscuous_tx() commit bf11315eeda510ea4fc1a2bf972d8155d31d89b4 upstream. The driver does not count space of radiotap fields when allocating skb for radiotap packet. This leads to kernel panic with the following call trace: ... [67607.676067] [] error_code+0x67/0x6c [67607.676067] [] ? skb_put+0x91/0xa0 [67607.676067] [] ? ipw_handle_promiscuous_tx+0x16b/0x2d0 [ipw2200] [67607.676067] [] ipw_handle_promiscuous_tx+0x16b/0x2d0 [ipw2200] [67607.676067] [] ipw_net_hard_start_xmit+0x8b/0x90 [ipw2200] [67607.676067] [] libipw_xmit+0x55a/0x980 [libipw] [67607.676067] [] dev_hard_start_xmit+0x218/0x4d0 ... This bug was found by VittGam. https://bugzilla.kernel.org/show_bug.cgi?id=43255 Signed-off-by: Stanislav Yakovlev Signed-off-by: John W. Linville Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ipw2x00/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 3a6b991f0234..3dd80dfdcfdd 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -10471,7 +10471,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, } else len = src->len; - dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC); + dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC); if (!dst) continue; -- GitLab From 0c4528e770362d3497f59e9d15484ce24dd65ba9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 25 Sep 2012 16:40:12 +0200 Subject: [PATCH 1207/1799] iwlwifi: fix 6000 series channel switch command commit 8f7b8db6e0557c8437adf9371e020cd89a7e85dc upstream. The channel switch command for 6000 series devices is larger than the maximum inline command size of 320 bytes. The command is therefore refused with a warning. Fix this by allocating the command and using the NOCOPY mechanism. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-6000.c | 33 ++++++++++++++++--------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index c0cfa4e652c9..2067bdff83ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -170,7 +170,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, * See iwlagn_mac_channel_switch. */ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - struct iwl6000_channel_switch_cmd cmd; + struct iwl6000_channel_switch_cmd *cmd; const struct iwl_channel_info *ch_info; u32 switch_time_in_usec, ucode_switch_time; u16 ch; @@ -180,18 +180,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, - .len = { sizeof(cmd), }, + .len = { sizeof(*cmd), }, .flags = CMD_SYNC, - .data = { &cmd, }, + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, }; + int err; - cmd.band = priv->band == IEEE80211_BAND_2GHZ; + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + hcmd.data[0] = cmd; + + cmd->band = priv->band == IEEE80211_BAND_2GHZ; ch = ch_switch->channel->hw_value; IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", ctx->active.channel, ch); - cmd.channel = cpu_to_le16(ch); - cmd.rxon_flags = ctx->staging.flags; - cmd.rxon_filter_flags = ctx->staging.filter_flags; + cmd->channel = cpu_to_le16(ch); + cmd->rxon_flags = ctx->staging.flags; + cmd->rxon_filter_flags = ctx->staging.filter_flags; switch_count = ch_switch->count; tsf_low = ch_switch->timestamp & 0x0ffffffff; /* @@ -207,30 +214,32 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, switch_count = 0; } if (switch_count <= 1) - cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); + cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time); else { switch_time_in_usec = vif->bss_conf.beacon_int * switch_count * TIME_UNIT; ucode_switch_time = iwl_usecs_to_beacons(priv, switch_time_in_usec, beacon_interval); - cmd.switch_time = iwl_add_beacon_time(priv, + cmd->switch_time = iwl_add_beacon_time(priv, priv->ucode_beacon_time, ucode_switch_time, beacon_interval); } IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", - cmd.switch_time); + cmd->switch_time); ch_info = iwl_get_channel_info(priv, priv->band, ch); if (ch_info) - cmd.expect_beacon = is_channel_radar(ch_info); + cmd->expect_beacon = is_channel_radar(ch_info); else { IWL_ERR(priv, "invalid channel switch from %u to %u\n", ctx->active.channel, ch); return -EFAULT; } - return iwl_dvm_send_cmd(priv, &hcmd); + err = iwl_dvm_send_cmd(priv, &hcmd); + kfree(cmd); + return err; } static struct iwl_lib_ops iwl6000_lib = { -- GitLab From 3d514b82fc30a1425eba9e7b8f24620a4ec8a633 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 3 Dec 2012 12:18:42 -0800 Subject: [PATCH 1208/1799] Linux 3.4.21 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9c895596748c..7f9f6491c81f 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 20 +SUBLEVEL = 21 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 4d064b9c790a24c65e878fe0faba3490e8a7b342 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 20 Nov 2012 22:21:02 -0800 Subject: [PATCH 1209/1799] x86-32: Export kernel_stack_pointer() for modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit cb57a2b4cff7edf2a4e32c0163200e9434807e0a upstream. Modules, in particular oprofile (and possibly other similar tools) need kernel_stack_pointer(), so export it using EXPORT_SYMBOL_GPL(). Cc: Yang Wei Cc: Robert Richter Cc: Jun Zhang Link: http://lkml.kernel.org/r/20120912135059.GZ8285@erda.amd.com Signed-off-by: H. Peter Anvin Cc: Robert Richter Cc: Herton Ronaldo Krzesinski Cc: Philip Müller Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/ptrace.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index d3e115297fe2..c4410fb4938f 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -192,6 +193,7 @@ unsigned long kernel_stack_pointer(struct pt_regs *regs) return (unsigned long)regs; } +EXPORT_SYMBOL_GPL(kernel_stack_pointer); static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno) { -- GitLab From edc7a368636e2a48da92e059505c905737faf1c8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 5 Dec 2012 18:39:09 -0800 Subject: [PATCH 1210/1799] Linux 3.4.22 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7f9f6491c81f..320663d24096 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 21 +SUBLEVEL = 22 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 99e48f99066295c88c95058ecdfdd07145bef156 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Sun, 18 Nov 2012 16:29:44 +0000 Subject: [PATCH 1211/1799] Dove: Attempt to fix PMU/RTC interrupts commit 5d3df935426271016b895aecaa247101b4bfa35e upstream. Fix the acknowledgement of PMU interrupts on Dove: some Dove hardware has not been sensibly designed so that interrupts can be handled in a race free manner. The PMU is one such instance. The pending (aka 'cause') register is a bunch of RW bits, meaning that these bits can be both cleared and set by software (confirmed on the Armada-510 on the cubox.) Hardware sets the appropriate bit when an interrupt is asserted, and software is required to clear the bits which are to be processed. If we write ~(1 << bit), then we end up asserting every other interrupt except the one we're processing. So, we need to do a read-modify-write cycle to clear the asserted bit. However, any interrupts which occur in the middle of this cycle will also be written back as zero, which will also clear the new interrupts. The upshot of this is: there is _no_ way to safely clear down interrupts in this register (and other similarly behaving interrupt pending registers on this device.) The patch below at least stops us creating new interrupts. Signed-off-by: Russell King Signed-off-by: Jason Cooper Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-dove/irq.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-dove/irq.c b/arch/arm/mach-dove/irq.c index f07fd16e0c9b..9f2fd1001746 100644 --- a/arch/arm/mach-dove/irq.c +++ b/arch/arm/mach-dove/irq.c @@ -61,8 +61,20 @@ static void pmu_irq_ack(struct irq_data *d) int pin = irq_to_pmu(d->irq); u32 u; + /* + * The PMU mask register is not RW0C: it is RW. This means that + * the bits take whatever value is written to them; if you write + * a '1', you will set the interrupt. + * + * Unfortunately this means there is NO race free way to clear + * these interrupts. + * + * So, let's structure the code so that the window is as small as + * possible. + */ u = ~(1 << (pin & 31)); - writel(u, PMU_INTERRUPT_CAUSE); + u &= readl_relaxed(PMU_INTERRUPT_CAUSE); + writel_relaxed(u, PMU_INTERRUPT_CAUSE); } static struct irq_chip pmu_irq_chip = { -- GitLab From c004e0d6faac4da0488b72f0791a5f3de26c4e4e Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Sun, 18 Nov 2012 16:39:32 +0000 Subject: [PATCH 1212/1799] Dove: Fix irq_to_pmu() commit d356cf5a74afa32b40decca3c9dd88bc3cd63eb5 upstream. PMU interrupts start at IRQ_DOVE_PMU_START, not IRQ_DOVE_PMU_START + 1. Fix the condition. (It may have been less likely to occur had the code been written "if (irq >= IRQ_DOVE_PMU_START" which imho is the easier to understand notation, and matches the normal way of thinking about these things.) Signed-off-by: Russell King Signed-off-by: Jason Cooper Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-dove/include/mach/pm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-dove/include/mach/pm.h b/arch/arm/mach-dove/include/mach/pm.h index 3ad9f946a9e8..11799c33475e 100644 --- a/arch/arm/mach-dove/include/mach/pm.h +++ b/arch/arm/mach-dove/include/mach/pm.h @@ -45,7 +45,7 @@ static inline int pmu_to_irq(int pin) static inline int irq_to_pmu(int irq) { - if (IRQ_DOVE_PMU_START < irq && irq < NR_IRQS) + if (IRQ_DOVE_PMU_START <= irq && irq < NR_IRQS) return irq - IRQ_DOVE_PMU_START; return -EINVAL; -- GitLab From dfbc8b9eab0b50753a397de1abed62d4397e13ca Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 15 Aug 2012 17:13:53 -0400 Subject: [PATCH 1213/1799] drm/radeon/dce4+: don't use radeon_crtc for vblank callback commit 4a15903db02026728d0cf2755c6fabae16b8db6a upstream. This might be called before we've allocated the radeon_crtcs Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index e5328da70f84..9f5c943b8bf4 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -37,6 +37,16 @@ #define EVERGREEN_PFP_UCODE_SIZE 1120 #define EVERGREEN_PM4_UCODE_SIZE 1376 +static const u32 crtc_offsets[6] = +{ + EVERGREEN_CRTC0_REGISTER_OFFSET, + EVERGREEN_CRTC1_REGISTER_OFFSET, + EVERGREEN_CRTC2_REGISTER_OFFSET, + EVERGREEN_CRTC3_REGISTER_OFFSET, + EVERGREEN_CRTC4_REGISTER_OFFSET, + EVERGREEN_CRTC5_REGISTER_OFFSET +}; + static void evergreen_gpu_init(struct radeon_device *rdev); void evergreen_fini(struct radeon_device *rdev); void evergreen_pcie_gen2_enable(struct radeon_device *rdev); @@ -101,17 +111,19 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) { - struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; int i; - if (RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_MASTER_EN) { + if (crtc >= rdev->num_crtc) + return; + + if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN) { for (i = 0; i < rdev->usec_timeout; i++) { - if (!(RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK)) + if (!(RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)) break; udelay(1); } for (i = 0; i < rdev->usec_timeout; i++) { - if (RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK) + if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK) break; udelay(1); } -- GitLab From a0c246c82dc5d1a9ab857364522ec56627a858eb Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 15 Aug 2012 17:18:42 -0400 Subject: [PATCH 1214/1799] drm/radeon: properly handle mc_stop/mc_resume on evergreen+ (v2) commit 62444b7462a2b98bc78d68736c03a7c4e66ba7e2 upstream. - Stop the displays from accessing the FB - Block CPU access - Turn off MC client access This should fix issues some users have seen, especially with UEFI, when changing the MC FB location that result in hangs or display corruption. v2: fix crtc enabled check noticed by Luca Tettamanti Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen.c | 169 ++++++++++++------------- drivers/gpu/drm/radeon/evergreen_reg.h | 2 + drivers/gpu/drm/radeon/evergreend.h | 7 + drivers/gpu/drm/radeon/radeon_asic.h | 1 + 4 files changed, 88 insertions(+), 91 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 9f5c943b8bf4..497c265a93b4 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1129,116 +1129,103 @@ void evergreen_agp_enable(struct radeon_device *rdev) void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) { + u32 crtc_enabled, tmp, frame_count, blackout; + int i, j; + save->vga_render_control = RREG32(VGA_RENDER_CONTROL); save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); - /* Stop all video */ + /* disable VGA render */ WREG32(VGA_RENDER_CONTROL, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); - } - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); - } - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + /* blank the display controllers */ + for (i = 0; i < rdev->num_crtc; i++) { + crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN; + if (crtc_enabled) { + save->crtc_enabled[i] = true; + if (ASIC_IS_DCE6(rdev)) { + tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); + if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { + radeon_wait_for_vblank(rdev, i); + tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; + WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); + } + } else { + tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); + if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { + radeon_wait_for_vblank(rdev, i); + tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); + } + } + /* wait for the next frame */ + frame_count = radeon_get_vblank_counter(rdev, i); + for (j = 0; j < rdev->usec_timeout; j++) { + if (radeon_get_vblank_counter(rdev, i) != frame_count) + break; + udelay(1); + } + } } - WREG32(D1VGA_CONTROL, 0); - WREG32(D2VGA_CONTROL, 0); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_D3VGA_CONTROL, 0); - WREG32(EVERGREEN_D4VGA_CONTROL, 0); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_D5VGA_CONTROL, 0); - WREG32(EVERGREEN_D6VGA_CONTROL, 0); + radeon_mc_wait_for_idle(rdev); + + blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); + if ((blackout & BLACKOUT_MODE_MASK) != 1) { + /* Block CPU access */ + WREG32(BIF_FB_EN, 0); + /* blackout the MC */ + blackout &= ~BLACKOUT_MODE_MASK; + WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); } } void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) { - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); + u32 tmp, frame_count; + int i, j; - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, + /* update crtc base addresses */ + for (i = 0; i < rdev->num_crtc; i++) { + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], (u32)rdev->mc.vram_start); } - WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); - /* Unlock host access */ + + /* unblackout the MC */ + tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); + tmp &= ~BLACKOUT_MODE_MASK; + WREG32(MC_SHARED_BLACKOUT_CNTL, tmp); + /* allow CPU access */ + WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); + + for (i = 0; i < rdev->num_crtc; i++) { + if (save->crtc_enabled) { + if (ASIC_IS_DCE6(rdev)) { + tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); + tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; + WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); + } else { + tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); + tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); + } + /* wait for the next frame */ + frame_count = radeon_get_vblank_counter(rdev, i); + for (j = 0; j < rdev->usec_timeout; j++) { + if (radeon_get_vblank_counter(rdev, i) != frame_count) + break; + udelay(1); + } + } + } + /* Unlock vga access */ WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); mdelay(1); WREG32(VGA_RENDER_CONTROL, save->vga_render_control); diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h index 96c10b3991aa..34a0e856069f 100644 --- a/drivers/gpu/drm/radeon/evergreen_reg.h +++ b/drivers/gpu/drm/radeon/evergreen_reg.h @@ -218,6 +218,8 @@ #define EVERGREEN_CRTC_CONTROL 0x6e70 # define EVERGREEN_CRTC_MASTER_EN (1 << 0) # define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) +#define EVERGREEN_CRTC_BLANK_CONTROL 0x6e74 +# define EVERGREEN_CRTC_BLANK_DATA_EN (1 << 8) #define EVERGREEN_CRTC_STATUS 0x6e8c # define EVERGREEN_CRTC_V_BLANK (1 << 0) #define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 2eaaea061d6c..81e744fab31a 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,10 @@ #define CONFIG_MEMSIZE 0x5428 +#define BIF_FB_EN 0x5490 +#define FB_READ_EN (1 << 0) +#define FB_WRITE_EN (1 << 1) + #define CP_STRMOUT_CNTL 0x84FC #define CP_COHER_CNTL 0x85F0 @@ -200,6 +204,9 @@ #define NOOFCHAN_MASK 0x00003000 #define MC_SHARED_CHREMAP 0x2008 +#define MC_SHARED_BLACKOUT_CNTL 0x20ac +#define BLACKOUT_MODE_MASK 0x00000007 + #define MC_ARB_RAMCFG 0x2760 #define NOOFBANK_SHIFT 0 #define NOOFBANK_MASK 0x00000003 diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 665df8730c80..917e49cb490b 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -400,6 +400,7 @@ void r700_cp_fini(struct radeon_device *rdev); struct evergreen_mc_save { u32 vga_render_control; u32 vga_hdp_control; + bool crtc_enabled[RADEON_MAX_CRTCS]; }; void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); -- GitLab From 86d80959eb81b931a509fe9ea78b31f319882637 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 19 Nov 2012 09:11:27 -0500 Subject: [PATCH 1215/1799] drm/radeon: properly track the crtc not_enabled case evergreen_mc_stop() commit 804cc4a0ad3a896ca295f771a28c6eb36ced7903 upstream. The save struct is not initialized previously so explicitly mark the crtcs as not used when they are not in use. Signed-off-by: Alex Deucher 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 497c265a93b4..4a1d8f3457cc 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1164,6 +1164,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav break; udelay(1); } + } else { + save->crtc_enabled[i] = false; } } -- GitLab From 25a30e7cc1562e110c401f286f41c801d80b2b0a Mon Sep 17 00:00:00 2001 From: Jianguo Wu Date: Thu, 29 Nov 2012 13:54:21 -0800 Subject: [PATCH 1216/1799] mm/vmemmap: fix wrong use of virt_to_page commit ae64ffcac35de0db628ba9631edf8ff34c5cd7ac upstream. I enable CONFIG_DEBUG_VIRTUAL and CONFIG_SPARSEMEM_VMEMMAP, when doing memory hotremove, there is a kernel BUG at arch/x86/mm/physaddr.c:20. It is caused by free_section_usemap()->virt_to_page(), virt_to_page() is only used for kernel direct mapping address, but sparse-vmemmap uses vmemmap address, so it is going wrong here. ------------[ cut here ]------------ kernel BUG at arch/x86/mm/physaddr.c:20! invalid opcode: 0000 [#1] SMP Modules linked in: acpihp_drv acpihp_slot edd cpufreq_conservative cpufreq_userspace cpufreq_powersave acpi_cpufreq mperf fuse vfat fat loop dm_mod coretemp kvm crc32c_intel ipv6 ixgbe igb iTCO_wdt i7core_edac edac_core pcspkr iTCO_vendor_support ioatdma microcode joydev sr_mod i2c_i801 dca lpc_ich mfd_core mdio tpm_tis i2c_core hid_generic tpm cdrom sg tpm_bios rtc_cmos button ext3 jbd mbcache usbhid hid uhci_hcd ehci_hcd usbcore usb_common sd_mod crc_t10dif processor thermal_sys hwmon scsi_dh_alua scsi_dh_hp_sw scsi_dh_rdac scsi_dh_emc scsi_dh ata_generic ata_piix libata megaraid_sas scsi_mod CPU 39 Pid: 6454, comm: sh Not tainted 3.7.0-rc1-acpihp-final+ #45 QCI QSSC-S4R/QSSC-S4R RIP: 0010:[] [] __phys_addr+0x88/0x90 RSP: 0018:ffff8804440d7c08 EFLAGS: 00010006 RAX: 0000000000000006 RBX: ffffea0012000000 RCX: 000000000000002c ... Signed-off-by: Jianguo Wu Signed-off-by: Jiang Liu Reviewd-by: Wen Congyang Acked-by: Johannes Weiner Reviewed-by: Yasuaki Ishimatsu Reviewed-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/sparse.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/mm/sparse.c b/mm/sparse.c index a8bc7d364deb..290dba25a7ed 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -619,7 +619,7 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages) { return; /* XXX: Not implemented yet */ } -static void free_map_bootmem(struct page *page, unsigned long nr_pages) +static void free_map_bootmem(struct page *memmap, unsigned long nr_pages) { } #else @@ -660,10 +660,11 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages) get_order(sizeof(struct page) * nr_pages)); } -static void free_map_bootmem(struct page *page, unsigned long nr_pages) +static void free_map_bootmem(struct page *memmap, unsigned long nr_pages) { unsigned long maps_section_nr, removing_section_nr, i; unsigned long magic; + struct page *page = virt_to_page(memmap); for (i = 0; i < nr_pages; i++, page++) { magic = (unsigned long) page->lru.next; @@ -712,13 +713,10 @@ static void free_section_usemap(struct page *memmap, unsigned long *usemap) */ if (memmap) { - struct page *memmap_page; - memmap_page = virt_to_page(memmap); - nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page)) >> PAGE_SHIFT; - free_map_bootmem(memmap_page, nr_pages); + free_map_bootmem(memmap, nr_pages); } } -- GitLab From 0b4d372b78bef8ebbccca2e310973b550f1dc6f2 Mon Sep 17 00:00:00 2001 From: Naoya Horiguchi Date: Thu, 29 Nov 2012 13:54:34 -0800 Subject: [PATCH 1217/1799] mm: soft offline: split thp at the beginning of soft_offline_page() commit 783657a7dc20e5c0efbc9a09a9dd38e238a723da upstream. When we try to soft-offline a thp tail page, put_page() is called on the tail page unthinkingly and VM_BUG_ON is triggered in put_compound_page(). This patch splits thp before going into the main body of soft-offlining. Signed-off-by: Naoya Horiguchi Cc: Andi Kleen Cc: Tony Luck Cc: Andi Kleen Cc: Wu Fengguang Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memory-failure.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 274c3cc5fbc0..d86fb2057354 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1481,9 +1481,17 @@ int soft_offline_page(struct page *page, int flags) { int ret; unsigned long pfn = page_to_pfn(page); + struct page *hpage = compound_trans_head(page); if (PageHuge(page)) return soft_offline_huge_page(page, flags); + if (PageTransHuge(hpage)) { + if (PageAnon(hpage) && unlikely(split_huge_page(hpage))) { + pr_info("soft offline: %#lx: failed to split THP\n", + pfn); + return -EBUSY; + } + } ret = get_any_page(page, pfn, flags); if (ret < 0) -- GitLab From 659cca40ff27f7d73a0c49ac6c8d8b3838202524 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Wed, 21 Nov 2012 00:19:06 -0700 Subject: [PATCH 1218/1799] ARM: Kirkwood: Update PCI-E fixup commit 1dc831bf53fddcc6443f74a39e72db5bcea4f15d upstream. - The code relies on rc_pci_fixup being called, which only happens when CONFIG_PCI_QUIRKS is enabled, so add that to Kconfig. Omitting this causes a booting failure with a non-obvious cause. - Update rc_pci_fixup to set the class properly, copying the more modern style from other places - Correct the rc_pci_fixup comment Signed-off-by: Jason Gunthorpe Signed-off-by: Jason Cooper Signed-off-by: Greg Kroah-Hartman --- arch/arm/Kconfig | 1 + arch/arm/mach-kirkwood/pcie.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e14ae1141429..7fe19a38ba17 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -579,6 +579,7 @@ config ARCH_KIRKWOOD bool "Marvell Kirkwood" select CPU_FEROCEON select PCI + select PCI_QUIRKS select ARCH_REQUIRE_GPIOLIB select GENERIC_CLOCKEVENTS select NEED_MACH_IO_H diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c index f56a0118c1bb..c46d20e5f3fd 100644 --- a/arch/arm/mach-kirkwood/pcie.c +++ b/arch/arm/mach-kirkwood/pcie.c @@ -212,14 +212,19 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys) return 1; } +/* + * The root complex has a hardwired class of PCI_CLASS_MEMORY_OTHER, when it + * is operating as a root complex this needs to be switched to + * PCI_CLASS_BRIDGE_HOST or Linux will errantly try to process the BAR's on + * the device. Decoding setup is handled by the orion code. + */ static void __devinit rc_pci_fixup(struct pci_dev *dev) { - /* - * Prevent enumeration of root complex. - */ if (dev->bus->parent == NULL && dev->devfn == 0) { int i; + dev->class &= 0xff; + dev->class |= PCI_CLASS_BRIDGE_HOST << 8; for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { dev->resource[i].start = 0; dev->resource[i].end = 0; -- GitLab From 1b9dd61a10bed126661645cbf2623965fbbdefb3 Mon Sep 17 00:00:00 2001 From: Vincent Palatin Date: Fri, 30 Nov 2012 12:15:32 -0800 Subject: [PATCH 1219/1799] x86, fpu: Avoid FPU lazy restore after suspend commit 644c154186386bb1fa6446bc5e037b9ed098db46 upstream. When a cpu enters S3 state, the FPU state is lost. After resuming for S3, if we try to lazy restore the FPU for a process running on the same CPU, this will result in a corrupted FPU context. Ensure that "fpu_owner_task" is properly invalided when (re-)initializing a CPU, so nobody will try to lazy restore a state which doesn't exist in the hardware. Tested with a 64-bit kernel on a 4-core Ivybridge CPU with eagerfpu=off, by doing thousands of suspend/resume cycles with 4 processes doing FPU operations running. Without the patch, a process is killed after a few hundreds cycles by a SIGFPE. Signed-off-by: Vincent Palatin Cc: Duncan Laurie Cc: Olof Johansson Link: http://lkml.kernel.org/r/1354306532-1014-1-git-send-email-vpalatin@chromium.org Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/fpu-internal.h | 15 +++++++++------ arch/x86/kernel/smpboot.c | 5 +++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h index 4fa88154e4de..92e05b6c84f8 100644 --- a/arch/x86/include/asm/fpu-internal.h +++ b/arch/x86/include/asm/fpu-internal.h @@ -334,14 +334,17 @@ static inline void __thread_fpu_begin(struct task_struct *tsk) typedef struct { int preload; } fpu_switch_t; /* - * FIXME! We could do a totally lazy restore, but we need to - * add a per-cpu "this was the task that last touched the FPU - * on this CPU" variable, and the task needs to have a "I last - * touched the FPU on this CPU" and check them. + * Must be run with preemption disabled: this clears the fpu_owner_task, + * on this CPU. * - * We don't do that yet, so "fpu_lazy_restore()" always returns - * false, but some day.. + * This will disable any lazy FPU state restore of the current FPU state, + * but if the current thread owns the FPU, it will still be saved by. */ +static inline void __cpu_disable_lazy_restore(unsigned int cpu) +{ + per_cpu(fpu_owner_task, cpu) = NULL; +} + static inline int fpu_lazy_restore(struct task_struct *new, unsigned int cpu) { return new == percpu_read_stable(fpu_owner_task) && diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 6e1e406038c2..849cdcf2e76a 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -66,6 +66,8 @@ #include #include #include +#include +#include #include #include #include @@ -851,6 +853,9 @@ int __cpuinit native_cpu_up(unsigned int cpu) per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; + /* the FPU context is blank, nobody can own it */ + __cpu_disable_lazy_restore(cpu); + err = do_boot_cpu(apicid, cpu); if (err) { pr_debug("do_boot_cpu failed %d\n", err); -- GitLab From dbdd7f0c98e8ee0d49da5e8b462ad2ba07d0f358 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Wed, 28 Nov 2012 07:17:18 +0100 Subject: [PATCH 1220/1799] workqueue: exit rescuer_thread() as TASK_RUNNING commit 412d32e6c98527078779e5b515823b2810e40324 upstream. A rescue thread exiting TASK_INTERRUPTIBLE can lead to a task scheduling off, never to be seen again. In the case where this occurred, an exiting thread hit reiserfs homebrew conditional resched while holding a mutex, bringing the box to its knees. PID: 18105 TASK: ffff8807fd412180 CPU: 5 COMMAND: "kdmflush" #0 [ffff8808157e7670] schedule at ffffffff8143f489 #1 [ffff8808157e77b8] reiserfs_get_block at ffffffffa038ab2d [reiserfs] #2 [ffff8808157e79a8] __block_write_begin at ffffffff8117fb14 #3 [ffff8808157e7a98] reiserfs_write_begin at ffffffffa0388695 [reiserfs] #4 [ffff8808157e7ad8] generic_perform_write at ffffffff810ee9e2 #5 [ffff8808157e7b58] generic_file_buffered_write at ffffffff810eeb41 #6 [ffff8808157e7ba8] __generic_file_aio_write at ffffffff810f1a3a #7 [ffff8808157e7c58] generic_file_aio_write at ffffffff810f1c88 #8 [ffff8808157e7cc8] do_sync_write at ffffffff8114f850 #9 [ffff8808157e7dd8] do_acct_process at ffffffff810a268f [exception RIP: kernel_thread_helper] RIP: ffffffff8144a5c0 RSP: ffff8808157e7f58 RFLAGS: 00000202 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffffffff8107af60 RDI: ffff8803ee491d18 RBP: 0000000000000000 R8: 0000000000000000 R9: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 Signed-off-by: Mike Galbraith Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- kernel/workqueue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 56f793d044a5..bcb9d342714b 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -2040,8 +2040,10 @@ static int rescuer_thread(void *__wq) repeat: set_current_state(TASK_INTERRUPTIBLE); - if (kthread_should_stop()) + if (kthread_should_stop()) { + __set_current_state(TASK_RUNNING); return 0; + } /* * See whether any cpu is asking for help. Unbounded -- GitLab From f3921710aa40ae72bd2580282548f763b008a1d0 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 22 Nov 2012 14:42:49 +1100 Subject: [PATCH 1221/1799] md/raid10: close race that lose writes lost when replacement completes. commit e7c0c3fa29280d62aa5e11101a674bb3064bd791 upstream. When a replacement operation completes there is a small window when the original device is marked 'faulty' and the replacement still looks like a replacement. The faulty should be removed and the replacement moved in place very quickly, bit it isn't instant. So the code write out to the array must handle the possibility that the only working device for some slot in the replacement - but it doesn't. If the primary device is faulty it just gives up. This can lead to corruption. So make the code more robust: if either the primary or the replacement is present and working, write to them. Only when neither are present do we give up. This bug has been present since replacement was introduced in 3.3, so it is suitable for any -stable kernel since then. Reported-by: "George Spelvin" Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid10.c | 100 +++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index a2b5304b4eb8..6137d0041d4d 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1182,18 +1182,21 @@ static void make_request(struct mddev *mddev, struct bio * bio) blocked_rdev = rrdev; break; } + if (rdev && (test_bit(Faulty, &rdev->flags) + || test_bit(Unmerged, &rdev->flags))) + rdev = NULL; if (rrdev && (test_bit(Faulty, &rrdev->flags) || test_bit(Unmerged, &rrdev->flags))) rrdev = NULL; r10_bio->devs[i].bio = NULL; r10_bio->devs[i].repl_bio = NULL; - if (!rdev || test_bit(Faulty, &rdev->flags) || - test_bit(Unmerged, &rdev->flags)) { + + if (!rdev && !rrdev) { set_bit(R10BIO_Degraded, &r10_bio->state); continue; } - if (test_bit(WriteErrorSeen, &rdev->flags)) { + if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) { sector_t first_bad; sector_t dev_sector = r10_bio->devs[i].addr; int bad_sectors; @@ -1235,8 +1238,10 @@ static void make_request(struct mddev *mddev, struct bio * bio) max_sectors = good_sectors; } } - r10_bio->devs[i].bio = bio; - atomic_inc(&rdev->nr_pending); + if (rdev) { + r10_bio->devs[i].bio = bio; + atomic_inc(&rdev->nr_pending); + } if (rrdev) { r10_bio->devs[i].repl_bio = bio; atomic_inc(&rrdev->nr_pending); @@ -1292,51 +1297,52 @@ static void make_request(struct mddev *mddev, struct bio * bio) for (i = 0; i < conf->copies; i++) { struct bio *mbio; int d = r10_bio->devs[i].devnum; - if (!r10_bio->devs[i].bio) - continue; - - mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, - max_sectors); - r10_bio->devs[i].bio = mbio; - - mbio->bi_sector = (r10_bio->devs[i].addr+ - conf->mirrors[d].rdev->data_offset); - mbio->bi_bdev = conf->mirrors[d].rdev->bdev; - mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = WRITE | do_sync | do_fua; - mbio->bi_private = r10_bio; - - atomic_inc(&r10_bio->remaining); - spin_lock_irqsave(&conf->device_lock, flags); - bio_list_add(&conf->pending_bio_list, mbio); - conf->pending_count++; - spin_unlock_irqrestore(&conf->device_lock, flags); - - if (!r10_bio->devs[i].repl_bio) - continue; + if (r10_bio->devs[i].bio) { + struct md_rdev *rdev = conf->mirrors[d].rdev; + mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); + md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, + max_sectors); + r10_bio->devs[i].bio = mbio; + + mbio->bi_sector = (r10_bio->devs[i].addr+ + rdev->data_offset); + mbio->bi_bdev = rdev->bdev; + mbio->bi_end_io = raid10_end_write_request; + mbio->bi_rw = WRITE | do_sync | do_fua; + mbio->bi_private = r10_bio; - mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, - max_sectors); - r10_bio->devs[i].repl_bio = mbio; + atomic_inc(&r10_bio->remaining); + spin_lock_irqsave(&conf->device_lock, flags); + bio_list_add(&conf->pending_bio_list, mbio); + conf->pending_count++; + spin_unlock_irqrestore(&conf->device_lock, flags); + } - /* We are actively writing to the original device - * so it cannot disappear, so the replacement cannot - * become NULL here - */ - mbio->bi_sector = (r10_bio->devs[i].addr+ - conf->mirrors[d].replacement->data_offset); - mbio->bi_bdev = conf->mirrors[d].replacement->bdev; - mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = WRITE | do_sync | do_fua; - mbio->bi_private = r10_bio; + if (r10_bio->devs[i].repl_bio) { + struct md_rdev *rdev = conf->mirrors[d].replacement; + if (rdev == NULL) { + /* Replacement just got moved to main 'rdev' */ + smp_mb(); + rdev = conf->mirrors[d].rdev; + } + mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); + md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, + max_sectors); + r10_bio->devs[i].repl_bio = mbio; + + mbio->bi_sector = (r10_bio->devs[i].addr+ + rdev->data_offset); + mbio->bi_bdev = rdev->bdev; + mbio->bi_end_io = raid10_end_write_request; + mbio->bi_rw = WRITE | do_sync | do_fua; + mbio->bi_private = r10_bio; - atomic_inc(&r10_bio->remaining); - spin_lock_irqsave(&conf->device_lock, flags); - bio_list_add(&conf->pending_bio_list, mbio); - conf->pending_count++; - spin_unlock_irqrestore(&conf->device_lock, flags); + atomic_inc(&r10_bio->remaining); + spin_lock_irqsave(&conf->device_lock, flags); + bio_list_add(&conf->pending_bio_list, mbio); + conf->pending_count++; + spin_unlock_irqrestore(&conf->device_lock, flags); + } } /* Don't remove the bias on 'remaining' (one_write_done) until -- GitLab From 43477d60e75490b168627aaafccb7032b28d2574 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 18 Oct 2012 15:54:45 +0200 Subject: [PATCH 1222/1799] i7300_edac: Fix error flag testing commit 7e06b7a3333f5c7a0cec12aff20d39c5c87c0795 upstream. * Right-shift the values in GET_FBD_FAT_IDX and GET_FBD_NF_IDX, so that the callers get the result they expect. * Fix definition of FERR_FAT_FBD_ERR_MASK. * Call GET_FBD_NF_IDX, not GET_FBD_FAT_IDX, when operating on register FERR_NF_FBD. We were lucky they have the same definition. This fixes kernel bug #44131: https://bugzilla.kernel.org/show_bug.cgi?id=44131 Signed-off-by: Jean Delvare Cc: Mauro Carvalho Chehab Cc: Doug Thompson Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/edac/i7300_edac.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 3bafa3bca148..f4059e9da301 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -215,8 +215,8 @@ static const char *ferr_fat_fbd_name[] = { [0] = "Memory Write error on non-redundant retry or " "FBD configuration Write error on retry", }; -#define GET_FBD_FAT_IDX(fbderr) (fbderr & (3 << 28)) -#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)) +#define GET_FBD_FAT_IDX(fbderr) (((fbderr) >> 28) & 3) +#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 22)) #define FERR_NF_FBD 0xa0 static const char *ferr_nf_fbd_name[] = { @@ -243,7 +243,7 @@ static const char *ferr_nf_fbd_name[] = { [1] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC", [0] = "Uncorrectable Data ECC on Replay", }; -#define GET_FBD_NF_IDX(fbderr) (fbderr & (3 << 28)) +#define GET_FBD_NF_IDX(fbderr) (((fbderr) >> 28) & 3) #define FERR_NF_FBD_ERR_MASK ((1 << 24) | (1 << 23) | (1 << 22) | (1 << 21) |\ (1 << 18) | (1 << 17) | (1 << 16) | (1 << 15) |\ (1 << 14) | (1 << 13) | (1 << 11) | (1 << 10) |\ @@ -485,7 +485,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) errnum = find_first_bit(&errors, ARRAY_SIZE(ferr_nf_fbd_name)); specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum); - branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0; + branch = (GET_FBD_NF_IDX(error_reg) == 2) ? 1 : 0; pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, REDMEMA, &syndrome); -- GitLab From 3d81da8645585b9c116a7ac20b99ac8909677c80 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Mon, 3 Dec 2012 06:25:25 +0100 Subject: [PATCH 1223/1799] Revert "sched, autogroup: Stop going ahead if autogroup is disabled" commit fd8ef11730f1d03d5d6555aa53126e9e34f52f12 upstream. This reverts commit 800d4d30c8f20bd728e5741a3b77c4859a613f7c. Between commits 8323f26ce342 ("sched: Fix race in task_group()") and 800d4d30c8f2 ("sched, autogroup: Stop going ahead if autogroup is disabled"), autogroup is a wreck. With both applied, all you have to do to crash a box is disable autogroup during boot up, then reboot.. boom, NULL pointer dereference due to commit 800d4d30c8f2 not allowing autogroup to move things, and commit 8323f26ce342 making that the only way to switch runqueues: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] effective_load.isra.43+0x50/0x90 Pid: 7047, comm: systemd-user-se Not tainted 3.6.8-smp #7 MEDIONPC MS-7502/MS-7502 RIP: effective_load.isra.43+0x50/0x90 Process systemd-user-se (pid: 7047, threadinfo ffff880221dde000, task ffff88022618b3a0) Call Trace: select_task_rq_fair+0x255/0x780 try_to_wake_up+0x156/0x2c0 wake_up_state+0xb/0x10 signal_wake_up+0x28/0x40 complete_signal+0x1d6/0x250 __send_signal+0x170/0x310 send_signal+0x40/0x80 do_send_sig_info+0x47/0x90 group_send_sig_info+0x4a/0x70 kill_pid_info+0x3a/0x60 sys_kill+0x97/0x1a0 ? vfs_read+0x120/0x160 ? sys_read+0x45/0x90 system_call_fastpath+0x16/0x1b Code: 49 0f af 41 50 31 d2 49 f7 f0 48 83 f8 01 48 0f 46 c6 48 2b 07 48 8b bf 40 01 00 00 48 85 ff 74 3a 45 31 c0 48 8b 8f 50 01 00 00 <48> 8b 11 4c 8b 89 80 00 00 00 49 89 d2 48 01 d0 45 8b 59 58 4c RIP [] effective_load.isra.43+0x50/0x90 RSP CR2: 0000000000000000 Signed-off-by: Mike Galbraith Acked-by: Ingo Molnar Cc: Yong Zhang Cc: Peter Zijlstra Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/sched/auto_group.c | 4 ---- kernel/sched/auto_group.h | 5 ----- 2 files changed, 9 deletions(-) diff --git a/kernel/sched/auto_group.c b/kernel/sched/auto_group.c index 0984a21076a3..15f60d01198b 100644 --- a/kernel/sched/auto_group.c +++ b/kernel/sched/auto_group.c @@ -143,15 +143,11 @@ autogroup_move_group(struct task_struct *p, struct autogroup *ag) p->signal->autogroup = autogroup_kref_get(ag); - if (!ACCESS_ONCE(sysctl_sched_autogroup_enabled)) - goto out; - t = p; do { sched_move_task(t); } while_each_thread(p, t); -out: unlock_task_sighand(p, &flags); autogroup_kref_put(prev); } diff --git a/kernel/sched/auto_group.h b/kernel/sched/auto_group.h index 8bd047142816..443232ebbb53 100644 --- a/kernel/sched/auto_group.h +++ b/kernel/sched/auto_group.h @@ -4,11 +4,6 @@ #include struct autogroup { - /* - * reference doesn't mean how many thread attach to this - * autogroup now. It just stands for the number of task - * could use this autogroup. - */ struct kref kref; struct task_group *tg; struct rw_semaphore lock; -- GitLab From e3c8a4858ca78c5da18cd77660ba23ada1c938a9 Mon Sep 17 00:00:00 2001 From: Ariel Elior Date: Thu, 22 Nov 2012 07:16:17 +0000 Subject: [PATCH 1224/1799] bnx2x: remove redundant warning log commit 4a25417c20fac00b3afd58ce27408f964d19e708 upstream. fix bug where a register which was only meant to be read in 578xx/57712 devices causes a bogus error message to be logged when read from other devices. Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller Signed-off-by: CAI Qian Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 6af310195bae..b8e7f3e082e9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -9131,10 +9131,13 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp) */ static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp) { - u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS); - if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) { - BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing"); - REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, 1 << BP_FUNC(bp)); + if (!CHIP_IS_E1x(bp)) { + u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS); + if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) { + BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing"); + REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, + 1 << BP_FUNC(bp)); + } } } -- GitLab From cd81606a09d4ee84de72f02293f826508d1581b0 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 26 Oct 2012 01:05:56 +0200 Subject: [PATCH 1225/1799] ACPI: missing break commit 879dca019dc43a1622edca3e7dde644b14b5acc5 upstream. We handle NOTIFY_THROTTLING so don't then fall through to unsupported event. Signed-off-by: Alan Cox Signed-off-by: Rafael J. Wysocki Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/processor_driver.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index bbac51e79d1f..4a2c131bf086 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -407,6 +407,7 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event) acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); + break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); -- GitLab From 693023b7b8b1a869a7dc2b52a235f77080feed24 Mon Sep 17 00:00:00 2001 From: Calvin Walton Date: Fri, 24 Aug 2012 07:56:31 -0400 Subject: [PATCH 1226/1799] i915: Quirk no_lvds on Gigabyte GA-D525TUD ITX motherboard commit a51d4ed01e5bb39d2cf36a12f9976ab08872c192 upstream. This board is incorrectly detected as having an LVDS connector, resulting in the VGA output (the only available output on the board) showing the console only in the top-left 1024x768 pixels, and an extra LVDS connector appearing in X. It's a desktop Mini-ITX board using an Atom D525 CPU with an NM10 chipset. I've had this board for about a year, but this is the first time I noticed the issue because I've been running it headless for most of its life. Signed-off-by: Calvin Walton Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- 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 4ff7d5f06da6..648afcbc1530 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -785,6 +785,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Gigabyte GA-D525TUD", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), + DMI_MATCH(DMI_BOARD_NAME, "D525TUD"), + }, + }, { } /* terminating entry */ }; -- GitLab From f036099aa85d361fd062384c8e831b580de7bbb2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 18 Oct 2012 21:07:01 +0100 Subject: [PATCH 1227/1799] drm/i915: Add no-lvds quirk for Supermicro X7SPA-H commit c31407a3672aaebb4acddf90944a114fa5c8af7b upstream. Reported-and-tested-by: Francois Tigeot Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55375 Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter Signed-off-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- 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 648afcbc1530..802fec20ff82 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -793,6 +793,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "D525TUD"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Supermicro X7SPA-H", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"), + DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"), + }, + }, { } /* terminating entry */ }; -- GitLab From 0e252d8f530e5d322c53d014ce07b8115dfdac78 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Fri, 24 Aug 2012 00:27:51 +0800 Subject: [PATCH 1228/1799] pnfsblock: fix partial page buffer wirte commit fe6e1e8d9fad86873eb74a26e80a8f91f9e870b5 upstream. If applications use flock to protect its write range, generic NFS will not do read-modify-write cycle at page cache level. Therefore LD should know how to handle non-sector aligned writes. Otherwise there will be data corruption. Signed-off-by: Peng Tao Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/blocklayout/blocklayout.c | 176 ++++++++++++++++++++++++++++--- fs/nfs/blocklayout/blocklayout.h | 1 + 2 files changed, 165 insertions(+), 12 deletions(-) diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 7f6a23f0244e..d16dae2a9b2e 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -162,25 +162,39 @@ static struct bio *bl_alloc_init_bio(int npg, sector_t isect, return bio; } -static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw, +static struct bio *do_add_page_to_bio(struct bio *bio, int npg, int rw, sector_t isect, struct page *page, struct pnfs_block_extent *be, void (*end_io)(struct bio *, int err), - struct parallel_io *par) + struct parallel_io *par, + unsigned int offset, int len) { + isect = isect + (offset >> SECTOR_SHIFT); + dprintk("%s: npg %d rw %d isect %llu offset %u len %d\n", __func__, + npg, rw, (unsigned long long)isect, offset, len); retry: if (!bio) { bio = bl_alloc_init_bio(npg, isect, be, end_io, par); if (!bio) return ERR_PTR(-ENOMEM); } - if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) { + if (bio_add_page(bio, page, len, offset) < len) { bio = bl_submit_bio(rw, bio); goto retry; } return bio; } +static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw, + sector_t isect, struct page *page, + struct pnfs_block_extent *be, + void (*end_io)(struct bio *, int err), + struct parallel_io *par) +{ + return do_add_page_to_bio(bio, npg, rw, isect, page, be, + end_io, par, 0, PAGE_CACHE_SIZE); +} + /* This is basically copied from mpage_end_io_read */ static void bl_end_io_read(struct bio *bio, int err) { @@ -443,6 +457,107 @@ map_block(struct buffer_head *bh, sector_t isect, struct pnfs_block_extent *be) return; } +static void +bl_read_single_end_io(struct bio *bio, int error) +{ + struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; + struct page *page = bvec->bv_page; + + /* Only one page in bvec */ + unlock_page(page); +} + +static int +bl_do_readpage_sync(struct page *page, struct pnfs_block_extent *be, + unsigned int offset, unsigned int len) +{ + struct bio *bio; + struct page *shadow_page; + sector_t isect; + char *kaddr, *kshadow_addr; + int ret = 0; + + dprintk("%s: offset %u len %u\n", __func__, offset, len); + + shadow_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); + if (shadow_page == NULL) + return -ENOMEM; + + bio = bio_alloc(GFP_NOIO, 1); + if (bio == NULL) + return -ENOMEM; + + isect = (page->index << PAGE_CACHE_SECTOR_SHIFT) + + (offset / SECTOR_SIZE); + + bio->bi_sector = isect - be->be_f_offset + be->be_v_offset; + bio->bi_bdev = be->be_mdev; + bio->bi_end_io = bl_read_single_end_io; + + lock_page(shadow_page); + if (bio_add_page(bio, shadow_page, + SECTOR_SIZE, round_down(offset, SECTOR_SIZE)) == 0) { + unlock_page(shadow_page); + bio_put(bio); + return -EIO; + } + + submit_bio(READ, bio); + wait_on_page_locked(shadow_page); + if (unlikely(!test_bit(BIO_UPTODATE, &bio->bi_flags))) { + ret = -EIO; + } else { + kaddr = kmap_atomic(page); + kshadow_addr = kmap_atomic(shadow_page); + memcpy(kaddr + offset, kshadow_addr + offset, len); + kunmap_atomic(kshadow_addr); + kunmap_atomic(kaddr); + } + __free_page(shadow_page); + bio_put(bio); + + return ret; +} + +static int +bl_read_partial_page_sync(struct page *page, struct pnfs_block_extent *be, + unsigned int dirty_offset, unsigned int dirty_len, + bool full_page) +{ + int ret = 0; + unsigned int start, end; + + if (full_page) { + start = 0; + end = PAGE_CACHE_SIZE; + } else { + start = round_down(dirty_offset, SECTOR_SIZE); + end = round_up(dirty_offset + dirty_len, SECTOR_SIZE); + } + + dprintk("%s: offset %u len %d\n", __func__, dirty_offset, dirty_len); + if (!be) { + zero_user_segments(page, start, dirty_offset, + dirty_offset + dirty_len, end); + if (start == 0 && end == PAGE_CACHE_SIZE && + trylock_page(page)) { + SetPageUptodate(page); + unlock_page(page); + } + return ret; + } + + if (start != dirty_offset) + ret = bl_do_readpage_sync(page, be, start, + dirty_offset - start); + + if (!ret && (dirty_offset + dirty_len < end)) + ret = bl_do_readpage_sync(page, be, dirty_offset + dirty_len, + end - dirty_offset - dirty_len); + + return ret; +} + /* Given an unmapped page, zero it or read in page for COW, page is locked * by caller. */ @@ -476,7 +591,6 @@ init_page_for_write(struct page *page, struct pnfs_block_extent *cow_read) SetPageUptodate(page); cleanup: - bl_put_extent(cow_read); if (bh) free_buffer_head(bh); if (ret) { @@ -547,6 +661,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) struct parallel_io *par; loff_t offset = wdata->args.offset; size_t count = wdata->args.count; + unsigned int pg_offset, pg_len, saved_len; struct page **pages = wdata->args.pages; struct page *page; pgoff_t index; @@ -651,10 +766,11 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) if (!extent_length) { /* We've used up the previous extent */ bl_put_extent(be); + bl_put_extent(cow_read); bio = bl_submit_bio(WRITE, bio); /* Get the next one */ be = bl_find_get_extent(BLK_LSEG2EXT(wdata->lseg), - isect, NULL); + isect, &cow_read); if (!be || !is_writable(be, isect)) { wdata->pnfs_error = -EINVAL; goto out; @@ -671,7 +787,26 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) extent_length = be->be_length - (isect - be->be_f_offset); } - if (be->be_state == PNFS_BLOCK_INVALID_DATA) { + + dprintk("%s offset %lld count %Zu\n", __func__, offset, count); + pg_offset = offset & ~PAGE_CACHE_MASK; + if (pg_offset + count > PAGE_CACHE_SIZE) + pg_len = PAGE_CACHE_SIZE - pg_offset; + else + pg_len = count; + + saved_len = pg_len; + if (be->be_state == PNFS_BLOCK_INVALID_DATA && + !bl_is_sector_init(be->be_inval, isect)) { + ret = bl_read_partial_page_sync(pages[i], cow_read, + pg_offset, pg_len, true); + if (ret) { + dprintk("%s bl_read_partial_page_sync fail %d\n", + __func__, ret); + wdata->pnfs_error = ret; + goto out; + } + ret = bl_mark_sectors_init(be->be_inval, isect, PAGE_CACHE_SECTORS); if (unlikely(ret)) { @@ -680,15 +815,33 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) wdata->pnfs_error = ret; goto out; } + + /* Expand to full page write */ + pg_offset = 0; + pg_len = PAGE_CACHE_SIZE; + } else if ((pg_offset & (SECTOR_SIZE - 1)) || + (pg_len & (SECTOR_SIZE - 1))) { + /* ahh, nasty case. We have to do sync full sector + * read-modify-write cycles. + */ + unsigned int saved_offset = pg_offset; + ret = bl_read_partial_page_sync(pages[i], be, pg_offset, + pg_len, false); + pg_offset = round_down(pg_offset, SECTOR_SIZE); + pg_len = round_up(saved_offset + pg_len, SECTOR_SIZE) + - pg_offset; } - bio = bl_add_page_to_bio(bio, wdata->npages - i, WRITE, + bio = do_add_page_to_bio(bio, wdata->npages - i, WRITE, isect, pages[i], be, - bl_end_io_write, par); + bl_end_io_write, par, + pg_offset, pg_len); if (IS_ERR(bio)) { wdata->pnfs_error = PTR_ERR(bio); bio = NULL; goto out; } + offset += saved_len; + count -= saved_len; isect += PAGE_CACHE_SECTORS; last_isect = isect; extent_length -= PAGE_CACHE_SECTORS; @@ -706,17 +859,16 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) } write_done: - wdata->res.count = (last_isect << SECTOR_SHIFT) - (offset); - if (count < wdata->res.count) { - wdata->res.count = count; - } + wdata->res.count = wdata->args.count; out: bl_put_extent(be); + bl_put_extent(cow_read); bl_submit_bio(WRITE, bio); put_parallel(par); return PNFS_ATTEMPTED; out_mds: bl_put_extent(be); + bl_put_extent(cow_read); kfree(par); return PNFS_NOT_ATTEMPTED; } diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h index 03350690118e..39bb51a8dd18 100644 --- a/fs/nfs/blocklayout/blocklayout.h +++ b/fs/nfs/blocklayout/blocklayout.h @@ -41,6 +41,7 @@ #define PAGE_CACHE_SECTORS (PAGE_CACHE_SIZE >> SECTOR_SHIFT) #define PAGE_CACHE_SECTOR_SHIFT (PAGE_CACHE_SHIFT - SECTOR_SHIFT) +#define SECTOR_SIZE (1 << SECTOR_SHIFT) struct block_mount_id { spinlock_t bm_lock; /* protects list */ -- GitLab From cc7c332b34cb936b4a27c1c185700c9a0f7c7bf0 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 25 Sep 2012 16:03:03 +0200 Subject: [PATCH 1229/1799] kbuild: Do not package /boot and /lib in make tar-pkg commit fe04ddf7c2910362f3817c8156e41cbd6c0ee35d upstream. There were reports of users destroying their Fedora installs by a kernel tarball that replaces the /lib -> /usr/lib symlink. Let's remove the toplevel directories from the tarball to prevent this from happening. Reported-by: Andi Kleen Suggested-by: Ben Hutchings Signed-off-by: Michal Marek [bwh: Fold in commit 3ce9e53e788881da0d5f3912f80e0dd6b501f304 to avoid conflicts] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- scripts/package/buildtar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/package/buildtar b/scripts/package/buildtar index 8a7b15598ea9..d0d748e72915 100644 --- a/scripts/package/buildtar +++ b/scripts/package/buildtar @@ -109,7 +109,7 @@ esac if tar --owner=root --group=root --help >/dev/null 2>&1; then opts="--owner=root --group=root" fi - tar cf - . $opts | ${compress} > "${tarball}${file_ext}" + tar cf - boot/* lib/* $opts | ${compress} > "${tarball}${file_ext}" ) echo "Tarball successfully created in ${tarball}${file_ext}" -- GitLab From b947fcbcca85da6ad3ec79f6aa86b550f458e049 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 10 Dec 2012 10:59:56 -0800 Subject: [PATCH 1230/1799] Linux 3.4.23 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 320663d24096..bf1df55f4f97 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 22 +SUBLEVEL = 23 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 78a685beb044864de000a6f7339bce57513172bb Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Wed, 5 Dec 2012 14:01:41 -0800 Subject: [PATCH 1231/1799] tmpfs: fix shared mempolicy leak commit 18a2f371f5edf41810f6469cb9be39931ef9deb9 upstream. This fixes a regression in 3.7-rc, which has since gone into stable. Commit 00442ad04a5e ("mempolicy: fix a memory corruption by refcount imbalance in alloc_pages_vma()") changed get_vma_policy() to raise the refcount on a shmem shared mempolicy; whereas shmem_alloc_page() went on expecting alloc_page_vma() to drop the refcount it had acquired. This deserves a rework: but for now fix the leak in shmem_alloc_page(). Hugh: shmem_swapin() did not need a fix, but surely it's clearer to use the same refcounting there as in shmem_alloc_page(), delete its onstack mempolicy, and the strange mpol_cond_copy() and __mpol_cond_copy() - those were invented to let swapin_readahead() make an unknown number of calls to alloc_pages_vma() with one mempolicy; but since 00442ad04a5e, alloc_pages_vma() has kept refcount in balance, so now no problem. Reported-and-tested-by: Tommi Rantala Signed-off-by: Mel Gorman Signed-off-by: Hugh Dickins Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/mempolicy.h | 16 ---------------- mm/mempolicy.c | 22 ---------------------- mm/shmem.c | 26 ++++++++++++++++---------- 3 files changed, 16 insertions(+), 48 deletions(-) diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 0abf1d436b12..fe07e5a90569 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -137,16 +137,6 @@ static inline void mpol_cond_put(struct mempolicy *pol) __mpol_put(pol); } -extern struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol, - struct mempolicy *frompol); -static inline struct mempolicy *mpol_cond_copy(struct mempolicy *tompol, - struct mempolicy *frompol) -{ - if (!frompol) - return frompol; - return __mpol_cond_copy(tompol, frompol); -} - extern struct mempolicy *__mpol_dup(struct mempolicy *pol); static inline struct mempolicy *mpol_dup(struct mempolicy *pol) { @@ -270,12 +260,6 @@ static inline void mpol_cond_put(struct mempolicy *pol) { } -static inline struct mempolicy *mpol_cond_copy(struct mempolicy *to, - struct mempolicy *from) -{ - return from; -} - static inline void mpol_get(struct mempolicy *pol) { } diff --git a/mm/mempolicy.c b/mm/mempolicy.c index d1e4beffbe1f..458dedef9ee5 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2009,28 +2009,6 @@ struct mempolicy *__mpol_dup(struct mempolicy *old) return new; } -/* - * If *frompol needs [has] an extra ref, copy *frompol to *tompol , - * eliminate the * MPOL_F_* flags that require conditional ref and - * [NOTE!!!] drop the extra ref. Not safe to reference *frompol directly - * after return. Use the returned value. - * - * Allows use of a mempolicy for, e.g., multiple allocations with a single - * policy lookup, even if the policy needs/has extra ref on lookup. - * shmem_readahead needs this. - */ -struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol, - struct mempolicy *frompol) -{ - if (!mpol_needs_cond_ref(frompol)) - return frompol; - - *tompol = *frompol; - tompol->flags &= ~MPOL_F_SHARED; /* copy doesn't need unref */ - __mpol_put(frompol); - return tompol; -} - /* Slow path of a mempolicy comparison */ bool __mpol_equal(struct mempolicy *a, struct mempolicy *b) { diff --git a/mm/shmem.c b/mm/shmem.c index a859b06d573f..a409bd817819 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -798,24 +798,28 @@ static struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo) static struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp, struct shmem_inode_info *info, pgoff_t index) { - struct mempolicy mpol, *spol; struct vm_area_struct pvma; - - spol = mpol_cond_copy(&mpol, - mpol_shared_policy_lookup(&info->policy, index)); + struct page *page; /* Create a pseudo vma that just contains the policy */ pvma.vm_start = 0; pvma.vm_pgoff = index; pvma.vm_ops = NULL; - pvma.vm_policy = spol; - return swapin_readahead(swap, gfp, &pvma, 0); + pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index); + + page = swapin_readahead(swap, gfp, &pvma, 0); + + /* Drop reference taken by mpol_shared_policy_lookup() */ + mpol_cond_put(pvma.vm_policy); + + return page; } static struct page *shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info, pgoff_t index) { struct vm_area_struct pvma; + struct page *page; /* Create a pseudo vma that just contains the policy */ pvma.vm_start = 0; @@ -823,10 +827,12 @@ static struct page *shmem_alloc_page(gfp_t gfp, pvma.vm_ops = NULL; pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index); - /* - * alloc_page_vma() will drop the shared policy reference - */ - return alloc_page_vma(gfp, &pvma, 0); + page = alloc_page_vma(gfp, &pvma, 0); + + /* Drop reference taken by mpol_shared_policy_lookup() */ + mpol_cond_put(pvma.vm_policy); + + return page; } #else /* !CONFIG_NUMA */ #ifdef CONFIG_TMPFS -- GitLab From e07aa3cc22bef722b29b247287d8e47d4c6c2b22 Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Mon, 3 Dec 2012 09:17:19 -0500 Subject: [PATCH 1232/1799] Revert misapplied "mmc: sh-mmcif: avoid oops on spurious interrupts" commit 6984f3c31bb57cb7491dbec1be44b74bd00f4648 upstream. This reverts commit 8464dd52d3198dd05, which was a misapplied debugging version of the patch, not the final patch itself. Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sh_mmcif.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 3b8236bedee5..724b35e85a26 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1191,10 +1191,6 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) host->sd_error = true; dev_dbg(&host->pd->dev, "int err state = %08x\n", state); } - if (host->state == STATE_IDLE) { - dev_info(&host->pd->dev, "Spurious IRQ status 0x%x", state); - return IRQ_HANDLED; - } if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) { if (!host->dma_active) return IRQ_WAKE_THREAD; -- GitLab From 47dc7057a276a3394c94803dd66b395664ebc8f0 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 22 Aug 2012 06:49:47 +0000 Subject: [PATCH 1233/1799] mmc: sh-mmcif: avoid oops on spurious interrupts (second try) commit 91ab252ac5a5c3461dd6910797611e9172626aed upstream. On some systems, e.g., kzm9g, MMCIF interfaces can produce spurious interrupts without any active request. To prevent the Oops, that results in such cases, don't dereference the mmc request pointer until we make sure, that we are indeed processing such a request. Reported-by: Tetsuyuki Kobayashi Signed-off-by: Guennadi Liakhovetski Tested-by: Tetsuyuki Kobayashi Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sh_mmcif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 724b35e85a26..a5786a837a29 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1066,7 +1066,6 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) { struct sh_mmcif_host *host = dev_id; struct mmc_request *mrq = host->mrq; - struct mmc_data *data = mrq->data; cancel_delayed_work_sync(&host->timeout_work); @@ -1114,13 +1113,14 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) case MMCIF_WAIT_FOR_READ_END: case MMCIF_WAIT_FOR_WRITE_END: if (host->sd_error) - data->error = sh_mmcif_error_manage(host); + mrq->data->error = sh_mmcif_error_manage(host); break; default: BUG(); } if (host->wait_for != MMCIF_WAIT_FOR_STOP) { + struct mmc_data *data = mrq->data; if (!mrq->cmd->error && data && !data->error) data->bytes_xfered = data->blocks * data->blksz; -- GitLab From 1b59789b7d3aca70cca0a7b66e57a4a78fcd12d4 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 23 Oct 2012 20:32:59 +0100 Subject: [PATCH 1234/1799] ARM: 7566/1: vfp: fix save and restore when running on pre-VFPv3 and CONFIG_VFPv3 set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 39141ddfb63a664f26d3f42f64ee386e879b492c upstream. After commit 846a136881b8f73c1f74250bf6acfaa309cab1f2 ("ARM: vfp: fix saving d16-d31 vfp registers on v6+ kernels"), the OMAP 2430SDP board started crashing during boot with omap2plus_defconfig: [ 3.875122] mmcblk0: mmc0:e624 SD04G 3.69 GiB [ 3.915954] mmcblk0: p1 [ 4.086639] Internal error: Oops - undefined instruction: 0 [#1] SMP ARM [ 4.093719] Modules linked in: [ 4.096954] CPU: 0 Not tainted (3.6.0-02232-g759e00b #570) [ 4.103149] PC is at vfp_reload_hw+0x1c/0x44 [ 4.107666] LR is at __und_usr_fault_32+0x0/0x8 It turns out that the context save/restore fix unmasked a latent bug in commit 5aaf254409f8d58229107b59507a8235b715a960 ("ARM: 6203/1: Make VFPv3 usable on ARMv6"). When CONFIG_VFPv3 is set, but the kernel is booted on a pre-VFPv3 core, the code attempts to save and restore the d16-d31 VFP registers. These are only present on non-D16 VFPv3+, so this results in an undefined instruction exception. The code didn't crash before commit 846a136 because the save and restore code was only touching d0-d15, present on all VFP. Fix by implementing a request from Russell King to add a new HWCAP flag that affirmatively indicates the presence of the d16-d31 registers: http://marc.info/?l=linux-arm-kernel&m=135013547905283&w=2 and some feedback from Måns to clarify the name of the HWCAP flag. Signed-off-by: Paul Walmsley Cc: Tony Lindgren Cc: Catalin Marinas Cc: Dave Martin Cc: Måns Rullgård Signed-off-by: Russell King Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/hwcap.h | 3 ++- arch/arm/include/asm/vfpmacros.h | 12 ++++++------ arch/arm/vfp/vfpmodule.c | 9 ++++++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/arch/arm/include/asm/hwcap.h b/arch/arm/include/asm/hwcap.h index 917626128a1d..a2fe893802a6 100644 --- a/arch/arm/include/asm/hwcap.h +++ b/arch/arm/include/asm/hwcap.h @@ -18,11 +18,12 @@ #define HWCAP_THUMBEE (1 << 11) #define HWCAP_NEON (1 << 12) #define HWCAP_VFPv3 (1 << 13) -#define HWCAP_VFPv3D16 (1 << 14) +#define HWCAP_VFPv3D16 (1 << 14) /* also set for VFPv4-D16 */ #define HWCAP_TLS (1 << 15) #define HWCAP_VFPv4 (1 << 16) #define HWCAP_IDIVA (1 << 17) #define HWCAP_IDIVT (1 << 18) +#define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */ #define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) #if defined(__KERNEL__) diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h index bf5304797c76..c49c8f778b5d 100644 --- a/arch/arm/include/asm/vfpmacros.h +++ b/arch/arm/include/asm/vfpmacros.h @@ -27,9 +27,9 @@ #if __LINUX_ARM_ARCH__ <= 6 ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, [\tmp, #0] - tst \tmp, #HWCAP_VFPv3D16 - ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} - addne \base, \base, #32*4 @ step over unused register space + tst \tmp, #HWCAP_VFPD32 + ldcnel p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} + addeq \base, \base, #32*4 @ step over unused register space #else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field @@ -51,9 +51,9 @@ #if __LINUX_ARM_ARCH__ <= 6 ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, [\tmp, #0] - tst \tmp, #HWCAP_VFPv3D16 - stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} - addne \base, \base, #32*4 @ step over unused register space + tst \tmp, #HWCAP_VFPD32 + stcnel p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} + addeq \base, \base, #32*4 @ step over unused register space #else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 1f8241da03be..3b360625af75 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -701,11 +701,14 @@ static int __init vfp_init(void) elf_hwcap |= HWCAP_VFPv3; /* - * Check for VFPv3 D16. CPUs in this configuration - * only have 16 x 64bit registers. + * Check for VFPv3 D16 and VFPv4 D16. CPUs in + * this configuration only have 16 x 64bit + * registers. */ if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1) - elf_hwcap |= HWCAP_VFPv3D16; + elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */ + else + elf_hwcap |= HWCAP_VFPD32; } #endif /* -- GitLab From a11bf0aa146b60e917dc30348e301d6a7d13dcbd Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 1 Oct 2012 12:29:26 +0300 Subject: [PATCH 1235/1799] ASoC: dmaengine: Correct Makefile when sound is built as module commit 961a7aeafab477f63d9eef26afde9cbb8badcd0f upstream. soc-dmaengine-pcm library need to be part of the snd-soc-core in order to be able to compile ASoC as modules when dmaengine is enabled on the platform. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown Cc: Florian Fainelli Signed-off-by: Greg Kroah-Hartman --- sound/soc/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 2feaf376e94b..0f370861bbae 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,8 +1,9 @@ snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o snd-soc-core-objs += soc-pcm.o soc-io.o -snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o -obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o +ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),) +snd-soc-core-objs += soc-dmaengine-pcm.o +endif obj-$(CONFIG_SND_SOC) += snd-soc-core.o obj-$(CONFIG_SND_SOC) += codecs/ -- GitLab From 4afca924c03e95345be979bfb7abbfa85963fada Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 4 Dec 2012 07:40:39 -0800 Subject: [PATCH 1236/1799] workqueue: convert BUG_ON()s in __queue_delayed_work() to WARN_ON_ONCE()s commit fc4b514f2727f74a4587c31db87e0e93465518c3 upstream. 8852aac25e ("workqueue: mod_delayed_work_on() shouldn't queue timer on 0 delay") unexpectedly uncovered a very nasty abuse of delayed_work in megaraid - it allocated work_struct, casted it to delayed_work and then pass that into queue_delayed_work(). Previously, this was okay because 0 @delay short-circuited to queue_work() before doing anything with delayed_work. 8852aac25e moved 0 @delay test into __queue_delayed_work() after sanity check on delayed_work making megaraid trigger BUG_ON(). Although megaraid is already fixed by c1d390d8e6 ("megaraid: fix BUG_ON() from incorrect use of delayed work"), this patch converts BUG_ON()s in __queue_delayed_work() to WARN_ON_ONCE()s so that such abusers, if there are more, trigger warning but don't crash the machine. Signed-off-by: Tejun Heo Cc: Xiaotian Feng Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- kernel/workqueue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index bcb9d342714b..a64b94e3c27c 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1141,8 +1141,8 @@ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) { unsigned int lcpu; - BUG_ON(timer_pending(timer)); - BUG_ON(!list_empty(&work->entry)); + WARN_ON_ONCE(timer_pending(timer)); + WARN_ON_ONCE(!list_empty(&work->entry)); timer_stats_timer_set_start_info(&dwork->timer); -- GitLab From 11b73096b67cde81ba05125cecb06fe9884e4cb7 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 Nov 2012 14:33:44 +0200 Subject: [PATCH 1237/1799] drm/i915: do not ignore eDP bpc settings from vbt commit 2f4f649a69a9eb51f6e98130e19dd90a260a4145 upstream. There are laptops out there that need the eDP bpc from VBT. This is effectively a revert of commit 4344b813f105a19f793f1fd93ad775b784648b95 Author: Daniel Vetter Date: Fri Aug 10 11:10:20 2012 +0200 drm/i915: ignore eDP bpc settings from vbt but putting the VBT check after the EDID check to see them both in dmesg if this clamps more than the EDID. We have enough history with bpc clamping to warrant the extra debug info. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47641 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=56401 Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f3b06f04e011..c9ea4fba4479 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4996,6 +4996,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, } } + if (intel_encoder->type == INTEL_OUTPUT_EDP) { + /* Use VBT settings if we have an eDP panel */ + unsigned int edp_bpc = dev_priv->edp.bpp / 3; + + if (edp_bpc < display_bpc) { + DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); + display_bpc = edp_bpc; + } + continue; + } + /* * HDMI is either 12 or 8, so if the display lets 10bpc sneak * through, clamp it down. (Note: >12bpc will be caught below.) -- GitLab From d7ba8dff3e8afc83efe19c52ac7bd9ee2b65720b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 Nov 2012 14:33:45 +0200 Subject: [PATCH 1238/1799] drm/i915: do not default to 18 bpp for eDP if missing from VBT commit 9a30a61f3516871c5c638fd7c025fbaa11ddf7fe upstream. commit 500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0c Author: Zhenyu Wang Date: Wed Jan 13 11:19:52 2010 +0800 drm/i915: parse eDP panel color depth from VBT block originally introduced parsing bpp for eDP from VBT, with a default of 18 bpp if the eDP BIOS data block is not present. Turns out that default seems to break the Macbook Pro with retina display, as noted in commit 4344b813f105a19f793f1fd93ad775b784648b95 Author: Daniel Vetter Date: Fri Aug 10 11:10:20 2012 +0200 drm/i915: ignore eDP bpc settings from vbt Since we can't ignore bpc settings from VBT completely after all, get rid of the default. Do not clamp eDP to 18 bpp by default if the eDP BDB is missing from VBT. Signed-off-by: Jani Nikula Tested-by: Henrik Rydberg [danvet: paste in the updated commit message from irc.] Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_bios.c | 11 ++--------- drivers/gpu/drm/i915/intel_display.c | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index b48fc2a8410c..3fe05245d3fc 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -459,12 +459,8 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) edp = find_section(bdb, BDB_EDP); if (!edp) { - if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) { - DRM_DEBUG_KMS("No eDP BDB found but eDP panel " - "supported, assume %dbpp panel color " - "depth.\n", - dev_priv->edp.bpp); - } + if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) + DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n"); return; } @@ -617,9 +613,6 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) dev_priv->lvds_use_ssc = 1; dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq); - - /* eDP data */ - dev_priv->edp.bpp = 18; } static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c9ea4fba4479..dd3e7e44023e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5000,7 +5000,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, /* Use VBT settings if we have an eDP panel */ unsigned int edp_bpc = dev_priv->edp.bpp / 3; - if (edp_bpc < display_bpc) { + if (edp_bpc && edp_bpc < display_bpc) { DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); display_bpc = edp_bpc; } -- GitLab From ead8c6b3697c9d45c16ecad17e5b4101573767f9 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 7 Nov 2012 15:37:07 +0100 Subject: [PATCH 1239/1799] mm: dmapool: use provided gfp flags for all dma_alloc_coherent() calls commit 387870f2d6d679746020fa8e25ef786ff338dc98 upstream. dmapool always calls dma_alloc_coherent() with GFP_ATOMIC flag, regardless the flags provided by the caller. This causes excessive pruning of emergency memory pools without any good reason. Additionaly, on ARM architecture any driver which is using dmapools will sooner or later trigger the following error: "ERROR: 256 KiB atomic DMA coherent pool is too small! Please increase it with coherent_pool= kernel parameter!". Increasing the coherent pool size usually doesn't help much and only delays such error, because all GFP_ATOMIC DMA allocations are always served from the special, very limited memory pool. This patch changes the dmapool code to correctly use gfp flags provided by the dmapool caller. Reported-by: Soeren Moch Reported-by: Thomas Petazzoni Signed-off-by: Marek Szyprowski Tested-by: Andrew Lunn Tested-by: Soeren Moch Signed-off-by: Greg Kroah-Hartman --- mm/dmapool.c | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/mm/dmapool.c b/mm/dmapool.c index c5ab33bca0a8..da1b0f0b8709 100644 --- a/mm/dmapool.c +++ b/mm/dmapool.c @@ -50,7 +50,6 @@ struct dma_pool { /* the pool */ size_t allocation; size_t boundary; char name[32]; - wait_queue_head_t waitq; struct list_head pools; }; @@ -62,8 +61,6 @@ struct dma_page { /* cacheable header for 'allocation' bytes */ unsigned int offset; }; -#define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000) - static DEFINE_MUTEX(pools_lock); static ssize_t @@ -172,7 +169,6 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev, retval->size = size; retval->boundary = boundary; retval->allocation = allocation; - init_waitqueue_head(&retval->waitq); if (dev) { int ret; @@ -227,7 +223,6 @@ static struct dma_page *pool_alloc_page(struct dma_pool *pool, gfp_t mem_flags) memset(page->vaddr, POOL_POISON_FREED, pool->allocation); #endif pool_initialise_page(pool, page); - list_add(&page->page_list, &pool->page_list); page->in_use = 0; page->offset = 0; } else { @@ -315,30 +310,21 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags, might_sleep_if(mem_flags & __GFP_WAIT); spin_lock_irqsave(&pool->lock, flags); - restart: list_for_each_entry(page, &pool->page_list, page_list) { if (page->offset < pool->allocation) goto ready; } - page = pool_alloc_page(pool, GFP_ATOMIC); - if (!page) { - if (mem_flags & __GFP_WAIT) { - DECLARE_WAITQUEUE(wait, current); - __set_current_state(TASK_UNINTERRUPTIBLE); - __add_wait_queue(&pool->waitq, &wait); - spin_unlock_irqrestore(&pool->lock, flags); + /* pool_alloc_page() might sleep, so temporarily drop &pool->lock */ + spin_unlock_irqrestore(&pool->lock, flags); - schedule_timeout(POOL_TIMEOUT_JIFFIES); + page = pool_alloc_page(pool, mem_flags); + if (!page) + return NULL; - spin_lock_irqsave(&pool->lock, flags); - __remove_wait_queue(&pool->waitq, &wait); - goto restart; - } - retval = NULL; - goto done; - } + spin_lock_irqsave(&pool->lock, flags); + list_add(&page->page_list, &pool->page_list); ready: page->in_use++; offset = page->offset; @@ -348,7 +334,6 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags, #ifdef DMAPOOL_DEBUG memset(retval, POOL_POISON_ALLOCATED, pool->size); #endif - done: spin_unlock_irqrestore(&pool->lock, flags); return retval; } @@ -435,8 +420,6 @@ void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t dma) page->in_use--; *(int *)vaddr = page->offset; page->offset = offset; - if (waitqueue_active(&pool->waitq)) - wake_up_locked(&pool->waitq); /* * Resist a temptation to do * if (!is_page_busy(page)) pool_free_page(pool, page); -- GitLab From 5678ad746ce7654007d3fd521015ff93ef907747 Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Wed, 5 Dec 2012 06:12:42 -0500 Subject: [PATCH 1240/1799] x86,AMD: Power driver support for AMD's family 16h processors commit 22e32f4f57778ebc6e17812fa3008361c05d64f9 upstream. Add family 16h PCI ID to AMD's power driver to allow it report power consumption on these processors. Signed-off-by: Boris Ostrovsky Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/fam15h_power.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index ac2d6cb39e7d..770e95951a56 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -31,6 +31,9 @@ MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor"); MODULE_AUTHOR("Andreas Herrmann "); MODULE_LICENSE("GPL"); +/* Family 16h Northbridge's function 4 PCI ID */ +#define PCI_DEVICE_ID_AMD_16H_NB_F4 0x1534 + /* D18F3 */ #define REG_NORTHBRIDGE_CAP 0xe8 @@ -256,6 +259,7 @@ static void __devexit fam15h_power_remove(struct pci_dev *pdev) static DEFINE_PCI_DEVICE_TABLE(fam15h_power_id_table) = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) }, {} }; MODULE_DEVICE_TABLE(pci, fam15h_power_id_table); -- GitLab From 2ee75ba7f69754ee04e723b037b15715c0483d50 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 3 Dec 2012 22:05:12 +0300 Subject: [PATCH 1241/1799] telephony: ijx: buffer overflow in ixj_write_cid() [Not needed in 3.8 or newer as this driver is removed there. - gregkh] We get this from user space and nothing has been done to ensure that these strings are NUL terminated. Reported-by: Chen Gang Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/telephony/ixj.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/telephony/ixj.c b/drivers/staging/telephony/ixj.c index f96027921f60..638d2b8c687c 100644 --- a/drivers/staging/telephony/ixj.c +++ b/drivers/staging/telephony/ixj.c @@ -3190,12 +3190,12 @@ static void ixj_write_cid(IXJ *j) ixj_fsk_alloc(j); - strcpy(sdmf1, j->cid_send.month); - strcat(sdmf1, j->cid_send.day); - strcat(sdmf1, j->cid_send.hour); - strcat(sdmf1, j->cid_send.min); - strcpy(sdmf2, j->cid_send.number); - strcpy(sdmf3, j->cid_send.name); + strlcpy(sdmf1, j->cid_send.month, sizeof(sdmf1)); + strlcat(sdmf1, j->cid_send.day, sizeof(sdmf1)); + strlcat(sdmf1, j->cid_send.hour, sizeof(sdmf1)); + strlcat(sdmf1, j->cid_send.min, sizeof(sdmf1)); + strlcpy(sdmf2, j->cid_send.number, sizeof(sdmf2)); + strlcpy(sdmf3, j->cid_send.name, sizeof(sdmf3)); len1 = strlen(sdmf1); len2 = strlen(sdmf2); @@ -3340,12 +3340,12 @@ static void ixj_write_cidcw(IXJ *j) ixj_pre_cid(j); } j->flags.cidcw_ack = 0; - strcpy(sdmf1, j->cid_send.month); - strcat(sdmf1, j->cid_send.day); - strcat(sdmf1, j->cid_send.hour); - strcat(sdmf1, j->cid_send.min); - strcpy(sdmf2, j->cid_send.number); - strcpy(sdmf3, j->cid_send.name); + strlcpy(sdmf1, j->cid_send.month, sizeof(sdmf1)); + strlcat(sdmf1, j->cid_send.day, sizeof(sdmf1)); + strlcat(sdmf1, j->cid_send.hour, sizeof(sdmf1)); + strlcat(sdmf1, j->cid_send.min, sizeof(sdmf1)); + strlcpy(sdmf2, j->cid_send.number, sizeof(sdmf2)); + strlcpy(sdmf3, j->cid_send.name, sizeof(sdmf3)); len1 = strlen(sdmf1); len2 = strlen(sdmf2); -- GitLab From 280c7a49c54e1191ddff18db0f44f1f404408829 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 2 Nov 2012 14:02:40 +0000 Subject: [PATCH 1242/1799] x86: hpet: Fix masking of MSI interrupts commit 6acf5a8c931da9d26c8dd77d784daaf07fa2bff0 upstream. HPET_TN_FSB is not a proper mask bit; it merely toggles between MSI and legacy interrupt delivery. The proper mask bit is HPET_TN_ENABLE, so use both bits when (un)masking the interrupt. Signed-off-by: Jan Beulich Link: http://lkml.kernel.org/r/5093E09002000078000A60E6@nat28.tlf.novell.com Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/hpet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index ad0de0c2714e..2861b4cafd2e 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -431,7 +431,7 @@ void hpet_msi_unmask(struct irq_data *data) /* unmask it */ cfg = hpet_readl(HPET_Tn_CFG(hdev->num)); - cfg |= HPET_TN_FSB; + cfg |= HPET_TN_ENABLE | HPET_TN_FSB; hpet_writel(cfg, HPET_Tn_CFG(hdev->num)); } @@ -442,7 +442,7 @@ void hpet_msi_mask(struct irq_data *data) /* mask it */ cfg = hpet_readl(HPET_Tn_CFG(hdev->num)); - cfg &= ~HPET_TN_FSB; + cfg &= ~(HPET_TN_ENABLE | HPET_TN_FSB); hpet_writel(cfg, HPET_Tn_CFG(hdev->num)); } -- GitLab From d1687be63d3037bd98ab8e0e5e34fc724f0863a1 Mon Sep 17 00:00:00 2001 From: "li.rui27@zte.com.cn" Date: Tue, 20 Nov 2012 14:31:47 +0800 Subject: [PATCH 1243/1799] USB: add new zte 3g-dongle's pid to option.c commit 31b6a1048b7292efff8b5b53ae3d9d29adde385e upstream. Signed-off-by: Rui li Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 43aa36bcd396..329fe2b8e538 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -883,6 +883,10 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0135, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0136, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0137, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0139, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) }, @@ -903,20 +907,34 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */ .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0196, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0197, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */ .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0200, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0201, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0330, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0395, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0414, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0417, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, @@ -1096,6 +1114,10 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1301, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1302, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1303, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1333, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff), -- GitLab From 249d474cd9320f25ab04832e5b03b98462930362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sun, 25 Nov 2012 17:05:10 +0100 Subject: [PATCH 1244/1799] USB: option: blacklist network interface on Huawei E173 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f36446cf9bbebaa03a80d95cfeeafbaf68218249 upstream. The Huawei E173 will normally appear as 12d1:1436 in Linux. But the modem has another mode with different device ID and a slightly different set of descriptors. This is the mode used by Windows like this: 3Modem: USB\VID_12D1&PID_140C&MI_00\6&3A1D2012&0&0000 Networkcard: USB\VID_12D1&PID_140C&MI_01\6&3A1D2012&0&0001 Appli.Inter: USB\VID_12D1&PID_140C&MI_02\6&3A1D2012&0&0002 PC UI Inter: USB\VID_12D1&PID_140C&MI_03\6&3A1D2012&0&0003 All interfaces have the same ff/ff/ff class codes in this mode. Blacklisting the network interface to allow it to be picked up by the network driver. Reported-by: Thomas Schäfer Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 329fe2b8e538..0c3d29034816 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -80,6 +80,7 @@ static void option_instat_callback(struct urb *urb); #define OPTION_PRODUCT_GTM380_MODEM 0x7201 #define HUAWEI_VENDOR_ID 0x12D1 +#define HUAWEI_PRODUCT_E173 0x140C #define HUAWEI_PRODUCT_K4505 0x1464 #define HUAWEI_PRODUCT_K3765 0x1465 #define HUAWEI_PRODUCT_K4605 0x14C6 @@ -552,6 +553,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff), -- GitLab From c36337a3562352a753995cb220b58f81f5e81e74 Mon Sep 17 00:00:00 2001 From: Martin Teichmann Date: Wed, 21 Nov 2012 16:45:07 +0100 Subject: [PATCH 1245/1799] USB: ftdi_sio: Add support for Newport AGILIS motor drivers commit d7e14b375b40c04cd735b115713043b69a2c68ac upstream. The Newport AGILIS model AG-UC8 compact piezo motor controller (http://search.newport.com/?q=*&x2=sku&q2=AG-UC8) is yet another device using an FTDI USB-to-serial chip. It works fine with the ftdi_sio driver when adding options ftdi-sio product=0x3000 vendor=0x104d to modprobe.d. udevadm reports "Newport" as the manufacturer, and "Agilis" as the product name. Signed-off-by: Martin Teichmann 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 25bb93503963..dd6b0270f68e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -197,6 +197,7 @@ static struct usb_device_id id_table_combined [] = { { 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(NEWPORT_VID, NEWPORT_AGILIS_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 57c12ef6625e..049b6e715fa4 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -752,6 +752,12 @@ #define TTI_VID 0x103E /* Vendor Id */ #define TTI_QL355P_PID 0x03E8 /* TTi QL355P power supply */ +/* + * Newport Cooperation (www.newport.com) + */ +#define NEWPORT_VID 0x104D +#define NEWPORT_AGILIS_PID 0x3000 + /* Interbiometrics USB I/O Board */ /* Developed for Interbiometrics by Rudolf Gugler */ #define INTERBIOMETRICS_VID 0x1209 -- GitLab From 73b01ef413e7311e5dff622a1e50fe86d7253273 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Thu, 22 Nov 2012 16:30:46 +0100 Subject: [PATCH 1246/1799] usb: ftdi_sio: fixup BeagleBone A5+ quirk commit 1a88d5eee2ef2ad1d3c4e32043e9c4c5347d4fc1 upstream. BeagleBone A5+ devices ended up getting shipped with the 'BeagleBone/XDS100V2' product string, and not XDS100 like it was agreed, so adjust the quirk to match. For details, see the thread on the beagle list: https://groups.google.com/forum/#!msg/beagleboard/zrFPew9_Wvo/ibWr1-eE8JwJ Signed-off-by: Peter Korsgaard 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 dd6b0270f68e..25903f54c1d2 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1811,7 +1811,7 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial) dbg("%s", __func__); if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) || - (udev->product && !strcmp(udev->product, "BeagleBone/XDS100"))) + (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2"))) return ftdi_jtag_probe(serial); return 0; -- GitLab From 7052793cd192c09b47c4fb307bc3c2afbdf3c5df Mon Sep 17 00:00:00 2001 From: Markus Becker Date: Thu, 22 Nov 2012 09:41:23 +0100 Subject: [PATCH 1247/1799] USB: cp210x: add Virtenio Preon32 device id commit 356fe44f4b8ece867bdb9876b1854d7adbef9de2 upstream. Signed-off-by: Markus Becker 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 53e7e692d616..f38a27831466 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -120,6 +120,7 @@ static const struct usb_device_id id_table[] = { { 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, 0x85F8) }, /* Virtenio Preon32 */ { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ -- GitLab From 46c117c706ef4f4086cbe24d24fd0f19551e96bd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 28 Nov 2012 10:19:16 -0800 Subject: [PATCH 1248/1799] USB: mark uas driver as BROKEN commit fb37ef98015f864d22be223a0e0d93547cd1d4ef upstream. As reported https://bugzilla.kernel.org/show_bug.cgi?id=51031, the UAS driver causes problems and has been asked to be not built into any of the major distributions. To prevent users from running into problems with it, and for distros that were not notified, just mark the whole thing as broken. Acked-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 7691c866637b..685edc872654 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -203,7 +203,7 @@ config USB_STORAGE_ENE_UB6250 config USB_UAS tristate "USB Attached SCSI" - depends on USB && SCSI + depends on USB && SCSI && BROKEN help The USB Attached SCSI protocol is supported by some USB storage devices. It permits higher performance by supporting -- GitLab From b49dc13a7f10e003e176263215411ccea99380f1 Mon Sep 17 00:00:00 2001 From: Kamil Iskra Date: Fri, 16 Nov 2012 22:28:58 +0100 Subject: [PATCH 1249/1799] ACPI / battery: Correct battery capacity values on Thinkpads commit 4000e626156935dfb626321ce09cae2c833eabbb upstream. Add a quirk to correctly report battery capacity on 2010 and 2011 Lenovo Thinkpad models. The affected models that I tested (x201, t410, t410s, and x220) exhibit a problem where, when battery capacity reporting unit is mAh, the values being reported are wrong. Pre-2010 and 2012 models appear to always report in mWh and are thus unaffected. Also, in mid-2012 Lenovo issued a BIOS update for the 2011 models that fixes the issue (tested on x220 with a post-1.29 BIOS). No such update is available for the 2010 models, so those still need this patch. Problem description: for some reason, the affected Thinkpads switch the reporting unit between mAh and mWh; generally, mAh is used when a laptop is plugged in and mWh when it's unplugged, although a suspend/resume or rmmod/modprobe is needed for the switch to take effect. The values reported in mAh are *always* wrong. This does not appear to be a kernel regression; I believe that the values were never reported correctly. I tested back to kernel 2.6.34, with multiple machines and BIOS versions. Simply plugging a laptop into mains before turning it on is enough to reproduce the problem. Here's a sample /proc/acpi/battery/BAT0/info from Thinkpad x220 (before a BIOS update) with a 4-cell battery: present: yes design capacity: 2886 mAh last full capacity: 2909 mAh battery technology: rechargeable design voltage: 14800 mV design capacity warning: 145 mAh design capacity low: 13 mAh cycle count: 0 capacity granularity 1: 1 mAh capacity granularity 2: 1 mAh model number: 42T4899 serial number: 21064 battery type: LION OEM info: SANYO Once the laptop switches the unit to mWh (unplug from mains, suspend, resume), the output changes to: present: yes design capacity: 28860 mWh last full capacity: 29090 mWh battery technology: rechargeable design voltage: 14800 mV design capacity warning: 1454 mWh design capacity low: 200 mWh cycle count: 0 capacity granularity 1: 1 mWh capacity granularity 2: 1 mWh model number: 42T4899 serial number: 21064 battery type: LION OEM info: SANYO Can you see how the values for "design capacity", etc., differ by a factor of 10 instead of 14.8 (the design voltage of this battery)? On the battery itself it says: 14.8V, 1.95Ah, 29Wh, so clearly the values reported in mWh are correct and the ones in mAh are not. My guess is that this problem has been around ever since those machines were released, but because the most common Thinkpad batteries are rated at 10.8V, the error (8%) is small enough that it simply hasn't been noticed or at least nobody could be bothered to look into it. My patch works around the problem by adjusting the incorrectly reported mAh values by "10000 / design_voltage". The patch also has code to figure out if it should be activated or not. It only activates on Lenovo Thinkpads, only when the unit is mAh, and, as an extra precaution, only when the battery capacity reported through ACPI does not match what is reported through DMI (I've never encountered a machine where the first two conditions would be true but the last would not, but better safe than sorry). I've been using this patch for close to a year on several systems without any problems. References: https://bugzilla.kernel.org/show_bug.cgi?id=41062 Acked-by: Henrique de Moraes Holschuh Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/battery.c | 77 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 7dd3f9fb9f3f..6ea287e22296 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef CONFIG_ACPI_PROCFS_POWER #include @@ -95,6 +96,18 @@ enum { ACPI_BATTERY_ALARM_PRESENT, ACPI_BATTERY_XINFO_PRESENT, ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, + /* On Lenovo Thinkpad models from 2010 and 2011, the power unit + switches between mWh and mAh depending on whether the system + is running on battery or not. When mAh is the unit, most + reported values are incorrect and need to be adjusted by + 10000/design_voltage. Verified on x201, t410, t410s, and x220. + Pre-2010 and 2012 models appear to always report in mWh and + are thus unaffected (tested with t42, t61, t500, x200, x300, + and x230). Also, in mid-2012 Lenovo issued a BIOS update for + the 2011 models that fixes the issue (tested on x220 with a + post-1.29 BIOS), but as of Nov. 2012, no such update is + available for the 2010 models. */ + ACPI_BATTERY_QUIRK_THINKPAD_MAH, }; struct acpi_battery { @@ -429,6 +442,21 @@ static int acpi_battery_get_info(struct acpi_battery *battery) kfree(buffer.pointer); if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) battery->full_charge_capacity = battery->design_capacity; + if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) && + battery->power_unit && battery->design_voltage) { + battery->design_capacity = battery->design_capacity * + 10000 / battery->design_voltage; + battery->full_charge_capacity = battery->full_charge_capacity * + 10000 / battery->design_voltage; + battery->design_capacity_warning = + battery->design_capacity_warning * + 10000 / battery->design_voltage; + /* Curiously, design_capacity_low, unlike the rest of them, + is correct. */ + /* capacity_granularity_* equal 1 on the systems tested, so + it's impossible to tell if they would need an adjustment + or not if their values were higher. */ + } return result; } @@ -477,6 +505,11 @@ static int acpi_battery_get_state(struct acpi_battery *battery) && battery->capacity_now >= 0 && battery->capacity_now <= 100) battery->capacity_now = (battery->capacity_now * battery->full_charge_capacity) / 100; + if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) && + battery->power_unit && battery->design_voltage) { + battery->capacity_now = battery->capacity_now * + 10000 / battery->design_voltage; + } return result; } @@ -586,6 +619,24 @@ static void sysfs_remove_battery(struct acpi_battery *battery) mutex_unlock(&battery->sysfs_lock); } +static void find_battery(const struct dmi_header *dm, void *private) +{ + struct acpi_battery *battery = (struct acpi_battery *)private; + /* Note: the hardcoded offsets below have been extracted from + the source code of dmidecode. */ + if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) { + const u8 *dmi_data = (const u8 *)(dm + 1); + int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6)); + if (dm->length >= 18) + dmi_capacity *= dmi_data[17]; + if (battery->design_capacity * battery->design_voltage / 1000 + != dmi_capacity && + battery->design_capacity * 10 == dmi_capacity) + set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, + &battery->flags); + } +} + /* * According to the ACPI spec, some kinds of primary batteries can * report percentage battery remaining capacity directly to OS. @@ -611,6 +662,32 @@ static void acpi_battery_quirks(struct acpi_battery *battery) battery->capacity_now = (battery->capacity_now * battery->full_charge_capacity) / 100; } + + if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags)) + return ; + + if (battery->power_unit && dmi_name_in_vendors("LENOVO")) { + const char *s; + s = dmi_get_system_info(DMI_PRODUCT_VERSION); + if (s && !strnicmp(s, "ThinkPad", 8)) { + dmi_walk(find_battery, battery); + if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, + &battery->flags) && + battery->design_voltage) { + battery->design_capacity = + battery->design_capacity * + 10000 / battery->design_voltage; + battery->full_charge_capacity = + battery->full_charge_capacity * + 10000 / battery->design_voltage; + battery->design_capacity_warning = + battery->design_capacity_warning * + 10000 / battery->design_voltage; + battery->capacity_now = battery->capacity_now * + 10000 / battery->design_voltage; + } + } + } } static int acpi_battery_update(struct acpi_battery *battery) -- GitLab From b54b1f3b656a93e874b38d88c513769c2f29bf6b Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 21 Nov 2012 23:12:12 +0100 Subject: [PATCH 1250/1799] ACPI / PM: Add Sony Vaio VPCEB1S1E to nonvs blacklist. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 876ab79055019e248508cfd0dee7caa3c0c831ed upstream. Sony Vaio VPCEB1S1E does not resume correctly without acpi_sleep=nonvs, so add it to the ACPI sleep blacklist. References: https://bugzilla.kernel.org/show_bug.cgi?id=48781 Reported-by: Sébastien Wilmet Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/sleep.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 2377445f4a3d..480b648b9a1d 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -508,6 +508,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { }, { .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCEB1S1E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1S1E"), + }, + }, + { + .callback = init_nvs_nosave, .ident = "Sony Vaio VGN-FW520F", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), -- GitLab From fe1fa6761bdc53fd7be7524436ad00907100c054 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 30 Nov 2012 13:05:05 +0100 Subject: [PATCH 1251/1799] ACPI / PNP: Do not crash due to stale pointer use during system resume commit a6b5e88c0e42093b9057856f35770966c8c591e3 upstream. During resume from system suspend the 'data' field of struct pnp_dev in pnpacpi_set_resources() may be a stale pointer, due to removal of the associated ACPI device node object in the previous suspend-resume cycle. This happens, for example, if a dockable machine is booted in the docking station and then suspended and resumed and suspended again. If that happens, pnpacpi_build_resource_template() called from pnpacpi_set_resources() attempts to use that pointer and crashes. However, pnpacpi_set_resources() actually checks the device's ACPI handle, attempts to find the ACPI device node object attached to it and returns an error code if that fails, so in fact it knows what the correct value of dev->data should be. Use this observation to update dev->data with the correct value if necessary and dump a call trace if that's the case (once). We still need to fix the root cause of this issue, but preventing systems from crashing because of it is an improvement too. Reported-and-tested-by: Zdenek Kabelac References: https://bugzilla.kernel.org/show_bug.cgi?id=51071 Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/pnp/pnpacpi/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index d21e8f59c84e..e3537888db7e 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -95,6 +95,9 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) return -ENODEV; } + if (WARN_ON_ONCE(acpi_dev != dev->data)) + dev->data = acpi_dev; + ret = pnpacpi_build_resource_template(dev, &buffer); if (ret) return ret; -- GitLab From a5e247e527586e4edee5f24d5e8f85ecf1905ea7 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 4 Dec 2012 23:30:19 +0100 Subject: [PATCH 1252/1799] ACPI / video: ignore BIOS initial backlight value for HP Folio 13-2000 commit 129ff8f8d58297b04f47b5d6fad81aa2d08404e1 upstream. Or else the laptop will boot with a dimmed screen. References: https://bugzilla.kernel.org/show_bug.cgi?id=51141 Tested-by: Stefan Nagy Signed-off-by: Zhang Rui Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/video.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 62d9ee6d077a..91357e1a1a88 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -389,6 +389,12 @@ static int __init video_set_bqc_offset(const struct dmi_system_id *d) return 0; } +static int video_ignore_initial_backlight(const struct dmi_system_id *d) +{ + use_bios_initial_backlight = 0; + return 0; +} + static struct dmi_system_id video_dmi_table[] __initdata = { /* * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121 @@ -433,6 +439,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"), }, }, + { + .callback = video_ignore_initial_backlight, + .ident = "HP Folio 13-2000", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"), + }, + }, {} }; -- GitLab From 96d791a8023037c312072a5a9d735417a07a6c5a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 26 Nov 2012 12:36:21 -0500 Subject: [PATCH 1253/1799] USB: OHCI: workaround for hardware bug: retired TDs not added to the Done Queue commit 50ce5c0683aa83eb161624ea89daa5a9eee0c2ce upstream. This patch (as1636) is a partial workaround for a hardware bug affecting OHCI controllers by NVIDIA at least, maybe others too. When the controller retires a Transfer Descriptor, it is supposed to add the TD onto the Done Queue. But sometimes this doesn't happen, with the result that ohci-hcd never realizes the corresponding transfer has finished. Symptoms can vary; a typical result is that USB audio stops working after a while. The patch works around the problem by recognizing that TDs are always processed in order. Therefore, if a later TD is found on the Done Queue than all the earlier TDs for the same endpoint must be finished as well. Unfortunately this won't solve the problem in cases where the missing TD is the last one in the endpoint's queue. A complete fix would require a signficant amount of change to the driver. Signed-off-by: Alan Stern Tested-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-q.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index c5a1ea9145fa..9d00d4721bca 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -1128,6 +1128,25 @@ dl_done_list (struct ohci_hcd *ohci) while (td) { struct td *td_next = td->next_dl_td; + struct ed *ed = td->ed; + + /* + * Some OHCI controllers (NVIDIA for sure, maybe others) + * occasionally forget to add TDs to the done queue. Since + * TDs for a given endpoint are always processed in order, + * if we find a TD on the donelist then all of its + * predecessors must be finished as well. + */ + for (;;) { + struct td *td2; + + td2 = list_first_entry(&ed->td_list, struct td, + td_list); + if (td2 == td) + break; + takeback_td(ohci, td2); + } + takeback_td(ohci, td); td = td_next; } -- GitLab From 31fdb19eb968995b3c5f4337918bd51442f992ec Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 17 Oct 2012 13:44:06 -0700 Subject: [PATCH 1254/1799] xhci: Extend Fresco Logic MSI quirk. commit bba18e33f25072ebf70fd8f7f0cdbf8cdb59a746 upstream. Ali reports that plugging a device into the Fresco Logic xHCI host with PCI device ID 1400 produces an IRQ error: do_IRQ: 3.176 No irq handler for vector (irq -1) Other early Fresco Logic host revisions don't support MSI, even though their PCI config space claims they do. Extend the quirk to disabling MSI to this chipset revision. Also enable the short transfer quirk, since it's likely this revision also has that quirk, and it should be harmless to enable. 04:00.0 0c03: 1b73:1400 (rev 01) (prog-if 30 [XHCI]) Subsystem: 1d5c:1000 Physical Slot: 3 Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+ Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- SERR- Reported-by: A Sh Tested-by: A Sh Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 4211017b8892..84e82dc7b794 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -29,6 +29,7 @@ /* Device for a quirk */ #define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73 #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000 +#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400 0x1400 #define PCI_VENDOR_ID_ETRON 0x1b6f #define PCI_DEVICE_ID_ASROCK_P67 0x7023 @@ -58,8 +59,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) /* Look for vendor-specific quirks */ if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && - pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) { - if (pdev->revision == 0x0) { + (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK || + pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1400)) { + if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK && + pdev->revision == 0x0) { xhci->quirks |= XHCI_RESET_EP_QUIRK; xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure" " endpoint cmd after reset endpoint\n"); -- GitLab From 455d8953951baf0d38673b010100241e508b765c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 9 Jun 2012 19:10:27 +0300 Subject: [PATCH 1255/1799] ftrace: Clear bits properly in reset_iter_read() commit 70f77b3f7ec010ff9624c1f2e39a81babc9e2429 upstream. There is a typo here where '&' is used instead of '|' and it turns the statement into a noop. The original code is equivalent to: iter->flags &= ~((1 << 2) & (1 << 4)); Link: http://lkml.kernel.org/r/20120609161027.GD6488@elgon.mountain Signed-off-by: Dan Carpenter 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 0fa92f677c92..100b7fd1a64b 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2368,7 +2368,7 @@ static void reset_iter_read(struct ftrace_iterator *iter) { iter->pos = 0; iter->func_pos = 0; - iter->flags &= ~(FTRACE_ITER_PRINTALL & FTRACE_ITER_HASH); + iter->flags &= ~(FTRACE_ITER_PRINTALL | FTRACE_ITER_HASH); } static void *t_start(struct seq_file *m, loff_t *pos) -- GitLab From 1229a83d1ea3d11b4433f7080825d05044af45a9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 8 Nov 2012 12:47:41 -0600 Subject: [PATCH 1256/1799] cdc-acm: implement TIOCSSERIAL to avoid blocking close(2) commit ba2d8ce9db0a61505362bb17b8899df3d3326146 upstream. Some devices (ex Nokia C7) simply don't respond at all when data is sent to some of their USB interfaces. The data gets stuck in the TTYs queue and sits there until close(2), which them blocks because closing_wait defaults to 30 seconds (even though the fd is O_NONBLOCK). This is rarely desired. Implement the standard mechanism to adjust closing_wait and let applications handle it how they want to. See also 02303f73373aa1da19dbec510ec5a4e2576f9610 for usb_wwan.c. Signed-off-by: Dan Williams Acked-by: Oliver Neukum Tested-by: Aleksander Morgado Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index c5f7eae429e8..b4e87cfa73a7 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -788,6 +788,10 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info) tmp.flags = ASYNC_LOW_LATENCY; tmp.xmit_fifo_size = acm->writesize; tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); + tmp.close_delay = acm->port.close_delay / 10; + tmp.closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : + acm->port.closing_wait / 10; if (copy_to_user(info, &tmp, sizeof(tmp))) return -EFAULT; @@ -795,6 +799,37 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info) return 0; } +static int set_serial_info(struct acm *acm, + struct serial_struct __user *newinfo) +{ + struct serial_struct new_serial; + unsigned int closing_wait, close_delay; + int retval = 0; + + if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) + return -EFAULT; + + close_delay = new_serial.close_delay * 10; + closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; + + mutex_lock(&acm->port.mutex); + + if (!capable(CAP_SYS_ADMIN)) { + if ((close_delay != acm->port.close_delay) || + (closing_wait != acm->port.closing_wait)) + retval = -EPERM; + else + retval = -EOPNOTSUPP; + } else { + acm->port.close_delay = close_delay; + acm->port.closing_wait = closing_wait; + } + + mutex_unlock(&acm->port.mutex); + return retval; +} + static int acm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { @@ -805,6 +840,9 @@ static int acm_tty_ioctl(struct tty_struct *tty, case TIOCGSERIAL: /* gets serial port data */ rv = get_serial_info(acm, (struct serial_struct __user *) arg); break; + case TIOCSSERIAL: + rv = set_serial_info(acm, (struct serial_struct __user *) arg); + break; } return rv; -- GitLab From d5a79aa30b7e6cd68dfee6a76acbe6c7f7905f51 Mon Sep 17 00:00:00 2001 From: Zheng Liu Date: Thu, 8 Nov 2012 16:58:46 -0800 Subject: [PATCH 1257/1799] perf test: fix a build error on builtin-test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 12f8f74b2a4d26c4facfa7ef99487cf0930f6ef7 upstream. Recently I build perf and get a build error on builtin-test.c. The error is as following: $ make CC perf.o CC builtin-test.o cc1: warnings being treated as errors builtin-test.c: In function ‘sched__get_first_possible_cpu’: builtin-test.c:977: warning: implicit declaration of function ‘CPU_ALLOC’ builtin-test.c:977: warning: nested extern declaration of ‘CPU_ALLOC’ builtin-test.c:977: warning: assignment makes pointer from integer without a cast builtin-test.c:978: warning: implicit declaration of function ‘CPU_ALLOC_SIZE’ builtin-test.c:978: warning: nested extern declaration of ‘CPU_ALLOC_SIZE’ builtin-test.c:979: warning: implicit declaration of function ‘CPU_ZERO_S’ builtin-test.c:979: warning: nested extern declaration of ‘CPU_ZERO_S’ builtin-test.c:982: warning: implicit declaration of function ‘CPU_FREE’ builtin-test.c:982: warning: nested extern declaration of ‘CPU_FREE’ builtin-test.c:992: warning: implicit declaration of function ‘CPU_ISSET_S’ builtin-test.c:992: warning: nested extern declaration of ‘CPU_ISSET_S’ builtin-test.c:998: warning: implicit declaration of function ‘CPU_CLR_S’ builtin-test.c:998: warning: nested extern declaration of ‘CPU_CLR_S’ make: *** [builtin-test.o] Error 1 This problem is introduced in 3e7c439a. CPU_ALLOC and related macros are missing in sched__get_first_possible_cpu function. In 54489c18, commiter mentioned that CPU_ALLOC has been removed. So CPU_ALLOC calls in this function are removed to let perf to be built. Signed-off-by: Vinson Lee Signed-off-by: Zheng Liu Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Vinson Lee Cc: Zheng Liu Link: http://lkml.kernel.org/r/1352422726-31114-1-git-send-email-vlee@twitter.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman --- tools/perf/builtin-test.c | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 223ffdcc0fd8..3487b4b42114 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -1154,19 +1154,13 @@ static int test__parse_events(void) return ret; } -static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t **maskp, - size_t *sizep) +static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp) { - cpu_set_t *mask; - size_t size; int i, cpu = -1, nrcpus = 1024; realloc: - mask = CPU_ALLOC(nrcpus); - size = CPU_ALLOC_SIZE(nrcpus); - CPU_ZERO_S(size, mask); + CPU_ZERO(maskp); - if (sched_getaffinity(pid, size, mask) == -1) { - CPU_FREE(mask); + if (sched_getaffinity(pid, sizeof(*maskp), maskp) == -1) { if (errno == EINVAL && nrcpus < (1024 << 8)) { nrcpus = nrcpus << 2; goto realloc; @@ -1176,19 +1170,14 @@ static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t **maskp, } for (i = 0; i < nrcpus; i++) { - if (CPU_ISSET_S(i, size, mask)) { - if (cpu == -1) { + if (CPU_ISSET(i, maskp)) { + if (cpu == -1) cpu = i; - *maskp = mask; - *sizep = size; - } else - CPU_CLR_S(i, size, mask); + else + CPU_CLR(i, maskp); } } - if (cpu == -1) - CPU_FREE(mask); - return cpu; } @@ -1199,8 +1188,8 @@ static int test__PERF_RECORD(void) .freq = 10, .mmap_pages = 256, }; - cpu_set_t *cpu_mask = NULL; - size_t cpu_mask_size = 0; + cpu_set_t cpu_mask; + size_t cpu_mask_size = sizeof(cpu_mask); struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); struct perf_evsel *evsel; struct perf_sample sample; @@ -1265,8 +1254,7 @@ static int test__PERF_RECORD(void) evsel->attr.sample_type |= PERF_SAMPLE_TIME; perf_evlist__config_attrs(evlist, &opts); - err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask, - &cpu_mask_size); + err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); if (err < 0) { pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); goto out_delete_evlist; @@ -1277,9 +1265,9 @@ static int test__PERF_RECORD(void) /* * So that we can check perf_sample.cpu on all the samples. */ - if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, cpu_mask) < 0) { + if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { pr_debug("sched_setaffinity: %s\n", strerror(errno)); - goto out_free_cpu_mask; + goto out_delete_evlist; } /* @@ -1472,8 +1460,6 @@ static int test__PERF_RECORD(void) } out_err: perf_evlist__munmap(evlist); -out_free_cpu_mask: - CPU_FREE(cpu_mask); out_delete_evlist: perf_evlist__delete(evlist); out: -- GitLab From 29251de53e1712158c29b3626a008d8b93a6e024 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 18 Oct 2012 04:55:36 -0700 Subject: [PATCH 1258/1799] rcu: Fix batch-limit size problem commit 878d7439d0f45a95869e417576774673d1fa243f upstream. Commit 29c00b4a1d9e27 (rcu: Add event-tracing for RCU callback invocation) added a regression in rcu_do_batch() Under stress, RCU is supposed to allow to process all items in queue, instead of a batch of 10 items (blimit), but an integer overflow makes the effective limit being 1. So, unless there is frequent idle periods (during which RCU ignores batch limits), RCU can be forced into a state where it cannot keep up with the callback-generation rate, eventually resulting in OOM. This commit therefore converts a few variables in rcu_do_batch() from int to long to fix this problem, along with the module parameters controlling the batch limits. Signed-off-by: Eric Dumazet Signed-off-by: Paul E. McKenney Signed-off-by: Greg Kroah-Hartman --- kernel/rcutree.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 4eec66e0350d..62c5e9cf6fcb 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -202,13 +202,13 @@ DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = { .dynticks = ATOMIC_INIT(1), }; -static int blimit = 10; /* Maximum callbacks per rcu_do_batch. */ -static int qhimark = 10000; /* If this many pending, ignore blimit. */ -static int qlowmark = 100; /* Once only this many pending, use blimit. */ +static long blimit = 10; /* Maximum callbacks per rcu_do_batch. */ +static long qhimark = 10000; /* If this many pending, ignore blimit. */ +static long qlowmark = 100; /* Once only this many pending, use blimit. */ -module_param(blimit, int, 0); -module_param(qhimark, int, 0); -module_param(qlowmark, int, 0); +module_param(blimit, long, 0); +module_param(qhimark, long, 0); +module_param(qlowmark, long, 0); int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */ int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT; @@ -1476,7 +1476,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp) { unsigned long flags; struct rcu_head *next, *list, **tail; - int bl, count, count_lazy; + long bl, count, count_lazy; /* If no callbacks are ready, just return.*/ if (!cpu_has_callbacks_ready_to_invoke(rdp)) { -- GitLab From e56f8b7aeb0b8135ee29b0612b192a784450739e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Dec 2012 10:38:05 -0800 Subject: [PATCH 1259/1799] Linux 3.4.24 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bf1df55f4f97..a3e12e687c67 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 23 +SUBLEVEL = 24 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 1789172140b7b61955b87b3070fb30da1a701d7c Mon Sep 17 00:00:00 2001 From: Sarveshwar Bandi Date: Wed, 21 Nov 2012 04:35:03 +0000 Subject: [PATCH 1260/1799] bonding: Bonding driver does not consider the gso_max_size/gso_max_segs setting of slave devices. [ Upstream commit 0e376bd0b791ac6ac6bdb051492df0769c840848 ] Patch sets the lowest gso_max_size and gso_max_segs values of the slave devices during enslave and detach. Signed-off-by: Sarveshwar Bandi Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/bonding/bond_main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 318a62a4db52..6df52c9ba499 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1383,6 +1383,8 @@ static void bond_compute_features(struct bonding *bond) struct net_device *bond_dev = bond->dev; netdev_features_t vlan_features = BOND_VLAN_FEATURES; unsigned short max_hard_header_len = ETH_HLEN; + unsigned int gso_max_size = GSO_MAX_SIZE; + u16 gso_max_segs = GSO_MAX_SEGS; int i; read_lock(&bond->lock); @@ -1396,11 +1398,16 @@ static void bond_compute_features(struct bonding *bond) if (slave->dev->hard_header_len > max_hard_header_len) max_hard_header_len = slave->dev->hard_header_len; + + gso_max_size = min(gso_max_size, slave->dev->gso_max_size); + gso_max_segs = min(gso_max_segs, slave->dev->gso_max_segs); } done: bond_dev->vlan_features = vlan_features; bond_dev->hard_header_len = max_hard_header_len; + bond_dev->gso_max_segs = gso_max_segs; + netif_set_gso_max_size(bond_dev, gso_max_size); read_unlock(&bond->lock); -- GitLab From 1097b6a83df844d5145a1f9821300028857d8ca9 Mon Sep 17 00:00:00 2001 From: "nikolay@redhat.com" Date: Thu, 29 Nov 2012 01:37:59 +0000 Subject: [PATCH 1261/1799] bonding: fix race condition in bonding_store_slaves_active [ Upstream commit e196c0e579902f42cf72414461fb034e5a1ffbf7 ] Race between bonding_store_slaves_active() and slave manipulation functions. The bond_for_each_slave use in bonding_store_slaves_active() is not protected by any synchronization mechanism. NULL pointer dereference is easy to reach. Fixed by acquiring the bond->lock for the slave walk. v2: Make description text < 75 columns Signed-off-by: Nikolay Aleksandrov Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/bonding/bond_sysfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index aef42f045320..6734737c9530 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1578,6 +1578,7 @@ static ssize_t bonding_store_slaves_active(struct device *d, goto out; } + read_lock(&bond->lock); bond_for_each_slave(bond, slave, i) { if (!bond_is_active_slave(slave)) { if (new_value) @@ -1586,6 +1587,7 @@ static ssize_t bonding_store_slaves_active(struct device *d, slave->inactive = 1; } } + read_unlock(&bond->lock); out: return ret; } -- GitLab From d0804c62db373041db42aa976edf2b9e5f5ae9ed Mon Sep 17 00:00:00 2001 From: Tommi Rantala Date: Tue, 27 Nov 2012 04:01:46 +0000 Subject: [PATCH 1262/1799] sctp: fix memory leak in sctp_datamsg_from_user() when copy from user space fails [ Upstream commit be364c8c0f17a3dd42707b5a090b318028538eb9 ] Trinity (the syscall fuzzer) discovered a memory leak in SCTP, reproducible e.g. with the sendto() syscall by passing invalid user space pointer in the second argument: #include #include #include int main(void) { int fd; struct sockaddr_in sa; fd = socket(AF_INET, SOCK_STREAM, 132 /*IPPROTO_SCTP*/); if (fd < 0) return 1; memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = inet_addr("127.0.0.1"); sa.sin_port = htons(11111); sendto(fd, NULL, 1, 0, (struct sockaddr *)&sa, sizeof(sa)); return 0; } As far as I can tell, the leak has been around since ~2003. Signed-off-by: Tommi Rantala Acked-by: Vlad Yasevich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/chunk.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 6c8556459a75..9534bf9a14ea 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -284,7 +284,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, goto errout; err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov); if (err < 0) - goto errout; + goto errout_chunk_free; offset += len; @@ -324,7 +324,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, __skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr - (__u8 *)chunk->skb->data); if (err < 0) - goto errout; + goto errout_chunk_free; sctp_datamsg_assign(msg, chunk); list_add_tail(&chunk->frag_list, &msg->chunks); @@ -332,6 +332,9 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, return msg; +errout_chunk_free: + sctp_chunk_free(chunk); + errout: list_for_each_safe(pos, temp, &msg->chunks) { list_del_init(pos); -- GitLab From dff343c7f4dfa5650d5d3a78f58f080ec9f14a25 Mon Sep 17 00:00:00 2001 From: Tommi Rantala Date: Thu, 22 Nov 2012 03:23:16 +0000 Subject: [PATCH 1263/1799] sctp: fix -ENOMEM result with invalid user space pointer in sendto() syscall [ Upstream commit 6e51fe7572590d8d86e93b547fab6693d305fd0d ] Consider the following program, that sets the second argument to the sendto() syscall incorrectly: #include #include #include int main(void) { int fd; struct sockaddr_in sa; fd = socket(AF_INET, SOCK_STREAM, 132 /*IPPROTO_SCTP*/); if (fd < 0) return 1; memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = inet_addr("127.0.0.1"); sa.sin_port = htons(11111); sendto(fd, NULL, 1, 0, (struct sockaddr *)&sa, sizeof(sa)); return 0; } We get -ENOMEM: $ strace -e sendto ./demo sendto(3, NULL, 1, 0, {sa_family=AF_INET, sin_port=htons(11111), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 ENOMEM (Cannot allocate memory) Propagate the error code from sctp_user_addto_chunk(), so that we will tell user space what actually went wrong: $ strace -e sendto ./demo sendto(3, NULL, 1, 0, {sa_family=AF_INET, sin_port=htons(11111), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EFAULT (Bad address) Noticed while running Trinity (the syscall fuzzer). Signed-off-by: Tommi Rantala Acked-by: Vlad Yasevich Acked-by: Neil Horman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/chunk.c | 13 +++++++++---- net/sctp/socket.c | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 9534bf9a14ea..0018b653cb1f 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -183,7 +183,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, msg = sctp_datamsg_new(GFP_KERNEL); if (!msg) - return NULL; + return ERR_PTR(-ENOMEM); /* Note: Calculate this outside of the loop, so that all fragments * have the same expiration. @@ -280,8 +280,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0); - if (!chunk) + if (!chunk) { + err = -ENOMEM; goto errout; + } + err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov); if (err < 0) goto errout_chunk_free; @@ -315,8 +318,10 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0); - if (!chunk) + if (!chunk) { + err = -ENOMEM; goto errout; + } err = sctp_user_addto_chunk(chunk, offset, over,msgh->msg_iov); @@ -342,7 +347,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, sctp_chunk_free(chunk); } sctp_datamsg_put(msg); - return NULL; + return ERR_PTR(err); } /* Check whether this message has expired. */ diff --git a/net/sctp/socket.c b/net/sctp/socket.c index dba20d6e3247..74053554a859 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1908,8 +1908,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, /* Break the message into multiple chunks of maximum size. */ datamsg = sctp_datamsg_from_user(asoc, sinfo, msg, msg_len); - if (!datamsg) { - err = -ENOMEM; + if (IS_ERR(datamsg)) { + err = PTR_ERR(datamsg); goto out_free; } -- GitLab From aa335048531c58da34fed27b69a7ba0faf9a1eee Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 20 Nov 2012 06:31:57 +0000 Subject: [PATCH 1264/1799] ne2000: add the right platform device [ Upstream commit da9da01d9199b5bb15289d0859053c9aa3a34ac0 ] Without this udev doesn't have a way to key the ne device to the platform device. Signed-off-by: Alan Cox Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/8390/ne.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c index d04911d33b64..47618e505355 100644 --- a/drivers/net/ethernet/8390/ne.c +++ b/drivers/net/ethernet/8390/ne.c @@ -813,6 +813,7 @@ static int __init ne_drv_probe(struct platform_device *pdev) dev->irq = irq[this_dev]; dev->mem_end = bad[this_dev]; } + SET_NETDEV_DEV(dev, &pdev->dev); err = do_ne_probe(dev); if (err) { free_netdev(dev); -- GitLab From 6b015f351d9c8a1800f4e234fbfbcc0198bf0b5f Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Tue, 20 Nov 2012 09:59:11 +0000 Subject: [PATCH 1265/1799] irda: sir_dev: Fix copy/paste typo [ Upstream commit 2355a62bcbdcc4b567425bab036bfab6ade87eed ] Signed-off-by: Alexander Shiyan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/irda/sir_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c index 5039f08f5a5b..43e9ab4f4d7e 100644 --- a/drivers/net/irda/sir_dev.c +++ b/drivers/net/irda/sir_dev.c @@ -222,7 +222,7 @@ static void sirdev_config_fsm(struct work_struct *work) break; case SIRDEV_STATE_DONGLE_SPEED: - if (dev->dongle_drv->reset) { + if (dev->dongle_drv->set_speed) { ret = dev->dongle_drv->set_speed(dev, fsm->param); if (ret < 0) { fsm->result = ret; -- GitLab From eab34a33cfdda79711f6c66a9f9d7a558238eed8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 9 Dec 2012 23:41:06 +0000 Subject: [PATCH 1266/1799] ipv4: ip_check_defrag must not modify skb before unsharing [ Upstream commit 1bf3751ec90cc3174e01f0d701e8449ce163d113 ] ip_check_defrag() might be called from af_packet within the RX path where shared SKBs are used, so it must not modify the input SKB before it has unshared it for defragmentation. Use skb_copy_bits() to get the IP header and only pull in everything later. The same is true for the other caller in macvlan as it is called from dev->rx_handler which can also get a shared SKB. Reported-by: Eric Leblond Cc: stable@vger.kernel.org Signed-off-by: Johannes Berg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ip_fragment.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 3727e234c884..b7bf6e30adbc 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -685,28 +685,27 @@ EXPORT_SYMBOL(ip_defrag); struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user) { - const struct iphdr *iph; + struct iphdr iph; u32 len; if (skb->protocol != htons(ETH_P_IP)) return skb; - if (!pskb_may_pull(skb, sizeof(struct iphdr))) + if (!skb_copy_bits(skb, 0, &iph, sizeof(iph))) return skb; - iph = ip_hdr(skb); - if (iph->ihl < 5 || iph->version != 4) + if (iph.ihl < 5 || iph.version != 4) return skb; - if (!pskb_may_pull(skb, iph->ihl*4)) - return skb; - iph = ip_hdr(skb); - len = ntohs(iph->tot_len); - if (skb->len < len || len < (iph->ihl * 4)) + + len = ntohs(iph.tot_len); + if (skb->len < len || len < (iph.ihl * 4)) return skb; - if (ip_is_fragment(ip_hdr(skb))) { + if (ip_is_fragment(&iph)) { skb = skb_share_check(skb, GFP_ATOMIC); if (skb) { + if (!pskb_may_pull(skb, iph.ihl*4)) + return skb; if (pskb_trim_rcsum(skb, len)) return skb; memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); -- GitLab From 1755fd2e38a0541dab207df5d42d92b567695497 Mon Sep 17 00:00:00 2001 From: Jay Purohit Date: Sun, 14 Oct 2012 07:07:21 +0000 Subject: [PATCH 1267/1799] usb/ipheth: Add iPhone 5 support [ Upstream commit af1b85e49089f945deb46258b0fc4bc9910afb22 ] I noticed that the iPhone ethernet driver did not support iPhone 5. I quickly added support to it in my kernel, here's a patch. Signed-off-by: Jay Purohit Acked-by: Valdis Kletnieks Signed-off-by: Jan Ceuleers Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/ipheth.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 5cba41517f73..32e47918e59d 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -62,6 +62,7 @@ #define USB_PRODUCT_IPAD 0x129a #define USB_PRODUCT_IPHONE_4_VZW 0x129c #define USB_PRODUCT_IPHONE_4S 0x12a0 +#define USB_PRODUCT_IPHONE_5 0x12a8 #define IPHETH_USBINTF_CLASS 255 #define IPHETH_USBINTF_SUBCLASS 253 @@ -113,6 +114,10 @@ static struct usb_device_id ipheth_table[] = { USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( + USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5, + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, { } }; MODULE_DEVICE_TABLE(usb, ipheth_table); -- GitLab From 457a04b96314023464f8249975b1efb4eef1c925 Mon Sep 17 00:00:00 2001 From: Neal Cardwell Date: Sat, 8 Dec 2012 19:43:21 +0000 Subject: [PATCH 1268/1799] inet_diag: fix oops for IPv4 AF_INET6 TCP SYN-RECV state [ Upstream commit 1c95df85ca49640576de2f0a850925957b547b84 ] Fix inet_diag to be aware of the fact that AF_INET6 TCP connections instantiated for IPv4 traffic and in the SYN-RECV state were actually created with inet_reqsk_alloc(), instead of inet6_reqsk_alloc(). This means that for such connections inet6_rsk(req) returns a pointer to a random spot in memory up to roughly 64KB beyond the end of the request_sock. With this bug, for a server using AF_INET6 TCP sockets and serving IPv4 traffic, an inet_diag user like `ss state SYN-RECV` would lead to inet_diag_fill_req() causing an oops or the export to user space of 16 bytes of kernel memory as a garbage IPv6 address, depending on where the garbage inet6_rsk(req) pointed. Signed-off-by: Neal Cardwell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/inet_diag.c | 53 ++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index dda5383a6f0b..06fe2fef2680 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -44,6 +44,10 @@ struct inet_diag_entry { u16 dport; u16 family; u16 userlocks; +#if IS_ENABLED(CONFIG_IPV6) + struct in6_addr saddr_storage; /* for IPv4-mapped-IPv6 addresses */ + struct in6_addr daddr_storage; /* for IPv4-mapped-IPv6 addresses */ +#endif }; #define INET_DIAG_PUT(skb, attrtype, attrlen) \ @@ -586,6 +590,36 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); } +/* Get the IPv4, IPv6, or IPv4-mapped-IPv6 local and remote addresses + * from a request_sock. For IPv4-mapped-IPv6 we must map IPv4 to IPv6. + */ +static inline void inet_diag_req_addrs(const struct sock *sk, + const struct request_sock *req, + struct inet_diag_entry *entry) +{ + struct inet_request_sock *ireq = inet_rsk(req); + +#if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == AF_INET6) { + if (req->rsk_ops->family == AF_INET6) { + entry->saddr = inet6_rsk(req)->loc_addr.s6_addr32; + entry->daddr = inet6_rsk(req)->rmt_addr.s6_addr32; + } else if (req->rsk_ops->family == AF_INET) { + ipv6_addr_set_v4mapped(ireq->loc_addr, + &entry->saddr_storage); + ipv6_addr_set_v4mapped(ireq->rmt_addr, + &entry->daddr_storage); + entry->saddr = entry->saddr_storage.s6_addr32; + entry->daddr = entry->daddr_storage.s6_addr32; + } + } else +#endif + { + entry->saddr = &ireq->loc_addr; + entry->daddr = &ireq->rmt_addr; + } +} + static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, struct request_sock *req, u32 pid, u32 seq, const struct nlmsghdr *unlh) @@ -624,8 +658,10 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, r->idiag_inode = 0; #if IS_ENABLED(CONFIG_IPV6) if (r->idiag_family == AF_INET6) { - *(struct in6_addr *)r->id.idiag_src = inet6_rsk(req)->loc_addr; - *(struct in6_addr *)r->id.idiag_dst = inet6_rsk(req)->rmt_addr; + struct inet_diag_entry entry; + inet_diag_req_addrs(sk, req, &entry); + memcpy(r->id.idiag_src, entry.saddr, sizeof(struct in6_addr)); + memcpy(r->id.idiag_dst, entry.daddr, sizeof(struct in6_addr)); } #endif nlh->nlmsg_len = skb_tail_pointer(skb) - b; @@ -683,18 +719,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, continue; if (bc) { - entry.saddr = -#if IS_ENABLED(CONFIG_IPV6) - (entry.family == AF_INET6) ? - inet6_rsk(req)->loc_addr.s6_addr32 : -#endif - &ireq->loc_addr; - entry.daddr = -#if IS_ENABLED(CONFIG_IPV6) - (entry.family == AF_INET6) ? - inet6_rsk(req)->rmt_addr.s6_addr32 : -#endif - &ireq->rmt_addr; + inet_diag_req_addrs(sk, req, &entry); entry.dport = ntohs(ireq->rmt_port); if (!inet_diag_bc_run(bc, &entry)) -- GitLab From 879fc99ecd078f64849b95c47cf7e28705ac8884 Mon Sep 17 00:00:00 2001 From: Neal Cardwell Date: Sat, 8 Dec 2012 19:43:22 +0000 Subject: [PATCH 1269/1799] inet_diag: validate byte code to prevent oops in inet_diag_bc_run() [ Upstream commit 405c005949e47b6e91359159c24753519ded0c67 ] Add logic to validate INET_DIAG_BC_S_COND and INET_DIAG_BC_D_COND operations. Previously we did not validate the inet_diag_hostcond, address family, address length, and prefix length. So a malicious user could make the kernel read beyond the end of the bytecode array by claiming to have a whole inet_diag_hostcond when the bytecode was not long enough to contain a whole inet_diag_hostcond of the given address family. Or they could make the kernel read up to about 27 bytes beyond the end of a connection address by passing a prefix length that exceeded the length of addresses of the given family. Signed-off-by: Neal Cardwell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/inet_diag.c | 48 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 06fe2fef2680..35b2dfc092ae 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -504,6 +504,44 @@ static int valid_cc(const void *bc, int len, int cc) return 0; } +/* Validate an inet_diag_hostcond. */ +static bool valid_hostcond(const struct inet_diag_bc_op *op, int len, + int *min_len) +{ + int addr_len; + struct inet_diag_hostcond *cond; + + /* Check hostcond space. */ + *min_len += sizeof(struct inet_diag_hostcond); + if (len < *min_len) + return false; + cond = (struct inet_diag_hostcond *)(op + 1); + + /* Check address family and address length. */ + switch (cond->family) { + case AF_UNSPEC: + addr_len = 0; + break; + case AF_INET: + addr_len = sizeof(struct in_addr); + break; + case AF_INET6: + addr_len = sizeof(struct in6_addr); + break; + default: + return false; + } + *min_len += addr_len; + if (len < *min_len) + return false; + + /* Check prefix length (in bits) vs address length (in bytes). */ + if (cond->prefix_len > 8 * addr_len) + return false; + + return true; +} + static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) { const void *bc = bytecode; @@ -511,18 +549,22 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) while (len > 0) { const struct inet_diag_bc_op *op = bc; + int min_len = sizeof(struct inet_diag_bc_op); //printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len); switch (op->code) { - case INET_DIAG_BC_AUTO: case INET_DIAG_BC_S_COND: case INET_DIAG_BC_D_COND: + if (!valid_hostcond(bc, len, &min_len)) + return -EINVAL; + /* fall through */ + case INET_DIAG_BC_AUTO: case INET_DIAG_BC_S_GE: case INET_DIAG_BC_S_LE: case INET_DIAG_BC_D_GE: case INET_DIAG_BC_D_LE: case INET_DIAG_BC_JMP: - if (op->no < 4 || op->no > len + 4 || op->no & 3) + if (op->no < min_len || op->no > len + 4 || op->no & 3) return -EINVAL; if (op->no < len && !valid_cc(bytecode, bytecode_len, len - op->no)) @@ -533,7 +575,7 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) default: return -EINVAL; } - if (op->yes < 4 || op->yes > len + 4 || op->yes & 3) + if (op->yes < min_len || op->yes > len + 4 || op->yes & 3) return -EINVAL; bc += op->yes; len -= op->yes; -- GitLab From b2aa2e70f9d6d5c4aadccdda5956991e8d1869e8 Mon Sep 17 00:00:00 2001 From: Neal Cardwell Date: Sat, 8 Dec 2012 19:43:23 +0000 Subject: [PATCH 1270/1799] inet_diag: avoid unsafe and nonsensical prefix matches in inet_diag_bc_run() [ Upstream commit f67caec9068cee426ec23cf9005a1dee2ecad187 ] Add logic to check the address family of the user-supplied conditional and the address family of the connection entry. We now do not do prefix matching of addresses from different address families (AF_INET vs AF_INET6), except for the previously existing support for having an IPv4 prefix match an IPv4-mapped IPv6 address (which this commit maintains as-is). This change is needed for two reasons: (1) The addresses are different lengths, so comparing a 128-bit IPv6 prefix match condition to a 32-bit IPv4 connection address can cause us to unwittingly walk off the end of the IPv4 address and read garbage or oops. (2) The IPv4 and IPv6 address spaces are semantically distinct, so a simple bit-wise comparison of the prefixes is not meaningful, and would lead to bogus results (except for the IPv4-mapped IPv6 case, which this commit maintains). Signed-off-by: Neal Cardwell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/inet_diag.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 35b2dfc092ae..8b20ca64208b 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -423,25 +423,31 @@ static int inet_diag_bc_run(const struct nlattr *_bc, break; } - if (cond->prefix_len == 0) - break; - if (op->code == INET_DIAG_BC_S_COND) addr = entry->saddr; else addr = entry->daddr; + if (cond->family != AF_UNSPEC && + cond->family != entry->family) { + if (entry->family == AF_INET6 && + cond->family == AF_INET) { + if (addr[0] == 0 && addr[1] == 0 && + addr[2] == htonl(0xffff) && + bitstring_match(addr + 3, + cond->addr, + cond->prefix_len)) + break; + } + yes = 0; + break; + } + + if (cond->prefix_len == 0) + break; if (bitstring_match(addr, cond->addr, cond->prefix_len)) break; - if (entry->family == AF_INET6 && - cond->family == AF_INET) { - if (addr[0] == 0 && addr[1] == 0 && - addr[2] == htonl(0xffff) && - bitstring_match(addr + 3, cond->addr, - cond->prefix_len)) - break; - } yes = 0; break; } -- GitLab From f762136f85f60e7d9e8a0422f078bb187fbfc9f0 Mon Sep 17 00:00:00 2001 From: Neal Cardwell Date: Sun, 9 Dec 2012 11:09:54 +0000 Subject: [PATCH 1271/1799] inet_diag: validate port comparison byte code to prevent unsafe reads [ Upstream commit 5e1f54201cb481f40a04bc47e1bc8c093a189e23 ] Add logic to verify that a port comparison byte code operation actually has the second inet_diag_bc_op from which we read the port for such operations. Previously the code blindly referenced op[1] without first checking whether a second inet_diag_bc_op struct could fit there. So a malicious user could make the kernel read 4 bytes beyond the end of the bytecode array by claiming to have a whole port comparison byte code (2 inet_diag_bc_op structs) when in fact the bytecode was not long enough to hold both. Signed-off-by: Neal Cardwell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/inet_diag.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 8b20ca64208b..d7b862ad4be4 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -548,6 +548,17 @@ static bool valid_hostcond(const struct inet_diag_bc_op *op, int len, return true; } +/* Validate a port comparison operator. */ +static inline bool valid_port_comparison(const struct inet_diag_bc_op *op, + int len, int *min_len) +{ + /* Port comparisons put the port in a follow-on inet_diag_bc_op. */ + *min_len += sizeof(struct inet_diag_bc_op); + if (len < *min_len) + return false; + return true; +} + static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) { const void *bc = bytecode; @@ -563,24 +574,30 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) case INET_DIAG_BC_D_COND: if (!valid_hostcond(bc, len, &min_len)) return -EINVAL; - /* fall through */ - case INET_DIAG_BC_AUTO: + break; case INET_DIAG_BC_S_GE: case INET_DIAG_BC_S_LE: case INET_DIAG_BC_D_GE: case INET_DIAG_BC_D_LE: - case INET_DIAG_BC_JMP: - if (op->no < min_len || op->no > len + 4 || op->no & 3) - return -EINVAL; - if (op->no < len && - !valid_cc(bytecode, bytecode_len, len - op->no)) + if (!valid_port_comparison(bc, len, &min_len)) return -EINVAL; break; + case INET_DIAG_BC_AUTO: + case INET_DIAG_BC_JMP: case INET_DIAG_BC_NOP: break; default: return -EINVAL; } + + if (op->code != INET_DIAG_BC_NOP) { + if (op->no < min_len || op->no > len + 4 || op->no & 3) + return -EINVAL; + if (op->no < len && + !valid_cc(bytecode, bytecode_len, len - op->no)) + return -EINVAL; + } + if (op->yes < min_len || op->yes > len + 4 || op->yes & 3) return -EINVAL; bc += op->yes; -- GitLab From 0752c77c0f04ac2649d5175fbc25dd3c5d414870 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 6 Dec 2012 21:55:16 -0600 Subject: [PATCH 1272/1799] b43legacy: Fix firmware loading when driver is built into the kernel commit 576d28a7c73013717311cfcb514dbcae27c82eeb upstream. Recent versions of udev cause synchronous firmware loading from the probe routine to fail because the request to user space times out. The original fix for b43legacy (commit a3ea2c7) moved the firmware load from the probe routine to a work queue, but it still used synchronous firmware loading. This method is OK when b43legacy is built as a module; however, it fails when the driver is compiled into the kernel. This version changes the code to load the initial firmware file using request_firmware_nowait(). A completion event is used to hold the work queue until that file is available. The remaining firmware files are read synchronously. Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/b43legacy/b43legacy.h | 5 +++ drivers/net/wireless/b43legacy/main.c | 37 ++++++++++++++++++---- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index a29da674e69d..482476fdb1f3 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -13,6 +13,7 @@ #include #include +#include #include @@ -733,6 +734,10 @@ struct b43legacy_wldev { /* Firmware data */ struct b43legacy_firmware fw; + const struct firmware *fwp; /* needed to pass fw pointer */ + + /* completion struct for firmware loading */ + struct completion fw_load_complete; /* Devicelist in struct b43legacy_wl (all 802.11 cores) */ struct list_head list; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 0f30c07e9198..53696efbe155 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -1511,9 +1511,17 @@ static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl) "and download the correct firmware (version 3).\n"); } +static void b43legacy_fw_cb(const struct firmware *firmware, void *context) +{ + struct b43legacy_wldev *dev = context; + + dev->fwp = firmware; + complete(&dev->fw_load_complete); +} + static int do_request_fw(struct b43legacy_wldev *dev, const char *name, - const struct firmware **fw) + const struct firmware **fw, bool async) { char path[sizeof(modparam_fwpostfix) + 32]; struct b43legacy_fw_header *hdr; @@ -1526,7 +1534,24 @@ static int do_request_fw(struct b43legacy_wldev *dev, snprintf(path, ARRAY_SIZE(path), "b43legacy%s/%s.fw", modparam_fwpostfix, name); - err = request_firmware(fw, path, dev->dev->dev); + b43legacyinfo(dev->wl, "Loading firmware %s\n", path); + if (async) { + init_completion(&dev->fw_load_complete); + err = request_firmware_nowait(THIS_MODULE, 1, path, + dev->dev->dev, GFP_KERNEL, + dev, b43legacy_fw_cb); + if (err) { + b43legacyerr(dev->wl, "Unable to load firmware\n"); + return err; + } + /* stall here until fw ready */ + wait_for_completion(&dev->fw_load_complete); + if (!dev->fwp) + err = -EINVAL; + *fw = dev->fwp; + } else { + err = request_firmware(fw, path, dev->dev->dev); + } if (err) { b43legacyerr(dev->wl, "Firmware file \"%s\" not found " "or load failed.\n", path); @@ -1578,7 +1603,7 @@ static void b43legacy_request_firmware(struct work_struct *work) filename = "ucode4"; else filename = "ucode5"; - err = do_request_fw(dev, filename, &fw->ucode); + err = do_request_fw(dev, filename, &fw->ucode, true); if (err) goto err_load; } @@ -1587,7 +1612,7 @@ static void b43legacy_request_firmware(struct work_struct *work) filename = "pcm4"; else filename = "pcm5"; - err = do_request_fw(dev, filename, &fw->pcm); + err = do_request_fw(dev, filename, &fw->pcm, false); if (err) goto err_load; } @@ -1605,7 +1630,7 @@ static void b43legacy_request_firmware(struct work_struct *work) default: goto err_no_initvals; } - err = do_request_fw(dev, filename, &fw->initvals); + err = do_request_fw(dev, filename, &fw->initvals, false); if (err) goto err_load; } @@ -1625,7 +1650,7 @@ static void b43legacy_request_firmware(struct work_struct *work) default: goto err_no_initvals; } - err = do_request_fw(dev, filename, &fw->initvals_band); + err = do_request_fw(dev, filename, &fw->initvals_band, false); if (err) goto err_load; } -- GitLab From 6afc22ba722253aafc389264edc7134e73700e60 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 10 Dec 2012 17:40:21 +0100 Subject: [PATCH 1273/1799] b43: fix tx path skb leaks commit 78f18df4b323d2ac14d6c82e2fc3c8dc4556bccc upstream. ieee80211_free_txskb() needs to be used instead of dev_kfree_skb_any for tx packets passed to the driver from mac80211 Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/b43/dma.c | 7 +++++-- drivers/net/wireless/b43/main.c | 12 ++++++++---- drivers/net/wireless/b43/pio.c | 4 ++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index b5f1b91002bb..65f831faf2af 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -409,7 +409,10 @@ static inline struct b43_dmadesc_meta *meta) { if (meta->skb) { - dev_kfree_skb_any(meta->skb); + if (ring->tx) + ieee80211_free_txskb(ring->dev->wl->hw, meta->skb); + else + dev_kfree_skb_any(meta->skb); meta->skb = NULL; } } @@ -1454,7 +1457,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) if (unlikely(err == -ENOKEY)) { /* Drop this packet, as we don't have the encryption key * anymore and must not transmit it unencrypted. */ - dev_kfree_skb_any(skb); + ieee80211_free_txskb(dev->wl->hw, skb); err = 0; goto out; } diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index d6ffd434f413..4e465c5b2df7 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3393,7 +3393,7 @@ static void b43_tx_work(struct work_struct *work) break; } if (unlikely(err)) - dev_kfree_skb(skb); /* Drop it */ + ieee80211_free_txskb(wl->hw, skb); err = 0; } @@ -3414,7 +3414,7 @@ static void b43_op_tx(struct ieee80211_hw *hw, if (unlikely(skb->len < 2 + 2 + 6)) { /* Too short, this can't be a valid frame. */ - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); return; } B43_WARN_ON(skb_shinfo(skb)->nr_frags); @@ -4210,8 +4210,12 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev) /* Drain all TX queues. */ for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) { - while (skb_queue_len(&wl->tx_queue[queue_num])) - dev_kfree_skb(skb_dequeue(&wl->tx_queue[queue_num])); + while (skb_queue_len(&wl->tx_queue[queue_num])) { + struct sk_buff *skb; + + skb = skb_dequeue(&wl->tx_queue[queue_num]); + ieee80211_free_txskb(wl->hw, skb); + } } b43_mac_suspend(dev); diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 3533ab86bd36..a73ff8c9deb5 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -196,7 +196,7 @@ static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q) for (i = 0; i < ARRAY_SIZE(q->packets); i++) { pack = &(q->packets[i]); if (pack->skb) { - dev_kfree_skb_any(pack->skb); + ieee80211_free_txskb(q->dev->wl->hw, pack->skb); pack->skb = NULL; } } @@ -552,7 +552,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) if (unlikely(err == -ENOKEY)) { /* Drop this packet, as we don't have the encryption key * anymore and must not transmit it unencrypted. */ - dev_kfree_skb_any(skb); + ieee80211_free_txskb(dev->wl->hw, skb); err = 0; goto out; } -- GitLab From 745a4b9a8bedb82d56e23a2e14452ab71df9cf60 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 7 Dec 2012 23:11:14 +0100 Subject: [PATCH 1274/1799] pnpacpi: fix incorrect TEST_ALPHA() test commit cdc87c5a30f407ed1ce43d8a22261116873d5ef1 upstream. TEST_ALPHA() is broken and always returns 0. [akpm@linux-foundation.org: return false for '@' as well, per Bjorn] Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/pnp/pnpacpi/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index e3537888db7e..291906e8e9a9 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -58,7 +58,7 @@ static inline int __init is_exclusive_device(struct acpi_device *dev) if (!(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'F'))) \ return 0 #define TEST_ALPHA(c) \ - if (!('@' <= (c) || (c) <= 'Z')) \ + if (!('A' <= (c) && (c) <= 'Z')) \ return 0 static int __init ispnpidacpi(const char *id) { -- GitLab From 5a76bf41fe85c0ebdf4fe1fcdf729697b11a5338 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Thu, 20 Dec 2012 15:05:50 -0800 Subject: [PATCH 1275/1799] SGI-XP: handle non-fatal traps commit 891348ca0f66206f1dc0e30d63757e3df1ae2d15 upstream. We found a user code which was raising a divide-by-zero trap. That trap would lead to XPC connections between system-partitions being torn down due to the die_chain notifier callouts it received. This also revealed a different issue where multiple callers into xpc_die_deactivate() would all attempt to do the disconnect in parallel which would sometimes lock up but often overwhelm the console on very large machines as each would print at least one line of output at the end of the deactivate. I reviewed all the users of the die_chain notifier and changed the code to ignore the notifier callouts for reasons which will not actually lead to a system to continue on to call die(). [akpm@linux-foundation.org: fix ia64] Signed-off-by: Robin Holt Cc: Thomas Gleixner Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/misc/sgi-xp/xpc_main.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 8d082b46426b..d971817182f7 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c @@ -53,6 +53,10 @@ #include #include "xpc.h" +#ifdef CONFIG_X86_64 +#include +#endif + /* define two XPC debug device structures to be used with dev_dbg() et al */ struct device_driver xpc_dbg_name = { @@ -1079,6 +1083,9 @@ xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) return NOTIFY_DONE; } +/* Used to only allow one cpu to complete disconnect */ +static unsigned int xpc_die_disconnecting; + /* * Notify other partitions to deactivate from us by first disengaging from all * references to our memory. @@ -1092,6 +1099,9 @@ xpc_die_deactivate(void) long keep_waiting; long wait_to_print; + if (cmpxchg(&xpc_die_disconnecting, 0, 1)) + return; + /* keep xpc_hb_checker thread from doing anything (just in case) */ xpc_exiting = 1; @@ -1159,7 +1169,7 @@ xpc_die_deactivate(void) * about the lack of a heartbeat. */ static int -xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) +xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args) { #ifdef CONFIG_IA64 /* !!! temporary kludge */ switch (event) { @@ -1191,7 +1201,27 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) break; } #else - xpc_die_deactivate(); + struct die_args *die_args = _die_args; + + switch (event) { + case DIE_TRAP: + if (die_args->trapnr == X86_TRAP_DF) + xpc_die_deactivate(); + + if (((die_args->trapnr == X86_TRAP_MF) || + (die_args->trapnr == X86_TRAP_XF)) && + !user_mode_vm(die_args->regs)) + xpc_die_deactivate(); + + break; + case DIE_INT3: + case DIE_DEBUG: + break; + case DIE_OOPS: + case DIE_GPF: + default: + xpc_die_deactivate(); + } #endif return NOTIFY_DONE; -- GitLab From 7361a9019ff8d45dc835f987ccefbbeb4f560f09 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 20 Dec 2012 15:05:16 -0800 Subject: [PATCH 1276/1799] exec: do not leave bprm->interp on stack commit b66c5984017533316fd1951770302649baf1aa33 upstream. If a series of scripts are executed, each triggering module loading via unprintable bytes in the script header, kernel stack contents can leak into the command line. Normally execution of binfmt_script and binfmt_misc happens recursively. However, when modules are enabled, and unprintable bytes exist in the bprm->buf, execution will restart after attempting to load matching binfmt modules. Unfortunately, the logic in binfmt_script and binfmt_misc does not expect to get restarted. They leave bprm->interp pointing to their local stack. This means on restart bprm->interp is left pointing into unused stack memory which can then be copied into the userspace argv areas. After additional study, it seems that both recursion and restart remains the desirable way to handle exec with scripts, misc, and modules. As such, we need to protect the changes to interp. This changes the logic to require allocation for any changes to the bprm->interp. To avoid adding a new kmalloc to every exec, the default value is left as-is. Only when passing through binfmt_script or binfmt_misc does an allocation take place. For a proof of concept, see DoTest.sh from: http://www.halfdog.net/Security/2012/LinuxKernelBinfmtScriptStackDataDisclosure/ Signed-off-by: Kees Cook Cc: halfdog Cc: P J P Cc: Alexander Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/binfmt_misc.c | 5 ++++- fs/binfmt_script.c | 4 +++- fs/exec.c | 15 +++++++++++++++ include/linux/binfmts.h | 1 + 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 613aa0618235..e1724392d050 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -176,7 +176,10 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) goto _error; bprm->argc ++; - bprm->interp = iname; /* for binfmt_script */ + /* Update interp in case binfmt_script needs it. */ + retval = bprm_change_interp(iname, bprm); + if (retval < 0) + goto _error; interp_file = open_exec (iname); retval = PTR_ERR (interp_file); diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index d3b8c1f63155..df49d486b0c0 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c @@ -82,7 +82,9 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) retval = copy_strings_kernel(1, &i_name, bprm); if (retval) return retval; bprm->argc++; - bprm->interp = interp; + retval = bprm_change_interp(interp, bprm); + if (retval < 0) + return retval; /* * OK, now restart the process with the interpreter's dentry. diff --git a/fs/exec.c b/fs/exec.c index 6c4791d4634a..51d862973639 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1206,9 +1206,24 @@ void free_bprm(struct linux_binprm *bprm) mutex_unlock(¤t->signal->cred_guard_mutex); abort_creds(bprm->cred); } + /* If a binfmt changed the interp, free it. */ + if (bprm->interp != bprm->filename) + kfree(bprm->interp); kfree(bprm); } +int bprm_change_interp(char *interp, struct linux_binprm *bprm) +{ + /* If a binfmt changed the interp, free it first. */ + if (bprm->interp != bprm->filename) + kfree(bprm->interp); + bprm->interp = kstrdup(interp, GFP_KERNEL); + if (!bprm->interp) + return -ENOMEM; + return 0; +} +EXPORT_SYMBOL(bprm_change_interp); + /* * install the new credentials for this executable */ diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 366422bc1633..eb53e15ede68 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -128,6 +128,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm, unsigned long stack_top, int executable_stack); extern int bprm_mm_init(struct linux_binprm *bprm); +extern int bprm_change_interp(char *interp, struct linux_binprm *bprm); extern int copy_strings_kernel(int argc, const char *const *argv, struct linux_binprm *bprm); extern int prepare_bprm_creds(struct linux_binprm *bprm); -- GitLab From 4511ba021ea5ee7f2b76d954fc23c3814ac07cba Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Tue, 11 Dec 2012 22:18:05 +0100 Subject: [PATCH 1277/1799] x86, 8042: Enable A20 using KBC to fix S3 resume on some MSI laptops commit ad68652412276f68ad4fe3e1ecf5ee6880876783 upstream. Some MSI laptop BIOSes are broken - INT 15h code uses port 92h to enable A20 line but resume code assumes that KBC was used. The laptop will not resume from S3 otherwise but powers off after a while and then powers on again stuck with a blank screen. Fix it by enabling A20 using KBC in i8042_platform_init for x86. Fixes https://bugzilla.kernel.org/show_bug.cgi?id=12878 Signed-off-by: Ondrej Zary Cc: Dmitry Torokhov Cc: Alan Cox Cc: Rafael J. Wysocki Link: http://lkml.kernel.org/r/201212112218.06551.linux@rainbow-software.org Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- drivers/input/serio/i8042-x86ia64io.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index d6cc77a53c7e..5f306f79da0c 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -921,6 +921,7 @@ static int __init i8042_platform_init(void) int retval; #ifdef CONFIG_X86 + u8 a20_on = 0xdf; /* Just return if pre-detection shows no i8042 controller exist */ if (!x86_platform.i8042_detect()) return -ENODEV; @@ -960,6 +961,14 @@ static int __init i8042_platform_init(void) if (dmi_check_system(i8042_dmi_dritek_table)) i8042_dritek = true; + + /* + * A20 was already enabled during early kernel init. But some buggy + * BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to + * resume from S3. So we do it here and hope that nothing breaks. + */ + i8042_command(&a20_on, 0x10d1); + i8042_command(NULL, 0x00ff); /* Null command for SMM firmware */ #endif /* CONFIG_X86 */ return retval; -- GitLab From 6cb6a94380506d9e5491b8e145811bd676ce6f3d Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 19 Oct 2012 14:03:33 +0100 Subject: [PATCH 1278/1799] virtio: force vring descriptors to be allocated from lowmem commit b92b1b89a33c172c075edccf6afb0edc41d851fd upstream. Virtio devices may attempt to add descriptors to a virtqueue from atomic context using GFP_ATOMIC allocation. This is problematic because such allocations can fall outside of the lowmem mapping, causing virt_to_phys to report bogus physical addresses which are subsequently passed to userspace via the buffers for the virtual device. This patch masks out __GFP_HIGH and __GFP_HIGHMEM from the requested flags when allocating descriptors for a virtqueue. If an atomic allocation is requested and later fails, we will return -ENOSPC which will be handled by the driver. Signed-off-by: Will Deacon Cc: Sasha Levin Signed-off-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- drivers/virtio/virtio_ring.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 5aa43c3392a2..52bfd0786fc8 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -132,6 +132,13 @@ static int vring_add_indirect(struct vring_virtqueue *vq, unsigned head; int i; + /* + * We require lowmem mappings for the descriptors because + * otherwise virt_to_phys will give us bogus addresses in the + * virtqueue. + */ + gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH); + desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp); if (!desc) return -ENOMEM; -- GitLab From 711cf004f2148f1d1967bc5eca025019e5001212 Mon Sep 17 00:00:00 2001 From: Sonny Rao Date: Thu, 20 Dec 2012 15:05:07 -0800 Subject: [PATCH 1279/1799] mm: fix calculation of dirtyable memory commit c8b74c2f6604923de91f8aa6539f8bb934736754 upstream. The system uses global_dirtyable_memory() to calculate number of dirtyable pages/pages that can be allocated to the page cache. A bug causes an underflow thus making the page count look like a big unsigned number. This in turn confuses the dirty writeback throttling to aggressively write back pages as they become dirty (usually 1 page at a time). This generally only affects systems with highmem because the underflowed count gets subtracted from the global count of dirtyable memory. The problem was introduced with v3.2-4896-gab8fabd Fix is to ensure we don't get an underflowed total of either highmem or global dirtyable memory. Signed-off-by: Sonny Rao Signed-off-by: Puneet Kumar Acked-by: Johannes Weiner Tested-by: Damien Wyart Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/page-writeback.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 26adea8ca2e7..bc8465f579a8 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -186,6 +186,18 @@ static unsigned long highmem_dirtyable_memory(unsigned long total) x += zone_page_state(z, NR_FREE_PAGES) + zone_reclaimable_pages(z) - z->dirty_balance_reserve; } + /* + * Unreclaimable memory (kernel memory or anonymous memory + * without swap) can bring down the dirtyable pages below + * the zone's dirty balance reserve and the above calculation + * will underflow. However we still want to add in nodes + * which are below threshold (negative values) to get a more + * accurate calculation but make sure that the total never + * underflows. + */ + if ((long)x < 0) + x = 0; + /* * Make sure that the number of highmem pages is never larger * than the number of the total dirtyable memory. This can only @@ -208,8 +220,8 @@ unsigned long global_dirtyable_memory(void) { unsigned long x; - x = global_page_state(NR_FREE_PAGES) + global_reclaimable_pages() - - dirty_balance_reserve; + x = global_page_state(NR_FREE_PAGES) + global_reclaimable_pages(); + x -= min(x, dirty_balance_reserve); if (!vm_highmem_is_dirtyable) x -= highmem_dirtyable_memory(x); @@ -276,9 +288,12 @@ static unsigned long zone_dirtyable_memory(struct zone *zone) * highmem zone can hold its share of dirty pages, so we don't * care about vm_highmem_is_dirtyable here. */ - return zone_page_state(zone, NR_FREE_PAGES) + - zone_reclaimable_pages(zone) - - zone->dirty_balance_reserve; + unsigned long nr_pages = zone_page_state(zone, NR_FREE_PAGES) + + zone_reclaimable_pages(zone); + + /* don't allow this to underflow */ + nr_pages -= min(nr_pages, zone->dirty_balance_reserve); + return nr_pages; } /** -- GitLab From 25747cc45825ffc0192779a224d3bb9bc4b9edbd Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Fri, 21 Dec 2012 13:03:50 -0500 Subject: [PATCH 1280/1799] mm: Fix PageHead when !CONFIG_PAGEFLAGS_EXTENDED commit ad4b3fb7ff9940bcdb1e4cd62bd189d10fa636ba upstream. Unfortunately with !CONFIG_PAGEFLAGS_EXTENDED, (!PageHead) is false, and (PageHead) is true, for tail pages. If this is indeed the intended behavior, which I doubt because it breaks cache cleaning on some ARM systems, then the nomenclature is highly problematic. This patch makes sure PageHead is only true for head pages and PageTail is only true for tail pages, and neither is true for non-compound pages. [ This buglet seems ancient - seems to have been introduced back in Apr 2008 in commit 6a1e7f777f61: "pageflags: convert to the use of new macros". And the reason nobody noticed is because the PageHead() tests are almost all about just sanity-checking, and only used on pages that are actual page heads. The fact that the old code returned true for tail pages too was thus not really noticeable. - Linus ] Signed-off-by: Christoffer Dall Acked-by: Andrea Arcangeli Cc: Andrew Morton Cc: Will Deacon Cc: Steve Capper Cc: Christoph Lameter Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/page-flags.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index c88d2a9451af..4dabf0fe527e 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -361,7 +361,7 @@ static inline void ClearPageCompound(struct page *page) * pages on the LRU and/or pagecache. */ TESTPAGEFLAG(Compound, compound) -__PAGEFLAG(Head, compound) +__SETPAGEFLAG(Head, compound) __CLEARPAGEFLAG(Head, compound) /* * PG_reclaim is used in combination with PG_compound to mark the @@ -373,8 +373,14 @@ __PAGEFLAG(Head, compound) * PG_compound & PG_reclaim => Tail page * PG_compound & ~PG_reclaim => Head page */ +#define PG_head_mask ((1L << PG_compound)) #define PG_head_tail_mask ((1L << PG_compound) | (1L << PG_reclaim)) +static inline int PageHead(struct page *page) +{ + return ((page->flags & PG_head_tail_mask) == PG_head_mask); +} + static inline int PageTail(struct page *page) { return ((page->flags & PG_head_tail_mask) == PG_head_tail_mask); -- GitLab From 6718272b115afbf5d80ea1e0a4d18f9fcb32351f Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 2 Jan 2013 02:01:33 -0800 Subject: [PATCH 1281/1799] tmpfs mempolicy: fix /proc/mounts corrupting memory commit f2a07f40dbc603c15f8b06e6ec7f768af67b424f upstream. Recently I suggested using "mount -o remount,mpol=local /tmp" in NUMA mempolicy testing. Very nasty. Reading /proc/mounts, /proc/pid/mounts or /proc/pid/mountinfo may then corrupt one bit of kernel memory, often in a page table (causing "Bad swap" or "Bad page map" warning or "Bad pagetable" oops), sometimes in a vm_area_struct or rbnode or somewhere worse. "mpol=prefer" and "mpol=prefer:Node" are equally toxic. Recent NUMA enhancements are not to blame: this dates back to 2.6.35, when commit e17f74af351c "mempolicy: don't call mpol_set_nodemask() when no_context" skipped mpol_parse_str()'s call to mpol_set_nodemask(), which used to initialize v.preferred_node, or set MPOL_F_LOCAL in flags. With slab poisoning, you can then rely on mpol_to_str() to set the bit for node 0x6b6b, probably in the next page above the caller's stack. mpol_parse_str() is only called from shmem_parse_options(): no_context is always true, so call it unused for now, and remove !no_context code. Set v.nodes or v.preferred_node or MPOL_F_LOCAL as mpol_to_str() might expect. Then mpol_to_str() can ignore its no_context argument also, the mpol being appropriately initialized whether contextualized or not. Rename its no_context unused too, and let subsequent patch remove them (that's not needed for stable backporting, which would involve rejects). I don't understand why MPOL_LOCAL is described as a pseudo-policy: it's a reasonable policy which suffers from a confusing implementation in terms of MPOL_PREFERRED with MPOL_F_LOCAL. I believe this would be much more robust if MPOL_LOCAL were recognized in switch statements throughout, MPOL_F_LOCAL deleted, and MPOL_PREFERRED use the (possibly empty) nodes mask like everyone else, instead of its preferred_node variant (I presume an optimization from the days before MPOL_LOCAL). But that would take me too long to get right and fully tested. Signed-off-by: Hugh Dickins Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mempolicy.c | 64 ++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 458dedef9ee5..82f1b027ba1c 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2344,8 +2344,7 @@ void numa_default_policy(void) */ /* - * "local" is pseudo-policy: MPOL_PREFERRED with MPOL_F_LOCAL flag - * Used only for mpol_parse_str() and mpol_to_str() + * "local" is implemented internally by MPOL_PREFERRED with MPOL_F_LOCAL flag. */ #define MPOL_LOCAL MPOL_MAX static const char * const policy_modes[] = @@ -2360,28 +2359,21 @@ static const char * const policy_modes[] = #ifdef CONFIG_TMPFS /** - * mpol_parse_str - parse string to mempolicy + * mpol_parse_str - parse string to mempolicy, for tmpfs mpol mount option. * @str: string containing mempolicy to parse * @mpol: pointer to struct mempolicy pointer, returned on success. - * @no_context: flag whether to "contextualize" the mempolicy + * @unused: redundant argument, to be removed later. * * Format of input: * [=][:] * - * if @no_context is true, save the input nodemask in w.user_nodemask in - * the returned mempolicy. This will be used to "clone" the mempolicy in - * a specific context [cpuset] at a later time. Used to parse tmpfs mpol - * mount option. Note that if 'static' or 'relative' mode flags were - * specified, the input nodemask will already have been saved. Saving - * it again is redundant, but safe. - * * On success, returns 0, else 1 */ -int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context) +int mpol_parse_str(char *str, struct mempolicy **mpol, int unused) { struct mempolicy *new = NULL; unsigned short mode; - unsigned short uninitialized_var(mode_flags); + unsigned short mode_flags; nodemask_t nodes; char *nodelist = strchr(str, ':'); char *flags = strchr(str, '='); @@ -2469,24 +2461,23 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context) if (IS_ERR(new)) goto out; - if (no_context) { - /* save for contextualization */ - new->w.user_nodemask = nodes; - } else { - int ret; - NODEMASK_SCRATCH(scratch); - if (scratch) { - task_lock(current); - ret = mpol_set_nodemask(new, &nodes, scratch); - task_unlock(current); - } else - ret = -ENOMEM; - NODEMASK_SCRATCH_FREE(scratch); - if (ret) { - mpol_put(new); - goto out; - } - } + /* + * Save nodes for mpol_to_str() to show the tmpfs mount options + * for /proc/mounts, /proc/pid/mounts and /proc/pid/mountinfo. + */ + if (mode != MPOL_PREFERRED) + new->v.nodes = nodes; + else if (nodelist) + new->v.preferred_node = first_node(nodes); + else + new->flags |= MPOL_F_LOCAL; + + /* + * Save nodes for contextualization: this will be used to "clone" + * the mempolicy in a specific context [cpuset] at a later time. + */ + new->w.user_nodemask = nodes; + err = 0; out: @@ -2506,13 +2497,13 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context) * @buffer: to contain formatted mempolicy string * @maxlen: length of @buffer * @pol: pointer to mempolicy to be formatted - * @no_context: "context free" mempolicy - use nodemask in w.user_nodemask + * @unused: redundant argument, to be removed later. * * Convert a mempolicy into a string. * Returns the number of characters in buffer (if positive) * or an error (negative) */ -int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context) +int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int unused) { char *p = buffer; int l; @@ -2538,7 +2529,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context) case MPOL_PREFERRED: nodes_clear(nodes); if (flags & MPOL_F_LOCAL) - mode = MPOL_LOCAL; /* pseudo-policy */ + mode = MPOL_LOCAL; else node_set(pol->v.preferred_node, nodes); break; @@ -2546,10 +2537,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context) case MPOL_BIND: /* Fall through */ case MPOL_INTERLEAVE: - if (no_context) - nodes = pol->w.user_nodemask; - else - nodes = pol->v.nodes; + nodes = pol->v.nodes; break; default: -- GitLab From 929cfe920d276f8d09b89c83f4ee0c721652d921 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 3 Dec 2012 11:12:46 +0100 Subject: [PATCH 1282/1799] ALSA: usb-audio: Avoid autopm calls after disconnection commit 59866da9e4ae54819e3c4e0a8f426bdb0c2ef993 upstream. Add a similar protection against the disconnection race and the invalid use of usb instance after disconnection, as well as we've done for the USB audio PCM. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=51201 Reviewd-by: Clemens Ladisch Tested-by: Clemens Ladisch Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/midi.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/sound/usb/midi.c b/sound/usb/midi.c index eeefbce3873c..c0054ee9389b 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -116,6 +116,7 @@ struct snd_usb_midi { struct list_head list; struct timer_list error_timer; spinlock_t disc_lock; + struct rw_semaphore disc_rwsem; struct mutex mutex; u32 usb_id; int next_midi_device; @@ -1038,6 +1039,12 @@ static void substream_open(struct snd_rawmidi_substream *substream, int open) struct snd_usb_midi* umidi = substream->rmidi->private_data; struct snd_kcontrol *ctl; + down_read(&umidi->disc_rwsem); + if (umidi->disconnected) { + up_read(&umidi->disc_rwsem); + return; + } + mutex_lock(&umidi->mutex); if (open) { if (umidi->opened++ == 0 && umidi->roland_load_ctl) { @@ -1056,6 +1063,7 @@ static void substream_open(struct snd_rawmidi_substream *substream, int open) } } mutex_unlock(&umidi->mutex); + up_read(&umidi->disc_rwsem); } static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) @@ -1076,8 +1084,15 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) snd_BUG(); return -ENXIO; } + + down_read(&umidi->disc_rwsem); + if (umidi->disconnected) { + up_read(&umidi->disc_rwsem); + return -ENODEV; + } err = usb_autopm_get_interface(umidi->iface); port->autopm_reference = err >= 0; + up_read(&umidi->disc_rwsem); if (err < 0 && err != -EACCES) return -EIO; substream->runtime->private_data = port; @@ -1092,8 +1107,10 @@ static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) struct usbmidi_out_port *port = substream->runtime->private_data; substream_open(substream, 0); - if (port->autopm_reference) + down_read(&umidi->disc_rwsem); + if (!umidi->disconnected && port->autopm_reference) usb_autopm_put_interface(umidi->iface); + up_read(&umidi->disc_rwsem); return 0; } @@ -1403,9 +1420,12 @@ void snd_usbmidi_disconnect(struct list_head* p) * a timer may submit an URB. To reliably break the cycle * a flag under lock must be used */ + down_write(&umidi->disc_rwsem); spin_lock_irq(&umidi->disc_lock); umidi->disconnected = 1; spin_unlock_irq(&umidi->disc_lock); + up_write(&umidi->disc_rwsem); + for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; if (ep->out) @@ -2117,6 +2137,7 @@ int snd_usbmidi_create(struct snd_card *card, umidi->usb_protocol_ops = &snd_usbmidi_standard_ops; init_timer(&umidi->error_timer); spin_lock_init(&umidi->disc_lock); + init_rwsem(&umidi->disc_rwsem); mutex_init(&umidi->mutex); umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor), le16_to_cpu(umidi->dev->descriptor.idProduct)); -- GitLab From 740ccbaa57110e49f2296c4c610d745baaecc530 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 3 Dec 2012 11:30:50 +0100 Subject: [PATCH 1283/1799] ALSA: usb-audio: Fix missing autopm for MIDI input commit f5f165418cabf2218eb466c0e94693b8b1aee88b upstream. The commit [88a8516a: ALSA: usbaudio: implement USB autosuspend] added the support of autopm for USB MIDI output, but it didn't take the MIDI input into account. This patch adds the following for fixing the autopm: - Manage the URB start at the first MIDI input stream open, instead of the time of instance creation - Move autopm code to the common substream_open() - Make snd_usbmidi_input_start/_stop() more robust and add the running state check Reviewd-by: Clemens Ladisch Tested-by: Clemens Ladisch Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/midi.c | 88 +++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/sound/usb/midi.c b/sound/usb/midi.c index c0054ee9389b..34b9bb7fe87c 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -126,8 +126,10 @@ struct snd_usb_midi { struct snd_usb_midi_in_endpoint *in; } endpoints[MIDI_MAX_ENDPOINTS]; unsigned long input_triggered; - unsigned int opened; + bool autopm_reference; + unsigned int opened[2]; unsigned char disconnected; + unsigned char input_running; struct snd_kcontrol *roland_load_ctl; }; @@ -149,7 +151,6 @@ struct snd_usb_midi_out_endpoint { struct snd_usb_midi_out_endpoint* ep; struct snd_rawmidi_substream *substream; int active; - bool autopm_reference; uint8_t cable; /* cable number << 4 */ uint8_t state; #define STATE_UNKNOWN 0 @@ -1034,36 +1035,58 @@ static void update_roland_altsetting(struct snd_usb_midi* umidi) snd_usbmidi_input_start(&umidi->list); } -static void substream_open(struct snd_rawmidi_substream *substream, int open) +static int substream_open(struct snd_rawmidi_substream *substream, int dir, + int open) { struct snd_usb_midi* umidi = substream->rmidi->private_data; struct snd_kcontrol *ctl; + int err; down_read(&umidi->disc_rwsem); if (umidi->disconnected) { up_read(&umidi->disc_rwsem); - return; + return open ? -ENODEV : 0; } mutex_lock(&umidi->mutex); if (open) { - if (umidi->opened++ == 0 && umidi->roland_load_ctl) { - ctl = umidi->roland_load_ctl; - ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(umidi->card, + if (!umidi->opened[0] && !umidi->opened[1]) { + err = usb_autopm_get_interface(umidi->iface); + umidi->autopm_reference = err >= 0; + if (err < 0 && err != -EACCES) { + mutex_unlock(&umidi->mutex); + up_read(&umidi->disc_rwsem); + return -EIO; + } + if (umidi->roland_load_ctl) { + ctl = umidi->roland_load_ctl; + ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; + snd_ctl_notify(umidi->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); - update_roland_altsetting(umidi); + update_roland_altsetting(umidi); + } } + umidi->opened[dir]++; + if (umidi->opened[1]) + snd_usbmidi_input_start(&umidi->list); } else { - if (--umidi->opened == 0 && umidi->roland_load_ctl) { - ctl = umidi->roland_load_ctl; - ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(umidi->card, + umidi->opened[dir]--; + if (!umidi->opened[1]) + snd_usbmidi_input_stop(&umidi->list); + if (!umidi->opened[0] && !umidi->opened[1]) { + if (umidi->roland_load_ctl) { + ctl = umidi->roland_load_ctl; + ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; + snd_ctl_notify(umidi->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); + } + if (umidi->autopm_reference) + usb_autopm_put_interface(umidi->iface); } } mutex_unlock(&umidi->mutex); up_read(&umidi->disc_rwsem); + return 0; } static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) @@ -1071,7 +1094,6 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) struct snd_usb_midi* umidi = substream->rmidi->private_data; struct usbmidi_out_port* port = NULL; int i, j; - int err; for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) if (umidi->endpoints[i].out) @@ -1085,33 +1107,14 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) return -ENXIO; } - down_read(&umidi->disc_rwsem); - if (umidi->disconnected) { - up_read(&umidi->disc_rwsem); - return -ENODEV; - } - err = usb_autopm_get_interface(umidi->iface); - port->autopm_reference = err >= 0; - up_read(&umidi->disc_rwsem); - if (err < 0 && err != -EACCES) - return -EIO; substream->runtime->private_data = port; port->state = STATE_UNKNOWN; - substream_open(substream, 1); - return 0; + return substream_open(substream, 0, 1); } static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) { - struct snd_usb_midi* umidi = substream->rmidi->private_data; - struct usbmidi_out_port *port = substream->runtime->private_data; - - substream_open(substream, 0); - down_read(&umidi->disc_rwsem); - if (!umidi->disconnected && port->autopm_reference) - usb_autopm_put_interface(umidi->iface); - up_read(&umidi->disc_rwsem); - return 0; + return substream_open(substream, 0, 0); } static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream, int up) @@ -1164,14 +1167,12 @@ static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream) static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream) { - substream_open(substream, 1); - return 0; + return substream_open(substream, 1, 1); } static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream) { - substream_open(substream, 0); - return 0; + return substream_open(substream, 1, 0); } static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) @@ -2080,12 +2081,15 @@ void snd_usbmidi_input_stop(struct list_head* p) unsigned int i, j; umidi = list_entry(p, struct snd_usb_midi, list); + if (!umidi->input_running) + return; for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; if (ep->in) for (j = 0; j < INPUT_URBS; ++j) usb_kill_urb(ep->in->urbs[j]); } + umidi->input_running = 0; } static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep) @@ -2110,8 +2114,11 @@ void snd_usbmidi_input_start(struct list_head* p) int i; umidi = list_entry(p, struct snd_usb_midi, list); + if (umidi->input_running || !umidi->opened[1]) + return; for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) snd_usbmidi_input_start_ep(umidi->endpoints[i].in); + umidi->input_running = 1; } /* @@ -2250,9 +2257,6 @@ int snd_usbmidi_create(struct snd_card *card, } list_add_tail(&umidi->list, midi_list); - - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) - snd_usbmidi_input_start_ep(umidi->endpoints[i].in); return 0; } -- GitLab From 37cb3a0366a60bca8f0bb4123639404c36402f70 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Dec 2012 20:06:49 +0100 Subject: [PATCH 1284/1799] ALSA: hda - Fix the wrong pincaps set in ALC861VD dallas/hp fixup commit b78562b10fa66175e30b76073e32a0ad8d92aa83 upstream. The workaround to force VREF50 for dallas/hp model with ALC861VD was introduced in commit 8fdcb6fe4204bdb4c6991652717ab5063751414e, but it contained wrong pincap override bits. This patch fixes to exclude VREF80 pincap bit correctly. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 29774e22bdad..7f2a10901ae4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6520,8 +6520,8 @@ static void alc861vd_fixup_dallas(struct hda_codec *codec, const struct alc_fixup *fix, int action) { if (action == ALC_FIXUP_ACT_PRE_PROBE) { - snd_hda_override_pin_caps(codec, 0x18, 0x00001714); - snd_hda_override_pin_caps(codec, 0x19, 0x0000171c); + snd_hda_override_pin_caps(codec, 0x18, 0x00000734); + snd_hda_override_pin_caps(codec, 0x19, 0x0000073c); } } -- GitLab From 73396089a501bdaa98a70efbd358c29daa7af0d9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 13 Dec 2012 14:33:42 +0100 Subject: [PATCH 1285/1799] ALSA: hda - Fix pin configuration of HP Pavilion dv7 commit 8ae5865ec77c22462c736846a0679947a6953548 upstream. Fix the quirk entry for HP Pavilion dv7 in order to make the bass speaker working. Reported-and-tested-by: Tomas Pospisek Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- 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 04cd44fa2248..137b67f8e69a 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1695,7 +1695,7 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1658, "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1659, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), + "HP Pavilion dv7", STAC_HP_DV7_4000), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165A, "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165B, -- GitLab From a86cd75b2fd681c71dd4a04877bc62151648e8c0 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Thu, 20 Dec 2012 16:24:43 +0200 Subject: [PATCH 1286/1799] rtlwifi: fix incorrect use of usb_alloc_coherent with usb_control_msg commit 4c3de5920c486b8eefa6187ee6a181864c161100 upstream. Incorrect use of usb_alloc_coherent memory as input buffer to usb_control_msg can cause problems in arch DMA code, for example kernel BUG at 'arch/arm/include/asm/dma-mapping.h:321' on ARM (linux-3.4). Change _usb_writeN_sync use kmalloc'd buffer instead. Signed-off-by: Jussi Kivilinna Acked-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/usb.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index aa970fc18a21..8fa144fa0c99 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -210,17 +210,16 @@ static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 index = REALTEK_USB_VENQT_CMD_IDX; int pipe = usb_sndctrlpipe(udev, 0); /* write_out */ u8 *buffer; - dma_addr_t dma_addr; - wvalue = (u16)(addr&0x0000ffff); - buffer = usb_alloc_coherent(udev, (size_t)len, GFP_ATOMIC, &dma_addr); + wvalue = (u16)(addr & 0x0000ffff); + buffer = kmalloc(len, GFP_ATOMIC); if (!buffer) return; memcpy(buffer, data, len); usb_control_msg(udev, pipe, request, reqtype, wvalue, index, buffer, len, 50); - usb_free_coherent(udev, (size_t)len, buffer, dma_addr); + kfree(buffer); } static void _rtl_usb_io_handler_init(struct device *dev, -- GitLab From 0e70111a128bd15f7ff90186deca1b6306a793e6 Mon Sep 17 00:00:00 2001 From: Tomasz Guszkowski Date: Sat, 22 Dec 2012 18:30:01 +0100 Subject: [PATCH 1287/1799] p54usb: add USB ID for T-Com Sinus 154 data II commit 3194b7fcdf6caea338b5d2c72d76fed80437649c upstream. Added USB ID for T-Com Sinus 154 data II. Signed-off-by: Tomasz Guszkowski Acked-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- 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 a337a50d4022..27e0a1ff8362 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[] = { {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, 0x4503)}, /* T-Com Sinus 154 data II */ {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 */ -- GitLab From 44c818b94f8b3d3ad173ef9556414944e6da6efb Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 27 Dec 2012 15:18:20 +0100 Subject: [PATCH 1288/1799] p54usb: add USBIDs for two more p54usb devices commit 4010fe21a315b4223c25376714c6a2b61b722e5c upstream. This patch adds USBIDs for: - DrayTek Vigor 530 - Zoom 4410a It also adds a note about Gemtek WUBI-100GW and SparkLAN WL-682 USBID conflict [WUBI-100GW is a ISL3886+NET2280 (LM86 firmare) solution, whereas WL-682 is a ISL3887 (LM87 firmware)] device. Source: Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/p54/p54usb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 27e0a1ff8362..be20cf765bc3 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -47,6 +47,7 @@ static struct usb_device_id p54u_table[] = { {USB_DEVICE(0x0411, 0x0050)}, /* Buffalo WLI2-USB2-G54 */ {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ + {USB_DEVICE(0x0675, 0x0530)}, /* DrayTek Vigor 530 */ {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */ {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */ @@ -82,6 +83,7 @@ static struct usb_device_id p54u_table[] = { {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(0x0803, 0x4310)}, /* Zoom 4410a */ {USB_DEVICE(0x083a, 0x4503)}, /* T-Com Sinus 154 data II */ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ {USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */ @@ -102,6 +104,7 @@ static struct usb_device_id p54u_table[] = { {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ + /* {USB_DEVICE(0x15a9, 0x0002)}, * Also SparkLAN WL-682 with 3887 */ {USB_DEVICE(0x1668, 0x1050)}, /* Actiontec 802UIG-1 */ {USB_DEVICE(0x1740, 0x1000)}, /* Senao NUB-350 */ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ -- GitLab From 9784404f31f7001186c5fc1f8e4a3c8091711dfa Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 22 Oct 2012 22:15:02 +0200 Subject: [PATCH 1289/1799] usb: gadget: midi: free hs descriptors commit d185039f7982eb82cf8d03b6fb6689587ca5af24 upstream. The HS descriptors are only created if HS is supported by the UDC but we never free them. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_midi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c index 2f7e8f2930cc..1bf95964056d 100644 --- a/drivers/usb/gadget/f_midi.c +++ b/drivers/usb/gadget/f_midi.c @@ -416,6 +416,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f) midi->id = NULL; usb_free_descriptors(f->descriptors); + usb_free_descriptors(f->hs_descriptors); kfree(midi); } -- GitLab From bb355e4833e30947197b58c8886dff40a5f6ee50 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 22 Oct 2012 22:15:04 +0200 Subject: [PATCH 1290/1799] usb: gadget: phonet: free requests in pn_bind()'s error path commit d0eca719dd11ad0619e8dd6a1f3eceb95b0216dd upstream. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_phonet.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index 965a6293206a..16512f921bc0 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c @@ -531,7 +531,7 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f) req = usb_ep_alloc_request(fp->out_ep, GFP_KERNEL); if (!req) - goto err; + goto err_req; req->complete = pn_rx_complete; fp->out_reqv[i] = req; @@ -540,14 +540,18 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f) /* Outgoing USB requests */ fp->in_req = usb_ep_alloc_request(fp->in_ep, GFP_KERNEL); if (!fp->in_req) - goto err; + goto err_req; INFO(cdev, "USB CDC Phonet function\n"); INFO(cdev, "using %s, OUT %s, IN %s\n", cdev->gadget->name, fp->out_ep->name, fp->in_ep->name); return 0; +err_req: + for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++) + usb_ep_free_request(fp->out_ep, fp->out_reqv[i]); err: + if (fp->out_ep) fp->out_ep->driver_data = NULL; if (fp->in_ep) -- GitLab From e7a4b0efe62e56a0acc81d16091c6efc2a282be8 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 22 Oct 2012 22:15:05 +0200 Subject: [PATCH 1291/1799] usb: gadget: uvc: fix error path in uvc_function_bind() commit 0f9df939385527049c8062a099fbfa1479fe7ce0 upstream. The "video->minor = -1" assigment is done in V4L2 by video_register_device() so it is removed here. Now. uvc_function_bind() calls in error case uvc_function_unbind() for cleanup. The problem is that uvc_function_unbind() frees the uvc struct and uvc_bind_config() does as well in error case of usb_add_function(). Removing kfree() in usb_add_function() would make the patch smaller but it would look odd because the new allocated memory is not cleaned up. However it is not guaranteed that if we call usb_add_function() we also get to the bind function. Therefore the patch extracts the conditional cleanup from uvc_function_unbind() applies to uvc_function_bind(). uvc_function_unbind() now contains only the complete cleanup which is required once everything has been registrated. Signed-off-by: Sebastian Andrzej Siewior Cc: Laurent Pinchart Cc: Bhupesh Sharma Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_uvc.c | 39 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 2022fe492148..a0abc65ecbea 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -335,7 +335,6 @@ uvc_register_video(struct uvc_device *uvc) return -ENOMEM; video->parent = &cdev->gadget->dev; - video->minor = -1; video->fops = &uvc_v4l2_fops; video->release = video_device_release; strncpy(video->name, cdev->gadget->name, sizeof(video->name)); @@ -462,23 +461,12 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f) INFO(cdev, "uvc_function_unbind\n"); - if (uvc->vdev) { - if (uvc->vdev->minor == -1) - video_device_release(uvc->vdev); - else - video_unregister_device(uvc->vdev); - uvc->vdev = NULL; - } - - if (uvc->control_ep) - uvc->control_ep->driver_data = NULL; - if (uvc->video.ep) - uvc->video.ep->driver_data = NULL; + video_unregister_device(uvc->vdev); + uvc->control_ep->driver_data = NULL; + uvc->video.ep->driver_data = NULL; - if (uvc->control_req) { - usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); - kfree(uvc->control_buf); - } + usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); + kfree(uvc->control_buf); kfree(f->descriptors); kfree(f->hs_descriptors); @@ -563,7 +551,22 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) return 0; error: - uvc_function_unbind(c, f); + if (uvc->vdev) + video_device_release(uvc->vdev); + + if (uvc->control_ep) + uvc->control_ep->driver_data = NULL; + if (uvc->video.ep) + uvc->video.ep->driver_data = NULL; + + if (uvc->control_req) { + usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); + kfree(uvc->control_buf); + } + + kfree(f->descriptors); + kfree(f->hs_descriptors); + kfree(f->ss_descriptors); return ret; } -- GitLab From c96158c87f8f3bc41ff6e1343c680a10fb747d31 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 22 Oct 2012 22:15:00 +0200 Subject: [PATCH 1292/1799] usb: gadget: network: fix bind() error path commit e79cc615a9bb44da72c499ccfa2c9c4bbea3aa84 upstream. I think this is wrong since 72c973dd ("usb: gadget: add usb_endpoint_descriptor to struct usb_ep"). If we fail to allocate an ep or bail out early we shouldn't check for the descriptor which is assigned at ep_enable() time. Signed-off-by: Sebastian Andrzej Siewior Cc: Tatyana Brokhman Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_ecm.c | 4 ++-- drivers/usb/gadget/f_eem.c | 5 ++--- drivers/usb/gadget/f_ncm.c | 4 ++-- drivers/usb/gadget/f_rndis.c | 4 ++-- drivers/usb/gadget/f_subset.c | 4 ++-- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index 30b908f2a53d..672c66aad6b9 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -808,9 +808,9 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) /* we might as well release our claims on endpoints */ if (ecm->notify) ecm->notify->driver_data = NULL; - if (ecm->port.out_ep->desc) + if (ecm->port.out_ep) ecm->port.out_ep->driver_data = NULL; - if (ecm->port.in_ep->desc) + if (ecm->port.in_ep) ecm->port.in_ep->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index 1a7b2dd7d408..a9cf20522ffa 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c @@ -319,10 +319,9 @@ eem_bind(struct usb_configuration *c, struct usb_function *f) if (f->hs_descriptors) usb_free_descriptors(f->hs_descriptors); - /* we might as well release our claims on endpoints */ - if (eem->port.out_ep->desc) + if (eem->port.out_ep) eem->port.out_ep->driver_data = NULL; - if (eem->port.in_ep->desc) + if (eem->port.in_ep) eem->port.in_ep->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c index aab8eded045b..d7811ae29729 100644 --- a/drivers/usb/gadget/f_ncm.c +++ b/drivers/usb/gadget/f_ncm.c @@ -1259,9 +1259,9 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f) /* we might as well release our claims on endpoints */ if (ncm->notify) ncm->notify->driver_data = NULL; - if (ncm->port.out_ep->desc) + if (ncm->port.out_ep) ncm->port.out_ep->driver_data = NULL; - if (ncm->port.in_ep->desc) + if (ncm->port.in_ep) ncm->port.in_ep->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 52343654f5df..345f8388cd33 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -803,9 +803,9 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) /* we might as well release our claims on endpoints */ if (rndis->notify) rndis->notify->driver_data = NULL; - if (rndis->port.out_ep->desc) + if (rndis->port.out_ep) rndis->port.out_ep->driver_data = NULL; - if (rndis->port.in_ep->desc) + if (rndis->port.in_ep) rndis->port.in_ep->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index 21ab474aca07..e5bb96628639 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -370,9 +370,9 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) usb_free_descriptors(f->hs_descriptors); /* we might as well release our claims on endpoints */ - if (geth->port.out_ep->desc) + if (geth->port.out_ep) geth->port.out_ep->driver_data = NULL; - if (geth->port.in_ep->desc) + if (geth->port.in_ep) geth->port.in_ep->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); -- GitLab From dc2306834bff03132beb1f18d7a13b6e5080e488 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 30 Nov 2012 12:57:03 +0100 Subject: [PATCH 1293/1799] ACPI: do acpisleep dmi check when CONFIG_ACPI_SLEEP is set commit 0ac1b1d7b7424cd6f129b5454b504b3cae746f0e upstream. The current acpisleep DMI checks only run when CONFIG_SUSPEND is set. And this may break hibernation on some platforms when CONFIG_SUSPEND is cleared. Move acpisleep DMI check into #ifdef CONFIG_ACPI_SLEEP instead. [rjw: Added acpi_sleep_dmi_check() and rebased on top of earlier patches adding entries to acpisleep_dmi_table[].] References: https://bugzilla.kernel.org/show_bug.cgi?id=45921 Signed-off-by: Zhang Rui Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/sleep.c | 348 ++++++++++++++++++++++--------------------- 1 file changed, 177 insertions(+), 171 deletions(-) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 480b648b9a1d..aa0a904e5631 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -138,6 +138,180 @@ void __init acpi_old_suspend_ordering(void) old_suspend_ordering = true; } +static int __init init_old_suspend_ordering(const struct dmi_system_id *d) +{ + acpi_old_suspend_ordering(); + 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, + .ident = "Abit KN9 (nForce4 variant)", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"), + DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "HP xw4600 Workstation", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "M2N8L"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "Panasonic CF51-2L", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, + "Matsushita Electric Industrial Co.,Ltd."), + DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-FW21E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCEB17FX", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"), + }, + }, + { + .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"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCEB1Z1E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-NW130D", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCCW29FX", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Averatec AV1020-ED2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"), + DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus A8N-SLI DELUXE", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus A8N-SLI Premium", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-SR26GN_P", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCEB1S1E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1S1E"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-FW520F", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Asus K54C", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "K54C"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Asus K54HR", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"), + }, + }, + {}, +}; + +static void acpi_sleep_dmi_check(void) +{ + dmi_check_system(acpisleep_dmi_table); +} + /** * acpi_pm_freeze - Disable the GPEs and suspend EC transactions. */ @@ -227,6 +401,7 @@ static void acpi_pm_end(void) } #else /* !CONFIG_ACPI_SLEEP */ #define acpi_target_sleep_state ACPI_STATE_S0 +static inline void acpi_sleep_dmi_check(void) {} #endif /* CONFIG_ACPI_SLEEP */ #ifdef CONFIG_SUSPEND @@ -371,175 +546,6 @@ static const struct platform_suspend_ops acpi_suspend_ops_old = { .end = acpi_pm_end, .recover = acpi_pm_finish, }; - -static int __init init_old_suspend_ordering(const struct dmi_system_id *d) -{ - old_suspend_ordering = true; - 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, - .ident = "Abit KN9 (nForce4 variant)", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"), - DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "HP xw4600 Workstation", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."), - DMI_MATCH(DMI_BOARD_NAME, "M2N8L"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "Panasonic CF51-2L", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, - "Matsushita Electric Industrial Co.,Ltd."), - DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-FW21E", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VPCEB17FX", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"), - }, - }, - { - .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"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VPCEB1Z1E", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-NW130D", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VPCCW29FX", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Averatec AV1020-ED2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"), - DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "Asus A8N-SLI DELUXE", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), - DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "Asus A8N-SLI Premium", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), - DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-SR26GN_P", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VPCEB1S1E", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1S1E"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-FW520F", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Asus K54C", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "K54C"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Asus K54HR", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"), - }, - }, - {}, -}; #endif /* CONFIG_SUSPEND */ #ifdef CONFIG_HIBERNATION @@ -880,13 +886,13 @@ int __init acpi_sleep_init(void) u8 type_a, type_b; #ifdef CONFIG_SUSPEND int i = 0; - - dmi_check_system(acpisleep_dmi_table); #endif if (acpi_disabled) return 0; + acpi_sleep_dmi_check(); + sleep_states[ACPI_STATE_S0] = 1; printk(KERN_INFO PREFIX "(supports S0"); -- GitLab From eb9422b448fdd814ca566c0509f72dc41971ba6b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 4 Jan 2013 23:00:54 +0100 Subject: [PATCH 1294/1799] ACPI / scan: Do not use dummy HID for system bus ACPI nodes commit 4f5f64cf0cc916220aaa055992e31195470cfe37 upstream. At one point acpi_device_set_id() checks if acpi_device_hid(device) returns NULL, but that never happens, so system bus devices with an empty list of PNP IDs are given the dummy HID ("device") instead of the "system bus HID" ("LNXSYBUS"). Fix the code to use the right check. Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 85cbfdccc97c..bd3199ce5b27 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1157,7 +1157,7 @@ static void acpi_device_set_id(struct acpi_device *device) acpi_add_id(device, ACPI_DOCK_HID); else if (!acpi_ibm_smbus_match(device)) acpi_add_id(device, ACPI_SMBUS_IBM_HID); - else if (!acpi_device_hid(device) && + else if (list_empty(&device->pnp.ids) && ACPI_IS_ROOT_DEVICE(device->parent)) { acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */ strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME); -- GitLab From d1967aac70c3eaf8f93710035b313904deabf6a9 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Mon, 12 Nov 2012 16:55:38 -0500 Subject: [PATCH 1295/1799] NFS: Add sequence_priviliged_ops for nfs4_proc_sequence() commit 6bdb5f213c4344324f600dde885f25768fbd14db upstream. If I mount an NFS v4.1 server to a single client multiple times and then run xfstests over each mountpoint I usually get the client into a state where recovery deadlocks. The server informs the client of a cb_path_down sequence error, the client then does a bind_connection_to_session and checks the status of the lease. I found that bind_connection_to_session sets the NFS4_SESSION_DRAINING flag on the client, but this flag is never unset before nfs4_check_lease() reaches nfs4_proc_sequence(). This causes the client to deadlock, halting all NFS activity to the server. nfs4_proc_sequence() is only called by the state manager, so I can change it to run in privileged mode to bypass the NFS4_SESSION_DRAINING check and avoid the deadlock. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8955e3642000..30351877aee2 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -5739,13 +5739,26 @@ static void nfs41_sequence_prepare(struct rpc_task *task, void *data) rpc_call_start(task); } +static void nfs41_sequence_prepare_privileged(struct rpc_task *task, void *data) +{ + rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); + nfs41_sequence_prepare(task, data); +} + static const struct rpc_call_ops nfs41_sequence_ops = { .rpc_call_done = nfs41_sequence_call_done, .rpc_call_prepare = nfs41_sequence_prepare, .rpc_release = nfs41_sequence_release, }; -static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) +static const struct rpc_call_ops nfs41_sequence_privileged_ops = { + .rpc_call_done = nfs41_sequence_call_done, + .rpc_call_prepare = nfs41_sequence_prepare_privileged, + .rpc_release = nfs41_sequence_release, +}; + +static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred, + const struct rpc_call_ops *seq_ops) { struct nfs4_sequence_data *calldata; struct rpc_message msg = { @@ -5755,7 +5768,7 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_ struct rpc_task_setup task_setup_data = { .rpc_client = clp->cl_rpcclient, .rpc_message = &msg, - .callback_ops = &nfs41_sequence_ops, + .callback_ops = seq_ops, .flags = RPC_TASK_ASYNC | RPC_TASK_SOFT, }; @@ -5782,7 +5795,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) return 0; - task = _nfs41_proc_sequence(clp, cred); + task = _nfs41_proc_sequence(clp, cred, &nfs41_sequence_ops); if (IS_ERR(task)) ret = PTR_ERR(task); else @@ -5796,7 +5809,7 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) struct rpc_task *task; int ret; - task = _nfs41_proc_sequence(clp, cred); + task = _nfs41_proc_sequence(clp, cred, &nfs41_sequence_privileged_ops); if (IS_ERR(task)) { ret = PTR_ERR(task); goto out; -- GitLab From 1627e18aed860a61cc740e9ec9883c63059ae2a3 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 13 Dec 2012 15:14:36 +1100 Subject: [PATCH 1296/1799] NFS: avoid NULL dereference in nfs_destroy_server commit f259613a1e4b44a0cf85a5dafd931be96ee7c9e5 upstream. In rare circumstances, nfs_clone_server() of a v2 or v3 server can get an error between setting server->destory (to nfs_destroy_server), and calling nfs_start_lockd (which will set server->nlm_host). If this happens, nfs_clone_server will call nfs_free_server which will call nfs_destroy_server and thence nlmclnt_done(NULL). This causes the NULL to be dereferenced. So add a guard to only call nlmclnt_done() if ->nlm_host is not NULL. The other guards there are irrelevant as nlm_host can only be non-NULL if one of these flags are set - so remove those tests. (Thanks to Trond for this suggestion). This is suitable for any stable kernel since 2.6.25. Signed-off-by: NeilBrown Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/client.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 60f7e4ec842c..37f6de36973c 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -694,8 +694,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp, */ static void nfs_destroy_server(struct nfs_server *server) { - if (!(server->flags & NFS_MOUNT_LOCAL_FLOCK) || - !(server->flags & NFS_MOUNT_LOCAL_FCNTL)) + if (server->nlm_host) nlmclnt_done(server->nlm_host); } -- GitLab From 0d965378563d9e73e52b11fcd8576a90f071b2af Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 14 Dec 2012 16:38:46 -0500 Subject: [PATCH 1297/1799] NFS: Fix calls to drop_nlink() commit 1f018458b30b0d5c535c94e577aa0acbb92e1395 upstream. It is almost always wrong for NFS to call drop_nlink() after removing a file. What we really want is to mark the inode's attributes for revalidation, and we want to ensure that the VFS drops it if we're reasonably sure that this is the final unlink(). Do the former using the usual cache validity flags, and the latter by testing if inode->i_nlink == 1, and clearing it in that case. This also fixes the following warning reported by Neil Brown and Jeff Layton (among others). [634155.004438] WARNING: at /home/abuild/rpmbuild/BUILD/kernel-desktop-3.5.0/lin [634155.004442] Hardware name: Latitude E6510 [634155.004577] crc_itu_t crc32c_intel snd_hwdep snd_pcm snd_timer snd soundcor [634155.004609] Pid: 13402, comm: bash Tainted: G W 3.5.0-36-desktop # [634155.004611] Call Trace: [634155.004630] [] dump_trace+0xaa/0x2b0 [634155.004641] [] dump_stack+0x69/0x6f [634155.004653] [] warn_slowpath_common+0x7b/0xc0 [634155.004662] [] drop_nlink+0x34/0x40 [634155.004687] [] nfs_dentry_iput+0x33/0x70 [nfs] [634155.004714] [] dput+0x12e/0x230 [634155.004726] [] __fput+0x170/0x230 [634155.004735] [] filp_close+0x5f/0x90 [634155.004743] [] sys_close+0x97/0x100 [634155.004754] [] system_call_fastpath+0x16/0x1b [634155.004767] [<00007f2a73a0d110>] 0x7f2a73a0d10f Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/dir.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 53ad9d1c37e4..a0daac7ad508 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1219,11 +1219,14 @@ static int nfs_dentry_delete(const struct dentry *dentry) } +/* Ensure that we revalidate inode->i_nlink */ static void nfs_drop_nlink(struct inode *inode) { spin_lock(&inode->i_lock); - if (inode->i_nlink > 0) - drop_nlink(inode); + /* drop the inode if we're reasonably sure this is the last link */ + if (inode->i_nlink == 1) + clear_nlink(inode); + NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR; spin_unlock(&inode->i_lock); } @@ -1238,8 +1241,8 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA; if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { - drop_nlink(inode); nfs_complete_unlink(dentry, inode); + nfs_drop_nlink(inode); } iput(inode); } @@ -1800,10 +1803,8 @@ static int nfs_safe_remove(struct dentry *dentry) if (inode != NULL) { nfs_inode_return_delegation(inode); error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); - /* The VFS may want to delete this inode */ if (error == 0) nfs_drop_nlink(inode); - nfs_mark_for_revalidate(inode); } else error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); if (error == -ENOENT) -- GitLab From aa8dc4af9a1ed18d71da58e883bb8260ba47afb5 Mon Sep 17 00:00:00 2001 From: Yanchuan Nian Date: Wed, 24 Oct 2012 14:44:19 +0800 Subject: [PATCH 1298/1799] nfs: fix wrong object type in lockowner_slab commit 3c40794b2dd0f355ef4e6bf8d85af5dcd7da7ece upstream. The object type in the cache of lockowner_slab is wrong, and it is better to fix it. Signed-off-by: Yanchuan Nian Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index a2f99d155840..537731e4c160 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -2356,7 +2356,7 @@ nfsd4_init_slabs(void) if (openowner_slab == NULL) goto out_nomem; lockowner_slab = kmem_cache_create("nfsd4_lockowners", - sizeof(struct nfs4_openowner), 0, 0, NULL); + sizeof(struct nfs4_lockowner), 0, 0, NULL); if (lockowner_slab == NULL) goto out_nomem; file_slab = kmem_cache_create("nfsd4_files", -- GitLab From 12c93e196764a2092f35b30a1e924a5071f164ee Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 16 Nov 2012 15:22:43 -0500 Subject: [PATCH 1299/1799] nfsd: fix v4 reply caching commit 57d276d71aef7d8305ff002a070cb98deb2edced upstream. Very embarassing: 1091006c5eb15cba56785bd5b498a8d0b9546903 "nfsd: turn on reply cache for NFSv4" missed a line, effectively leaving the reply cache off in the v4 case. I thought I'd tested that, but I guess not. This time, wrote a pynfs test to confirm it works. Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfssvc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index b6f8e65f85bd..53459b055cfc 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -650,7 +650,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) } /* Store reply in cache. */ - nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1); + nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1); return 1; } -- GitLab From 4cbb3d03810a50cb5d9eab0a6cfe3152a65911f2 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 4 Dec 2012 18:25:10 -0500 Subject: [PATCH 1300/1799] nfsd4: fix oops on unusual readlike compound commit d5f50b0c290431c65377c4afa1c764e2c3fe5305 upstream. If the argument and reply together exceed the maximum payload size, then a reply with a read-like operation can overlow the rq_pages array. Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4xdr.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 283d15e9f46d..967d68eef282 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2920,11 +2920,16 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, len = maxcount; v = 0; while (len > 0) { - pn = resp->rqstp->rq_resused++; + pn = resp->rqstp->rq_resused; + if (!resp->rqstp->rq_respages[pn]) { /* ran out of pages */ + maxcount -= len; + break; + } resp->rqstp->rq_vec[v].iov_base = page_address(resp->rqstp->rq_respages[pn]); resp->rqstp->rq_vec[v].iov_len = len < PAGE_SIZE ? len : PAGE_SIZE; + resp->rqstp->rq_resused++; v++; len -= PAGE_SIZE; } @@ -2970,6 +2975,8 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd return nfserr; if (resp->xbuf->page_len) return nfserr_resource; + if (!resp->rqstp->rq_respages[resp->rqstp->rq_resused]) + return nfserr_resource; page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); @@ -3019,6 +3026,8 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4 return nfserr; if (resp->xbuf->page_len) return nfserr_resource; + if (!resp->rqstp->rq_respages[resp->rqstp->rq_resused]) + return nfserr_resource; RESERVE_SPACE(NFS4_VERIFIER_SIZE); savep = p; -- GitLab From 59d6ce4370c17dbd3db789740a036f158e8ba9a0 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Fri, 7 Dec 2012 15:40:55 -0500 Subject: [PATCH 1301/1799] nfsd: avoid permission checks on EXCLUSIVE_CREATE replay commit 7007c90fb9fef593b4aeaeee57e6a6754276c97c upstream. With NFSv4, if we create a file then open it we explicit avoid checking the permissions on the file during the open because the fact that we created it ensures we should be allow to open it (the create and the open should appear to be a single operation). However if the reply to an EXCLUSIVE create gets lots and the client resends the create, the current code will perform the permission check - because it doesn't realise that it did the open already.. This patch should fix this. Note that I haven't actually seen this cause a problem. I was just looking at the code trying to figure out a different EXCLUSIVE open related issue, and this looked wrong. (Fix confirmed with pynfs 4.0 test OPEN4--bfields) Signed-off-by: NeilBrown [bfields: use OWNER_OVERRIDE and update for 4.1] Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4proc.c | 8 +++++--- fs/nfsd/vfs.c | 10 ++++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 987e719fbae8..dd0308d65f66 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -194,6 +194,7 @@ static __be32 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) { struct svc_fh *resfh; + int accmode; __be32 status; resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); @@ -253,9 +254,10 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o /* set reply cache */ fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh, &resfh->fh_handle); - if (!open->op_created) - status = do_open_permission(rqstp, resfh, open, - NFSD_MAY_NOP); + accmode = NFSD_MAY_NOP; + if (open->op_created) + accmode |= NFSD_MAY_OWNER_OVERRIDE; + status = do_open_permission(rqstp, resfh, open, accmode); set_change_info(&open->op_cinfo, current_fh); fh_dup2(current_fh, resfh); out: diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 568666156ea4..f03160106b95 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1477,13 +1477,19 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, case NFS3_CREATE_EXCLUSIVE: if ( dchild->d_inode->i_mtime.tv_sec == v_mtime && dchild->d_inode->i_atime.tv_sec == v_atime - && dchild->d_inode->i_size == 0 ) + && dchild->d_inode->i_size == 0 ) { + if (created) + *created = 1; break; + } case NFS4_CREATE_EXCLUSIVE4_1: if ( dchild->d_inode->i_mtime.tv_sec == v_mtime && dchild->d_inode->i_atime.tv_sec == v_atime - && dchild->d_inode->i_size == 0 ) + && dchild->d_inode->i_size == 0 ) { + if (created) + *created = 1; goto set_attr; + } /* fallthru */ case NFS3_CREATE_GUARDED: err = nfserr_exist; -- GitLab From 042cf2fb1d2ac4b4b27b2ccc4ac317a2f53df3c3 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Fri, 4 Jan 2013 03:22:57 -0500 Subject: [PATCH 1302/1799] nfs: fix null checking in nfs_get_option_str() commit e25fbe380c4e3c09afa98bcdcd9d3921443adab8 upstream. The following null pointer check is broken. *option = match_strdup(args); return !option; The pointer `option' must be non-null, and thus `!option' is always false. Use `!*option' instead. The bug was introduced in commit c5cb09b6f8 ("Cleanup: Factor out some cut-and-paste code."). Signed-off-by: Xi Wang Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index feabe7a394c3..c252161e7b1d 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -1138,7 +1138,7 @@ static int nfs_get_option_str(substring_t args[], char **option) { kfree(*option); *option = match_strdup(args); - return !option; + return !*option; } static int nfs_get_option_ul(substring_t args[], unsigned long *option) -- GitLab From c815c83dfd1aef11d4197dc46b21a2471b81af2c Mon Sep 17 00:00:00 2001 From: Peter Popovec Date: Fri, 14 Dec 2012 22:57:25 -0800 Subject: [PATCH 1303/1799] Input: walkera0701 - fix crash on startup commit a455e2985f57e2a71566bb8850094af38b2c932d upstream. The driver's timer must be set up before enabling IRQ handler, otherwise bad things may happen. Reported-and-tested-by: Fengguang Wu Signed-off-by: Peter Popovec Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/joystick/walkera0701.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/input/joystick/walkera0701.c b/drivers/input/joystick/walkera0701.c index 4dfa1eed4b7c..f8f892b076e8 100644 --- a/drivers/input/joystick/walkera0701.c +++ b/drivers/input/joystick/walkera0701.c @@ -196,6 +196,7 @@ static void walkera0701_close(struct input_dev *dev) struct walkera_dev *w = input_get_drvdata(dev); parport_disable_irq(w->parport); + hrtimer_cancel(&w->timer); } static int walkera0701_connect(struct walkera_dev *w, int parport) @@ -224,6 +225,9 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) if (parport_claim(w->pardevice)) goto init_err1; + hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + w->timer.function = timer_handler; + w->input_dev = input_allocate_device(); if (!w->input_dev) goto init_err2; @@ -254,8 +258,6 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) if (err) goto init_err3; - hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - w->timer.function = timer_handler; return 0; init_err3: @@ -271,7 +273,6 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) static void walkera0701_disconnect(struct walkera_dev *w) { - hrtimer_cancel(&w->timer); input_unregister_device(w->input_dev); parport_release(w->pardevice); parport_unregister_device(w->pardevice); -- GitLab From 1a37441ae4ad38d98c39b349137c0fb7f76b32ad Mon Sep 17 00:00:00 2001 From: Christophe TORDEUX Date: Mon, 24 Dec 2012 09:20:40 -0800 Subject: [PATCH 1304/1799] Input: sentelic - only report position of first finger as ST coordinates commit a25461659050b913e114d282bf58823682eb56b6 upstream. Report only the position of the first finger as absolute non-MT coordinates, instead of reporting both fingers alternatively. Actual MT events are unaffected. This fixes horizontal and improves vertical scrolling with the touchpad. Signed-off-by: Christophe TORDEUX Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/sentelic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 661a0ca3b3d6..1257ce8147fc 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -759,7 +759,7 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y); fsp_set_slot(dev, 1, false, 0, 0); } - if (fgrs > 0) { + if (fgrs == 1 || (fgrs == 2 && !(packet[0] & FSP_PB0_MFMC_FGR2))) { input_report_abs(dev, ABS_X, abs_x); input_report_abs(dev, ABS_Y, abs_y); } -- GitLab From 09c4161c8a1fe8900561029a5d1dce8887231afd Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sat, 3 Nov 2012 11:52:09 +0100 Subject: [PATCH 1305/1799] genirq: Always force thread affinity commit 04aa530ec04f61875b99c12721162e2964e3318c upstream. Sankara reported that the genirq core code fails to adjust the affinity of an interrupt thread in several cases: 1) On request/setup_irq() the call to setup_affinity() happens before the new action is registered, so the new thread is not notified. 2) For secondary shared interrupts nothing notifies the new thread to change its affinity. 3) Interrupts which have the IRQ_NO_BALANCE flag set are not moving the thread either. Fix this by setting the thread affinity flag right on thread creation time. This ensures that under all circumstances the thread moves to the right place. Requires a check in irq_thread_check_affinity for an existing affinity mask (CONFIG_CPU_MASK_OFFSTACK=y) Reported-and-tested-by: Sankara Muthukrishnan Link: http://lkml.kernel.org/r/alpine.LFD.2.02.1209041738200.2754@ionos Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/irq/manage.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index b9d1d83ec381..7684920f4f66 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -708,6 +708,7 @@ static void irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { cpumask_var_t mask; + bool valid = true; if (!test_and_clear_bit(IRQTF_AFFINITY, &action->thread_flags)) return; @@ -722,10 +723,18 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) } raw_spin_lock_irq(&desc->lock); - cpumask_copy(mask, desc->irq_data.affinity); + /* + * This code is triggered unconditionally. Check the affinity + * mask pointer. For CPU_MASK_OFFSTACK=n this is optimized out. + */ + if (desc->irq_data.affinity) + cpumask_copy(mask, desc->irq_data.affinity); + else + valid = false; raw_spin_unlock_irq(&desc->lock); - set_cpus_allowed_ptr(current, mask); + if (valid) + set_cpus_allowed_ptr(current, mask); free_cpumask_var(mask); } #else @@ -933,6 +942,16 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) */ get_task_struct(t); new->thread = t; + /* + * Tell the thread to set its affinity. This is + * important for shared interrupt handlers as we do + * not invoke setup_affinity() for the secondary + * handlers as everything is already set up. Even for + * interrupts marked with IRQF_NO_BALANCE this is + * correct as we want the thread to move to the cpu(s) + * on which the requesting code placed the interrupt. + */ + set_bit(IRQTF_AFFINITY, &new->thread_flags); } if (!alloc_cpumask_var(&mask, GFP_KERNEL)) { -- GitLab From 9044dea3b603b7f0246aa7bed4039df3666fc611 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 5 Nov 2012 22:26:40 +0300 Subject: [PATCH 1306/1799] usb: musb: cppi_dma: export cppi_interrupt() commit 8b416b0b25d5d8ddb3a91c1d20e1373582c50405 upstream. Now that DaVinci glue layer can be modular, we must export cppi_interrupt() that it may call... Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/cppi_dma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 66bc376005d2..319cfcf372ad 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -1313,6 +1313,7 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +EXPORT_SYMBOL_GPL(cppi_interrupt); /* Instantiate a software object representing a DMA controller. */ struct dma_controller *__init -- GitLab From 363cfe8903364aed741cc5c7f31610581a135be8 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 25 Oct 2012 13:44:12 -0700 Subject: [PATCH 1307/1799] xhci: Fix conditional check in bandwidth calculation. commit 392a07ae3316f2b90b39ce41e66d6f6b5c95de90 upstream. David reports that at drivers/usb/host/xhci.c:2257: static bool xhci_is_sync_in_ep(unsigned int ep_type) { return (ep_type == ISOC_IN_EP || ep_type != INT_IN_EP); } The static analyser cppcheck says [linux-3.7-rc2/drivers/usb/host/xhci.c:2257]: (style) Redundant condition: If ep_type == 5, the comparison ep_type != 7 is always true. Maybe the original programmer intention was something like static bool xhci_is_sync_in_ep(unsigned int ep_type) { return (ep_type == ISOC_IN_EP || ep_type == INT_IN_EP); } Fix this. This patch should be backported to stable kernels as old as 3.2, that contain the commit 2b69899934c63b7b9432568584fb4c4a2924f40c "xhci: USB 3.0 BW checking." Signed-off-by: Sarah Sharp Reported-by: David Binderman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index e52ddfe05486..1722e218ee27 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2253,7 +2253,7 @@ static bool xhci_is_async_ep(unsigned int ep_type) static bool xhci_is_sync_in_ep(unsigned int ep_type) { - return (ep_type == ISOC_IN_EP || ep_type != INT_IN_EP); + return (ep_type == ISOC_IN_EP || ep_type == INT_IN_EP); } static unsigned int xhci_get_ss_bw_consumed(struct xhci_bw_info *ep_bw) -- GitLab From ceb58b9ffa579690f6124fd49dc1734071544f50 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 25 Oct 2012 15:56:40 -0700 Subject: [PATCH 1308/1799] xHCI: Fix TD Size calculation on 1.0 hosts. commit 4525c0a10dff7ad3669763c28016c7daffc3900e upstream. The xHCI 1.0 specification made a change to the TD Size field in TRBs. The value is now the number of packets that remain to be sent in the TD, not including this TRB. The TD Size value for the last TRB in a TD must always be zero. The xHCI function xhci_v1_0_td_remainder() attempts to calculate this, but it gets it wrong. First, it erroneously reuses the old xhci_td_remainder function, which will right shift the value by 10. The xHCI 1.0 spec as of June 2011 says nothing about right shifting by 10. Second, it does not set the TD size for the last TRB in a TD to zero. Third, it uses roundup instead of DIV_ROUND_UP. The total packet count is supposed to be the total number of bytes in this TD, divided by the max packet size, rounded up. DIV_ROUND_UP is the right function to use in that case. With the old code, a TD on an endpoint with max packet size 1024 would be set up like so: TRB 1, TRB length = 600 bytes, TD size = 0 TRB 1, TRB length = 200 bytes, TD size = 0 TRB 1, TRB length = 100 bytes, TD size = 0 With the new code, the TD would be set up like this: TRB 1, TRB length = 600 bytes, TD size = 1 TRB 1, TRB length = 200 bytes, TD size = 1 TRB 1, TRB length = 100 bytes, TD size = 0 This commit should be backported to kernels as old as 3.0, that contain the commit 4da6e6f247a2601ab9f1e63424e4d944ed4124f3 "xhci 1.0: Update TD size field format." Signed-off-by: Sarah Sharp Reported-by: Chintan Mehta Reported-by: Shimmer Huang Tested-by: Bhavik Kothari Tested-by: Shimmer Huang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 23aebcb4ee24..bf8bcc4dd788 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3069,11 +3069,11 @@ static u32 xhci_td_remainder(unsigned int remainder) } /* - * For xHCI 1.0 host controllers, TD size is the number of packets remaining in - * the TD (*not* including this TRB). + * For xHCI 1.0 host controllers, TD size is the number of max packet sized + * packets remaining in the TD (*not* including this TRB). * * Total TD packet count = total_packet_count = - * roundup(TD size in bytes / wMaxPacketSize) + * DIV_ROUND_UP(TD size in bytes / wMaxPacketSize) * * Packets transferred up to and including this TRB = packets_transferred = * rounddown(total bytes transferred including this TRB / wMaxPacketSize) @@ -3081,15 +3081,16 @@ static u32 xhci_td_remainder(unsigned int remainder) * TD size = total_packet_count - packets_transferred * * It must fit in bits 21:17, so it can't be bigger than 31. + * The last TRB in a TD must have the TD size set to zero. */ - static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len, - unsigned int total_packet_count, struct urb *urb) + unsigned int total_packet_count, struct urb *urb, + unsigned int num_trbs_left) { int packets_transferred; /* One TRB with a zero-length data packet. */ - if (running_total == 0 && trb_buff_len == 0) + if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0)) return 0; /* All the TRB queueing functions don't count the current TRB in @@ -3098,7 +3099,9 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len, packets_transferred = (running_total + trb_buff_len) / usb_endpoint_maxp(&urb->ep->desc); - return xhci_td_remainder(total_packet_count - packets_transferred); + if ((total_packet_count - packets_transferred) > 31) + return 31 << 17; + return (total_packet_count - packets_transferred) << 17; } static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, @@ -3125,7 +3128,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, num_trbs = count_sg_trbs_needed(xhci, urb); num_sgs = urb->num_mapped_sgs; - total_packet_count = roundup(urb->transfer_buffer_length, + total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length, usb_endpoint_maxp(&urb->ep->desc)); trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id], @@ -3208,7 +3211,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, running_total); } else { remainder = xhci_v1_0_td_remainder(running_total, - trb_buff_len, total_packet_count, urb); + trb_buff_len, total_packet_count, urb, + num_trbs - 1); } length_field = TRB_LEN(trb_buff_len) | remainder | @@ -3316,7 +3320,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, start_cycle = ep_ring->cycle_state; running_total = 0; - total_packet_count = roundup(urb->transfer_buffer_length, + total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length, usb_endpoint_maxp(&urb->ep->desc)); /* How much data is in the first TRB? */ addr = (u64) urb->transfer_dma; @@ -3362,7 +3366,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, running_total); } else { remainder = xhci_v1_0_td_remainder(running_total, - trb_buff_len, total_packet_count, urb); + trb_buff_len, total_packet_count, urb, + num_trbs - 1); } length_field = TRB_LEN(trb_buff_len) | remainder | @@ -3625,7 +3630,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, addr = start_addr + urb->iso_frame_desc[i].offset; td_len = urb->iso_frame_desc[i].length; td_remain_len = td_len; - total_packet_count = roundup(td_len, + total_packet_count = DIV_ROUND_UP(td_len, usb_endpoint_maxp(&urb->ep->desc)); /* A zero-length transfer still involves at least one packet. */ if (total_packet_count == 0) @@ -3704,7 +3709,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } else { remainder = xhci_v1_0_td_remainder( running_total, trb_buff_len, - total_packet_count, urb); + total_packet_count, urb, + (trbs_per_td - j - 1)); } length_field = TRB_LEN(trb_buff_len) | remainder | -- GitLab From a50afb91545b5a7e32a508b3eecaffe9538f018b Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Thu, 1 Nov 2012 12:47:59 -0700 Subject: [PATCH 1309/1799] xhci: fix null-pointer dereference when destroying half-built segment rings commit 68e5254adb88bede68285f11fb442a4d34fb550c upstream. xhci_alloc_segments_for_ring() builds a list of xhci_segments and links the tail to head at the end (forming a ring). When it bails out for OOM reasons half-way through, it tries to destroy its half-built list with xhci_free_segments_for_ring(), even though it is not a ring yet. This causes a null-pointer dereference upon hitting the last element. Furthermore, one of its callers (xhci_ring_alloc()) mistakenly believes the output parameters to be valid upon this kind of OOM failure, and calls xhci_ring_free() on them. Since the (incomplete) list/ring should already be destroyed in that case, this would lead to a use after free. This patch fixes those issues by having xhci_alloc_segments_for_ring() destroy its half-built, non-circular list manually and destroying the invalid struct xhci_ring in xhci_ring_alloc() with a plain kfree(). This patch should be backported to kernels as old as 2.6.31, that contains the commit 0ebbab37422315a5d0cb29792271085bafdf38c0 "USB: xhci: Ring allocation and initialization." A separate patch will need to be developed for kernels older than 3.4, since the ring allocation code was refactored in that kernel. Signed-off-by: Julius Werner Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index cbed50ad9c12..3e16f1c160a2 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -205,7 +205,12 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, next = xhci_segment_alloc(xhci, cycle_state, flags); if (!next) { - xhci_free_segments_for_ring(xhci, *first); + prev = *first; + while (prev) { + next = prev->next; + xhci_segment_free(xhci, prev); + prev = next; + } return -ENOMEM; } xhci_link_segments(xhci, prev, next, type); @@ -258,7 +263,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, return ring; fail: - xhci_ring_free(xhci, ring); + kfree(ring); return NULL; } -- GitLab From 4b2e61048c2c51882dc268dc2916a5b3bfab00ea Mon Sep 17 00:00:00 2001 From: "Alexis R. Cortes" Date: Thu, 8 Nov 2012 16:59:27 -0600 Subject: [PATCH 1310/1799] usb: host: xhci: Stricter conditional for Z1 system models for Compliance Mode Patch commit b0e4e606ff6ff26da0f60826e75577b56ba4e463 upstream. This minor patch creates a more stricter conditional for the Z1 sytems for applying the Compliance Mode Patch, this to avoid the quirk to be applied to models that contain a "Z1" in their dmi product string but are different from Z1 systems. This patch should be backported to stable kernels as old as 3.2, that contain the commit 71c731a296f1b08a3724bd1b514b64f1bda87a23 "usb: host: xhci: Fix Compliance Mode on SN65LVPE502CP Hardware" Signed-off-by: Alexis R. Cortes Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1722e218ee27..b4063fc72b42 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -480,7 +480,7 @@ static bool compliance_mode_recovery_timer_quirk_check(void) if (strstr(dmi_product_name, "Z420") || strstr(dmi_product_name, "Z620") || strstr(dmi_product_name, "Z820") || - strstr(dmi_product_name, "Z1")) + strstr(dmi_product_name, "Z1 Workstation")) return true; return false; -- GitLab From 66f8b956aeeeea9e5b3024f860251687f13f9013 Mon Sep 17 00:00:00 2001 From: Russell Webb Date: Fri, 9 Nov 2012 13:58:49 -0800 Subject: [PATCH 1311/1799] xhci: Add Lynx Point LP to list of Intel switchable hosts commit bb1e5dd7113d2fd178d3af9aca8f480ae0468edf upstream. Like Lynx Point, Lynx Point LP is also switchable. See 1c12443ab8eba71a658fae4572147e56d1f84f66 for more details. This patch should be backported to stable kernels as old as 3.0, that contain commit 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support EHCI/xHCI port switching." Signed-off-by: Russell Webb Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 3 ++- drivers/usb/host/pci-quirks.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 123481793a47..0909783a034a 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -362,7 +362,8 @@ static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev) pdev->vendor == PCI_VENDOR_ID_INTEL && (pdev->device == 0x1E26 || pdev->device == 0x8C2D || - pdev->device == 0x8C26); + pdev->device == 0x8C26 || + pdev->device == 0x9C26); } static void ehci_enable_xhci_companion(void) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 39f9e4a9a2d3..eb5563ac58bc 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -723,6 +723,7 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done, } #define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI 0x8C31 +#define PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI 0x9C31 bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev) { @@ -736,7 +737,8 @@ bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev) { return pdev->class == PCI_CLASS_SERIAL_USB_XHCI && pdev->vendor == PCI_VENDOR_ID_INTEL && - pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI; + (pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI); } bool usb_is_intel_switchable_xhci(struct pci_dev *pdev) -- GitLab From 475261dbbf5d85e1a298886385d859ada787ae1f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 19 Nov 2012 08:13:35 -0800 Subject: [PATCH 1312/1799] cgroup: remove incorrect dget/dput() pair in cgroup_create_dir() commit 175431635ec09b1d1bba04979b006b99e8305a83 upstream. cgroup_create_dir() does weird dancing with dentry refcnt. On success, it gets and then puts it achieving nothing. On failure, it puts but there isn't no matching get anywhere leading to the following oops if cgroup_create_file() fails for whatever reason. ------------[ cut here ]------------ kernel BUG at /work/os/work/fs/dcache.c:552! invalid opcode: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC Modules linked in: CPU 2 Pid: 697, comm: mkdir Not tainted 3.7.0-rc4-work+ #3 Bochs Bochs RIP: 0010:[] [] dput+0x1dc/0x1e0 RSP: 0018:ffff88001a3ebef8 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff88000e5b1ef8 RCX: 0000000000000403 RDX: 0000000000000303 RSI: 2000000000000000 RDI: ffff88000e5b1f58 RBP: ffff88001a3ebf18 R08: ffffffff82c76960 R09: 0000000000000001 R10: ffff880015022080 R11: ffd9bed70f48a041 R12: 00000000ffffffea R13: 0000000000000001 R14: ffff88000e5b1f58 R15: 00007fff57656d60 FS: 00007ff05fcb3800(0000) GS:ffff88001fd00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000004046f0 CR3: 000000001315f000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process mkdir (pid: 697, threadinfo ffff88001a3ea000, task ffff880015022080) Stack: ffff88001a3ebf48 00000000ffffffea 0000000000000001 0000000000000000 ffff88001a3ebf38 ffffffff811cc889 0000000000000001 ffff88000e5b1ef8 ffff88001a3ebf68 ffffffff811d1fc9 ffff8800198d7f18 ffff880019106ef8 Call Trace: [] done_path_create+0x19/0x50 [] sys_mkdirat+0x59/0x80 [] sys_mkdir+0x19/0x20 [] system_call_fastpath+0x16/0x1b Code: 00 48 8d 90 18 01 00 00 48 89 93 c0 00 00 00 4c 89 a0 18 01 00 00 48 8b 83 a0 00 00 00 83 80 28 01 00 00 01 e8 e6 6f a0 00 eb 92 <0f> 0b 66 90 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 49 89 fe 41 RIP [] dput+0x1dc/0x1e0 RSP ---[ end trace 1277bcfd9561ddb0 ]--- Fix it by dropping the unnecessary dget/dput() pair. Signed-off-by: Tejun Heo Acked-by: Li Zefan Signed-off-by: Greg Kroah-Hartman --- kernel/cgroup.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 762f7cc753ac..a5dccd4c2360 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2568,9 +2568,7 @@ static int cgroup_create_dir(struct cgroup *cgrp, struct dentry *dentry, dentry->d_fsdata = cgrp; inc_nlink(parent->d_inode); rcu_assign_pointer(cgrp->dentry, dentry); - dget(dentry); } - dput(dentry); return error; } -- GitLab From cd924e960d3c2ae1654109b5b9e88cec334f7126 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 16 Oct 2012 15:03:14 -0700 Subject: [PATCH 1313/1799] freezer: add missing mb's to freezer_count() and freezer_should_skip() commit dd67d32dbc5de299d70cc9e10c6c1e29ffa56b92 upstream. A task is considered frozen enough between freezer_do_not_count() and freezer_count() and freezers use freezer_should_skip() to test this condition. This supposedly works because freezer_count() always calls try_to_freezer() after clearing %PF_FREEZER_SKIP. However, there currently is nothing which guarantees that freezer_count() sees %true freezing() after clearing %PF_FREEZER_SKIP when freezing is in progress, and vice-versa. A task can escape the freezing condition in effect by freezer_count() seeing !freezing() and freezer_should_skip() seeing %PF_FREEZER_SKIP. This patch adds smp_mb()'s to freezer_count() and freezer_should_skip() such that either %true freezing() is visible to freezer_count() or !PF_FREEZER_SKIP is visible to freezer_should_skip(). Signed-off-by: Tejun Heo Cc: Oleg Nesterov Cc: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- include/linux/freezer.h | 50 ++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/include/linux/freezer.h b/include/linux/freezer.h index d09af4b67cf1..ee899329e65a 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h @@ -75,28 +75,62 @@ static inline bool cgroup_freezing(struct task_struct *task) */ -/* Tell the freezer not to count the current task as freezable. */ +/** + * freezer_do_not_count - tell freezer to ignore %current + * + * Tell freezers to ignore the current task when determining whether the + * target frozen state is reached. IOW, the current task will be + * considered frozen enough by freezers. + * + * The caller shouldn't do anything which isn't allowed for a frozen task + * until freezer_cont() is called. Usually, freezer[_do_not]_count() pair + * wrap a scheduling operation and nothing much else. + */ static inline void freezer_do_not_count(void) { current->flags |= PF_FREEZER_SKIP; } -/* - * Tell the freezer to count the current task as freezable again and try to - * freeze it. +/** + * freezer_count - tell freezer to stop ignoring %current + * + * Undo freezer_do_not_count(). It tells freezers that %current should be + * considered again and tries to freeze if freezing condition is already in + * effect. */ static inline void freezer_count(void) { current->flags &= ~PF_FREEZER_SKIP; + /* + * If freezing is in progress, the following paired with smp_mb() + * in freezer_should_skip() ensures that either we see %true + * freezing() or freezer_should_skip() sees !PF_FREEZER_SKIP. + */ + smp_mb(); try_to_freeze(); } -/* - * Check if the task should be counted as freezable by the freezer +/** + * freezer_should_skip - whether to skip a task when determining frozen + * state is reached + * @p: task in quesion + * + * This function is used by freezers after establishing %true freezing() to + * test whether a task should be skipped when determining the target frozen + * state is reached. IOW, if this function returns %true, @p is considered + * frozen enough. */ -static inline int freezer_should_skip(struct task_struct *p) +static inline bool freezer_should_skip(struct task_struct *p) { - return !!(p->flags & PF_FREEZER_SKIP); + /* + * The following smp_mb() paired with the one in freezer_count() + * ensures that either freezer_count() sees %true freezing() or we + * see cleared %PF_FREEZER_SKIP and return %false. This makes it + * impossible for a task to slip frozen state testing after + * clearing %PF_FREEZER_SKIP. + */ + smp_mb(); + return p->flags & PF_FREEZER_SKIP; } /* -- GitLab From af445c0d36202fe86bc50f0a1831c5661f5b1189 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 31 Oct 2012 17:20:50 +0100 Subject: [PATCH 1314/1799] x86, amd: Disable way access filter on Piledriver CPUs commit 2bbf0a1427c377350f001fbc6260995334739ad7 upstream. The Way Access Filter in recent AMD CPUs may hurt the performance of some workloads, caused by aliasing issues in the L1 cache. This patch disables it on the affected CPUs. The issue is similar to that one of last year: http://lkml.indiana.edu/hypermail/linux/kernel/1107.3/00041.html This new patch does not replace the old one, we just need another quirk for newer CPUs. The performance penalty without the patch depends on the circumstances, but is a bit less than the last year's 3%. The workloads affected would be those that access code from the same physical page under different virtual addresses, so different processes using the same libraries with ASLR or multiple instances of PIE-binaries. The code needs to be accessed simultaneously from both cores of the same compute unit. More details can be found here: http://developer.amd.com/Assets/SharedL1InstructionCacheonAMD15hCPU.pdf CPUs affected are anything with the core known as Piledriver. That includes the new parts of the AMD A-Series (aka Trinity) and the just released new CPUs of the FX-Series (aka Vishera). The model numbering is a bit odd here: FX CPUs have model 2, A-Series has model 10h, with possible extensions to 1Fh. Hence the range of model ids. Signed-off-by: Andre Przywara Link: http://lkml.kernel.org/r/1351700450-9277-1-git-send-email-osp@andrep.de Signed-off-by: H. Peter Anvin Signed-off-by: CAI Qian Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/amd.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 146bb6218eec..6b4976b0cbb2 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -598,6 +598,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) } } + /* + * The way access filter has a performance penalty on some workloads. + * Disable it on the affected CPUs. + */ + if ((c->x86 == 0x15) && + (c->x86_model >= 0x02) && (c->x86_model < 0x20)) { + u64 val; + + if (!rdmsrl_safe(0xc0011021, &val) && !(val & 0x1E)) { + val |= 0x1E; + checking_wrmsrl(0xc0011021, val); + } + } + cpu_detect_cache_sizes(c); /* Multi core CPU? */ -- GitLab From a9b876220838f045ab3c365f668477771e149c3c Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 17 Dec 2012 11:52:47 -0600 Subject: [PATCH 1315/1799] sparc: huge_ptep_set_* functions need to call set_huge_pte_at() [ Upstream commit 6cb9c3697585c47977c42c5cc1b9fc49247ac530 ] Modifying the huge pte's requires that all the underlying pte's be modified. Version 2: added missing flush_tlb_page() Signed-off-by: Dave Kleikamp Cc: "David S. Miller" Cc: sparclinux@vger.kernel.org Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/include/asm/hugetlb.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/sparc/include/asm/hugetlb.h b/arch/sparc/include/asm/hugetlb.h index 177061064ee6..f368cef0379a 100644 --- a/arch/sparc/include/asm/hugetlb.h +++ b/arch/sparc/include/asm/hugetlb.h @@ -58,14 +58,20 @@ static inline pte_t huge_pte_wrprotect(pte_t pte) static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - ptep_set_wrprotect(mm, addr, ptep); + pte_t old_pte = *ptep; + set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); } static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, pte_t pte, int dirty) { - return ptep_set_access_flags(vma, addr, ptep, pte, dirty); + int changed = !pte_same(*ptep, pte); + if (changed) { + set_huge_pte_at(vma->vm_mm, addr, ptep, pte); + flush_tlb_page(vma, addr); + } + return changed; } static inline pte_t huge_ptep_get(pte_t *ptep) -- GitLab From 6eec2413cb320bdd0139ba0db3888d27f746ea2b Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 26 Dec 2012 02:32:10 +0000 Subject: [PATCH 1316/1799] batman-adv: fix random jitter calculation [ Upstream commit 143cdd8f33909ff5a153e3f02048738c5964ba26 ] batadv_iv_ogm_emit_send_time() attempts to calculates a random integer in the range of 'orig_interval +- BATADV_JITTER' by the below lines. msecs = atomic_read(&bat_priv->orig_interval) - BATADV_JITTER; msecs += (random32() % 2 * BATADV_JITTER); But it actually gets 'orig_interval' or 'orig_interval - BATADV_JITTER' because '%' and '*' have same precedence and associativity is left-to-right. This adds the parentheses at the appropriate position so that it matches original intension. Signed-off-by: Akinobu Mita Acked-by: Antonio Quartulli Cc: Marek Lindner Cc: Simon Wunderlich Cc: Antonio Quartulli Cc: b.a.t.m.a.n@lists.open-mesh.org Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/batman-adv/bat_iv_ogm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index a6d5d63fb6ad..fa701b6f7948 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -72,7 +72,7 @@ static unsigned long bat_iv_ogm_emit_send_time(const struct bat_priv *bat_priv) { return jiffies + msecs_to_jiffies( atomic_read(&bat_priv->orig_interval) - - JITTER + (random32() % 2*JITTER)); + JITTER + (random32() % (2*JITTER))); } /* when do we schedule a ogm packet to be sent */ -- GitLab From d46699a94ddf2dd4d83e986a759b64981b37fc5b Mon Sep 17 00:00:00 2001 From: Christoph Paasch Date: Fri, 14 Dec 2012 04:07:58 +0000 Subject: [PATCH 1317/1799] inet: Fix kmemleak in tcp_v4/6_syn_recv_sock and dccp_v4/6_request_recv_sock [ Upstream commit e337e24d6624e74a558aa69071e112a65f7b5758 ] If in either of the above functions inet_csk_route_child_sock() or __inet_inherit_port() fails, the newsk will not be freed: unreferenced object 0xffff88022e8a92c0 (size 1592): comm "softirq", pid 0, jiffies 4294946244 (age 726.160s) hex dump (first 32 bytes): 0a 01 01 01 0a 01 01 02 00 00 00 00 a7 cc 16 00 ................ 02 00 03 01 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [] kmemleak_alloc+0x21/0x3e [] kmem_cache_alloc+0xb5/0xc5 [] sk_prot_alloc.isra.53+0x2b/0xcd [] sk_clone_lock+0x16/0x21e [] inet_csk_clone_lock+0x10/0x7b [] tcp_create_openreq_child+0x21/0x481 [] tcp_v4_syn_recv_sock+0x3a/0x23b [] tcp_check_req+0x29f/0x416 [] tcp_v4_do_rcv+0x161/0x2bc [] tcp_v4_rcv+0x6c9/0x701 [] ip_local_deliver_finish+0x70/0xc4 [] ip_local_deliver+0x4e/0x7f [] ip_rcv_finish+0x1fc/0x233 [] ip_rcv+0x217/0x267 [] __netif_receive_skb+0x49e/0x553 [] netif_receive_skb+0x50/0x82 This happens, because sk_clone_lock initializes sk_refcnt to 2, and thus a single sock_put() is not enough to free the memory. Additionally, things like xfrm, memcg, cookie_values,... may have been initialized. We have to free them properly. This is fixed by forcing a call to tcp_done(), ending up in inet_csk_destroy_sock, doing the final sock_put(). tcp_done() is necessary, because it ends up doing all the cleanup on xfrm, memcg, cookie_values, xfrm,... Before calling tcp_done, we have to set the socket to SOCK_DEAD, to force it entering inet_csk_destroy_sock. To avoid the warning in inet_csk_destroy_sock, inet_num has to be set to 0. As inet_csk_destroy_sock does a dec on orphan_count, we first have to increase it. Calling tcp_done() allows us to remove the calls to tcp_clear_xmit_timer() and tcp_cleanup_congestion_control(). A similar approach is taken for dccp by calling dccp_done(). This is in the kernel since 093d282321 (tproxy: fix hash locking issue when using port redirection in __inet_inherit_port()), thus since version >= 2.6.37. Signed-off-by: Christoph Paasch Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/inet_connection_sock.h | 1 + net/dccp/ipv4.c | 4 ++-- net/dccp/ipv6.c | 3 ++- net/ipv4/inet_connection_sock.c | 16 ++++++++++++++++ net/ipv4/tcp_ipv4.c | 6 ++---- net/ipv6/tcp_ipv6.c | 3 ++- 6 files changed, 25 insertions(+), 8 deletions(-) diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index dbf9aab34c82..e9b05ded948b 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -317,6 +317,7 @@ extern void inet_csk_reqsk_queue_prune(struct sock *parent, const unsigned long max_rto); extern void inet_csk_destroy_sock(struct sock *sk); +extern void inet_csk_prepare_forced_close(struct sock *sk); /* * LISTEN is a special case for poll.. diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index caf6e1734b62..c6f6e425b2e4 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -435,8 +435,8 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb, NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); return NULL; put_and_exit: - bh_unlock_sock(newsk); - sock_put(newsk); + inet_csk_prepare_forced_close(newsk); + dccp_done(newsk); goto exit; } diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 4dc588f520e0..aaa8f8bee9e1 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -611,7 +611,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, newinet->inet_rcv_saddr = LOOPBACK4_IPV6; if (__inet_inherit_port(sk, newsk) < 0) { - sock_put(newsk); + inet_csk_prepare_forced_close(newsk); + dccp_done(newsk); goto out; } __inet6_hash(newsk, NULL); diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 19d66cefd7d3..3f4043258542 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -659,6 +659,22 @@ void inet_csk_destroy_sock(struct sock *sk) } EXPORT_SYMBOL(inet_csk_destroy_sock); +/* This function allows to force a closure of a socket after the call to + * tcp/dccp_create_openreq_child(). + */ +void inet_csk_prepare_forced_close(struct sock *sk) +{ + /* sk_clone_lock locked the socket and set refcnt to 2 */ + bh_unlock_sock(sk); + sock_put(sk); + + /* The below has to be done to allow calling inet_csk_destroy_sock */ + sock_set_flag(sk, SOCK_DEAD); + percpu_counter_inc(sk->sk_prot->orphan_count); + inet_sk(sk)->inet_num = 0; +} +EXPORT_SYMBOL(inet_csk_prepare_forced_close); + int inet_csk_listen_start(struct sock *sk, const int nr_table_entries) { struct inet_sock *inet = inet_sk(sk); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 8f2458df19f0..76f50e1b53af 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1524,10 +1524,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); return NULL; put_and_exit: - tcp_clear_xmit_timers(newsk); - tcp_cleanup_congestion_control(newsk); - bh_unlock_sock(newsk); - sock_put(newsk); + inet_csk_prepare_forced_close(newsk); + tcp_done(newsk); goto exit; } EXPORT_SYMBOL(tcp_v4_syn_recv_sock); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 8a8fa2dd149f..3889e0204183 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1411,7 +1411,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, #endif if (__inet_inherit_port(sk, newsk) < 0) { - sock_put(newsk); + inet_csk_prepare_forced_close(newsk); + tcp_done(newsk); goto out; } __inet6_hash(newsk, NULL); -- GitLab From c7078c2c5da80e387420795a5a0857b1cd711fc9 Mon Sep 17 00:00:00 2001 From: Stefan Hasko Date: Fri, 21 Dec 2012 15:04:59 +0000 Subject: [PATCH 1318/1799] net: sched: integer overflow fix [ Upstream commit d2fe85da52e89b8012ffad010ef352a964725d5f ] Fixed integer overflow in function htb_dequeue Signed-off-by: Stefan Hasko Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/sch_htb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 29b942ce9e82..f08b9166119b 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -876,7 +876,7 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) q->now = psched_get_time(); start_at = jiffies; - next_event = q->now + 5 * PSCHED_TICKS_PER_SEC; + next_event = q->now + 5LLU * PSCHED_TICKS_PER_SEC; for (level = 0; level < TC_HTB_MAXDEPTH; level++) { /* common case optimization - skip event handler quickly */ -- GitLab From c87b45599a4e0d8741abeb85d1d8d5f0c1fb13be Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 6 Jan 2013 18:21:49 +0000 Subject: [PATCH 1319/1799] tcp: fix MSG_SENDPAGE_NOTLAST logic [ Upstream commit ae62ca7b03217be5e74759dc6d7698c95df498b3 ] commit 35f9c09fe9c72e (tcp: tcp_sendpages() should call tcp_push() once) added an internal flag : MSG_SENDPAGE_NOTLAST meant to be set on all frags but the last one for a splice() call. The condition used to set the flag in pipe_to_sendpage() relied on splice() user passing the exact number of bytes present in the pipe, or a smaller one. But some programs pass an arbitrary high value, and the test fails. The effect of this bug is a lack of tcp_push() at the end of a splice(pipe -> socket) call, and possibly very slow or erratic TCP sessions. We should both test sd->total_len and fact that another fragment is in the pipe (pipe->nrbufs > 1) Many thanks to Willy for providing very clear bug report, bisection and test programs. Reported-by: Willy Tarreau Bisected-by: Willy Tarreau Tested-by: Willy Tarreau Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- fs/splice.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/splice.c b/fs/splice.c index 5cac690f8103..bed6a3c29355 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -696,8 +696,10 @@ static int pipe_to_sendpage(struct pipe_inode_info *pipe, return -EINVAL; more = (sd->flags & SPLICE_F_MORE) ? MSG_MORE : 0; - if (sd->len < sd->total_len) + + if (sd->len < sd->total_len && pipe->nrbufs > 1) more |= MSG_SENDPAGE_NOTLAST; + return file->f_op->sendpage(file, buf->page, buf->offset, sd->len, &pos, more); } -- GitLab From 34fb350281ced2a72707a5c0064f69992d440edb Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 17 Jul 2012 10:13:05 +0200 Subject: [PATCH 1320/1799] tcp: implement RFC 5961 3.2 [ Upstream commit 282f23c6ee343126156dd41218b22ece96d747e3 ] Implement the RFC 5691 mitigation against Blind Reset attack using RST bit. Idea is to validate incoming RST sequence, to match RCV.NXT value, instead of previouly accepted window : (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND) If sequence is in window but not an exact match, send a "challenge ACK", so that the other part can resend an RST with the appropriate sequence. Add a new sysctl, tcp_challenge_ack_limit, to limit number of challenge ACK sent per second. Add a new SNMP counter to count number of challenge acks sent. (netstat -s | grep TCPChallengeACK) Signed-off-by: Eric Dumazet Cc: Kiran Kumar Kella Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- Documentation/networking/ip-sysctl.txt | 5 +++++ include/linux/snmp.h | 1 + include/net/tcp.h | 1 + net/ipv4/proc.c | 1 + net/ipv4/sysctl_net_ipv4.c | 7 ++++++ net/ipv4/tcp_input.c | 31 +++++++++++++++++++++++++- 6 files changed, 45 insertions(+), 1 deletion(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 1619a8c80873..797715397f43 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -537,6 +537,11 @@ tcp_thin_dupack - BOOLEAN Documentation/networking/tcp-thin.txt Default: 0 +tcp_challenge_ack_limit - INTEGER + Limits number of Challenge ACK sent per second, as recommended + in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks) + Default: 100 + UDP variables: udp_mem - vector of 3 INTEGERs: min, pressure, max diff --git a/include/linux/snmp.h b/include/linux/snmp.h index 2e68f5ba0389..594638ec5acf 100644 --- a/include/linux/snmp.h +++ b/include/linux/snmp.h @@ -234,6 +234,7 @@ enum LINUX_MIB_TCPREQQFULLDROP, /* TCPReqQFullDrop */ LINUX_MIB_TCPRETRANSFAIL, /* TCPRetransFail */ LINUX_MIB_TCPRCVCOALESCE, /* TCPRcvCoalesce */ + LINUX_MIB_TCPCHALLENGEACK, /* TCPChallengeACK */ __LINUX_MIB_MAX }; diff --git a/include/net/tcp.h b/include/net/tcp.h index f75a04d752cb..2757a115514c 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -252,6 +252,7 @@ extern int sysctl_tcp_max_ssthresh; extern int sysctl_tcp_cookie_size; extern int sysctl_tcp_thin_linear_timeouts; extern int sysctl_tcp_thin_dupack; +extern int sysctl_tcp_challenge_ack_limit; extern atomic_long_t tcp_memory_allocated; extern struct percpu_counter tcp_sockets_allocated; diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 8af0d44e4e22..d589468fd40a 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -258,6 +258,7 @@ static const struct snmp_mib snmp4_net_list[] = { SNMP_MIB_ITEM("TCPReqQFullDrop", LINUX_MIB_TCPREQQFULLDROP), SNMP_MIB_ITEM("TCPRetransFail", LINUX_MIB_TCPRETRANSFAIL), SNMP_MIB_ITEM("TCPRcvCoalesce", LINUX_MIB_TCPRCVCOALESCE), + SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK), SNMP_MIB_SENTINEL }; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 7a7724da9bff..bf7a604c695c 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -590,6 +590,13 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "tcp_challenge_ack_limit", + .data = &sysctl_tcp_challenge_ack_limit, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, #ifdef CONFIG_NET_DMA { .procname = "tcp_dma_copybreak", diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3acebbd15ba0..390541858e40 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -88,6 +88,9 @@ int sysctl_tcp_app_win __read_mostly = 31; int sysctl_tcp_adv_win_scale __read_mostly = 1; EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); +/* rfc5961 challenge ack rate limiting */ +int sysctl_tcp_challenge_ack_limit = 100; + int sysctl_tcp_stdurg __read_mostly; int sysctl_tcp_rfc1337 __read_mostly; int sysctl_tcp_max_orphans __read_mostly = NR_FILE; @@ -5265,6 +5268,23 @@ static int tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb, } #endif /* CONFIG_NET_DMA */ +static void tcp_send_challenge_ack(struct sock *sk) +{ + /* unprotected vars, we dont care of overwrites */ + static u32 challenge_timestamp; + static unsigned int challenge_count; + u32 now = jiffies / HZ; + + if (now != challenge_timestamp) { + challenge_timestamp = now; + challenge_count = 0; + } + if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); + tcp_send_ack(sk); + } +} + /* Does PAWS and seqno based validation of an incoming segment, flags will * play significant role here. */ @@ -5301,7 +5321,16 @@ static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, /* Step 2: check RST bit */ if (th->rst) { - tcp_reset(sk); + /* RFC 5961 3.2 : + * If sequence number exactly matches RCV.NXT, then + * RESET the connection + * else + * Send a challenge ACK + */ + if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) + tcp_reset(sk); + else + tcp_send_challenge_ack(sk); goto discard; } -- GitLab From d21383fcbb535f90b429279852988d675ed22d67 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 17 Jul 2012 01:41:30 +0000 Subject: [PATCH 1321/1799] tcp: implement RFC 5961 4.2 [ Upstream commit 0c24604b68fc7810d429d6c3657b6f148270e528 ] Implement the RFC 5691 mitigation against Blind Reset attack using SYN bit. Section 4.2 of RFC 5961 advises to send a Challenge ACK and drop incoming packet, instead of resetting the session. Add a new SNMP counter to count number of challenge acks sent in response to SYN packets. (netstat -s | grep TCPSYNChallenge) Remove obsolete TCPAbortOnSyn, since we no longer abort a TCP session because of a SYN flag. Signed-off-by: Eric Dumazet Cc: Kiran Kumar Kella Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/snmp.h | 2 +- net/ipv4/proc.c | 2 +- net/ipv4/tcp_input.c | 32 +++++++++++++++----------------- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/include/linux/snmp.h b/include/linux/snmp.h index 594638ec5acf..a33f70fa1bfd 100644 --- a/include/linux/snmp.h +++ b/include/linux/snmp.h @@ -208,7 +208,6 @@ enum LINUX_MIB_TCPDSACKOFOSENT, /* TCPDSACKOfoSent */ LINUX_MIB_TCPDSACKRECV, /* TCPDSACKRecv */ LINUX_MIB_TCPDSACKOFORECV, /* TCPDSACKOfoRecv */ - LINUX_MIB_TCPABORTONSYN, /* TCPAbortOnSyn */ LINUX_MIB_TCPABORTONDATA, /* TCPAbortOnData */ LINUX_MIB_TCPABORTONCLOSE, /* TCPAbortOnClose */ LINUX_MIB_TCPABORTONMEMORY, /* TCPAbortOnMemory */ @@ -235,6 +234,7 @@ enum LINUX_MIB_TCPRETRANSFAIL, /* TCPRetransFail */ LINUX_MIB_TCPRCVCOALESCE, /* TCPRcvCoalesce */ LINUX_MIB_TCPCHALLENGEACK, /* TCPChallengeACK */ + LINUX_MIB_TCPSYNCHALLENGE, /* TCPSYNChallenge */ __LINUX_MIB_MAX }; diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index d589468fd40a..212897517b89 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -232,7 +232,6 @@ static const struct snmp_mib snmp4_net_list[] = { SNMP_MIB_ITEM("TCPDSACKOfoSent", LINUX_MIB_TCPDSACKOFOSENT), SNMP_MIB_ITEM("TCPDSACKRecv", LINUX_MIB_TCPDSACKRECV), SNMP_MIB_ITEM("TCPDSACKOfoRecv", LINUX_MIB_TCPDSACKOFORECV), - SNMP_MIB_ITEM("TCPAbortOnSyn", LINUX_MIB_TCPABORTONSYN), SNMP_MIB_ITEM("TCPAbortOnData", LINUX_MIB_TCPABORTONDATA), SNMP_MIB_ITEM("TCPAbortOnClose", LINUX_MIB_TCPABORTONCLOSE), SNMP_MIB_ITEM("TCPAbortOnMemory", LINUX_MIB_TCPABORTONMEMORY), @@ -259,6 +258,7 @@ static const struct snmp_mib snmp4_net_list[] = { SNMP_MIB_ITEM("TCPRetransFail", LINUX_MIB_TCPRETRANSFAIL), SNMP_MIB_ITEM("TCPRcvCoalesce", LINUX_MIB_TCPRCVCOALESCE), SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK), + SNMP_MIB_ITEM("TCPSYNChallenge", LINUX_MIB_TCPSYNCHALLENGE), SNMP_MIB_SENTINEL }; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 390541858e40..2dc2e1531324 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5288,8 +5288,8 @@ static void tcp_send_challenge_ack(struct sock *sk) /* Does PAWS and seqno based validation of an incoming segment, flags will * play significant role here. */ -static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, - const struct tcphdr *th, int syn_inerr) +static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, + const struct tcphdr *th, int syn_inerr) { const u8 *hash_location; struct tcp_sock *tp = tcp_sk(sk); @@ -5341,20 +5341,22 @@ static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, /* step 3: check security and precedence [ignored] */ - /* step 4: Check for a SYN in window. */ - if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { + /* step 4: Check for a SYN + * RFC 5691 4.2 : Send a challenge ack + */ + if (th->syn) { if (syn_inerr) TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONSYN); - tcp_reset(sk); - return -1; + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE); + tcp_send_challenge_ack(sk); + goto discard; } - return 1; + return true; discard: __kfree_skb(skb); - return 0; + return false; } /* @@ -5384,7 +5386,6 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, const struct tcphdr *th, unsigned int len) { struct tcp_sock *tp = tcp_sk(sk); - int res; /* * Header prediction. @@ -5564,9 +5565,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, * Standard slow path. */ - res = tcp_validate_incoming(sk, skb, th, 1); - if (res <= 0) - return -res; + if (!tcp_validate_incoming(sk, skb, th, 1)) + return 0; step5: if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) @@ -5876,7 +5876,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); int queued = 0; - int res; tp->rx_opt.saw_tstamp = 0; @@ -5931,9 +5930,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, return 0; } - res = tcp_validate_incoming(sk, skb, th, 0); - if (res <= 0) - return -res; + if (!tcp_validate_incoming(sk, skb, th, 0)) + return 0; /* step 5: check the ACK field */ if (th->ack) { -- GitLab From f451931e294c83d811783799f8a6c29929fc8e85 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 17 Jul 2012 12:29:30 +0000 Subject: [PATCH 1322/1799] tcp: refine SYN handling in tcp_validate_incoming [ Upstream commit e371589917011efe6ff8c7dfb4e9e81934ac5855 ] Followup of commit 0c24604b68fc (tcp: implement RFC 5961 4.2) As reported by Vijay Subramanian, we should send a challenge ACK instead of a dup ack if a SYN flag is set on a packet received out of window. This permits the ratelimiting to work as intended, and to increase correct SNMP counters. Suggested-by: Vijay Subramanian Signed-off-by: Eric Dumazet Acked-by: Vijay Subramanian Cc: Kiran Kumar Kella Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_input.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 2dc2e1531324..0070b9fafff4 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5314,8 +5314,11 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, * an acknowledgment should be sent in reply (unless the RST * bit is set, if so drop the segment and return)". */ - if (!th->rst) + if (!th->rst) { + if (th->syn) + goto syn_challenge; tcp_send_dupack(sk, skb); + } goto discard; } @@ -5345,6 +5348,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, * RFC 5691 4.2 : Send a challenge ack */ if (th->syn) { +syn_challenge: if (syn_inerr) TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE); -- GitLab From 29eac3795e2bb2a319f84438d45a4dbcc500cc6c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 13 Nov 2012 05:37:18 +0000 Subject: [PATCH 1323/1799] tcp: tcp_replace_ts_recent() should not be called from tcp_validate_incoming() [ Upstream commit bd090dfc634ddd711a5fbd0cadc6e0ab4977bcaf ] We added support for RFC 5961 in latest kernels but TCP fails to perform exhaustive check of ACK sequence. We can update our view of peer tsval from a frame that is later discarded by tcp_ack() This makes timestamps enabled sessions vulnerable to injection of a high tsval : peers start an ACK storm, since the victim sends a dupack each time it receives an ACK from the other peer. As tcp_validate_incoming() is called before tcp_ack(), we should not peform tcp_replace_ts_recent() from it, and let callers do it at the right time. Signed-off-by: Eric Dumazet Cc: Neal Cardwell Cc: Yuchung Cheng Cc: Nandita Dukkipati Cc: H.K. Jerry Chu Cc: Romain Francoise Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_input.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0070b9fafff4..ac8866c6244b 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5337,11 +5337,6 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, goto discard; } - /* ts_recent update must be made after we are sure that the packet - * is in window. - */ - tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); - /* step 3: check security and precedence [ignored] */ /* step 4: Check for a SYN @@ -5576,6 +5571,11 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) goto discard; + /* ts_recent update must be made after we are sure that the packet + * is in window. + */ + tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); + tcp_rcv_rtt_measure_ts(sk, skb); /* Process urgent data. */ @@ -6046,6 +6046,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, } else goto discard; + /* ts_recent update must be made after we are sure that the packet + * is in window. + */ + tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); + /* step 6: check the URG bit */ tcp_urg(sk, skb, th); -- GitLab From 2ee4432e82437a7c051c254b065fbf5d4581e1a3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 21 Oct 2012 19:57:11 +0000 Subject: [PATCH 1324/1799] tcp: RFC 5961 5.2 Blind Data Injection Attack Mitigation [ Upstream commit 354e4aa391ed50a4d827ff6fc11e0667d0859b25 ] RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] All TCP stacks MAY implement the following mitigation. TCP stacks that implement this mitigation MUST add an additional input check to any incoming segment. The ACK value is considered acceptable only if it is in the range of ((SND.UNA - MAX.SND.WND) <= SEG.ACK <= SND.NXT). All incoming segments whose ACK value doesn't satisfy the above condition MUST be discarded and an ACK sent back. Move tcp_send_challenge_ack() before tcp_ack() to avoid a forward declaration. Signed-off-by: Eric Dumazet Cc: Neal Cardwell Cc: Yuchung Cheng Cc: Jerry Chu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_input.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index ac8866c6244b..0e0b6d0e9a61 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3687,6 +3687,24 @@ static int tcp_process_frto(struct sock *sk, int flag) return 0; } +/* RFC 5961 7 [ACK Throttling] */ +static void tcp_send_challenge_ack(struct sock *sk) +{ + /* unprotected vars, we dont care of overwrites */ + static u32 challenge_timestamp; + static unsigned int challenge_count; + u32 now = jiffies / HZ; + + if (now != challenge_timestamp) { + challenge_timestamp = now; + challenge_count = 0; + } + if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); + tcp_send_ack(sk); + } +} + /* This routine deals with incoming acks, but not outgoing ones. */ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) { @@ -3706,8 +3724,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) /* If the ack is older than previous acks * then we can probably ignore it. */ - if (before(ack, prior_snd_una)) + if (before(ack, prior_snd_una)) { + /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */ + if (before(ack, prior_snd_una - tp->max_window)) { + tcp_send_challenge_ack(sk); + return -1; + } goto old_ack; + } /* If the ack includes data we haven't sent yet, discard * this segment (RFC793 Section 3.9). @@ -5268,23 +5292,6 @@ static int tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb, } #endif /* CONFIG_NET_DMA */ -static void tcp_send_challenge_ack(struct sock *sk) -{ - /* unprotected vars, we dont care of overwrites */ - static u32 challenge_timestamp; - static unsigned int challenge_count; - u32 now = jiffies / HZ; - - if (now != challenge_timestamp) { - challenge_timestamp = now; - challenge_count = 0; - } - if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); - tcp_send_ack(sk); - } -} - /* Does PAWS and seqno based validation of an incoming segment, flags will * play significant role here. */ -- GitLab From 99574fa03e407cad20953d7cbfcb0056f02e811e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 18 Sep 2012 19:18:35 +0100 Subject: [PATCH 1325/1799] ARM: mm: use pteval_t to represent page protection values commit 864aa04cd02979c2c755cb28b5f4fe56039171c0 upstream. When updating the page protection map after calculating the user_pgprot value, the base protection map is temporarily stored in an unsigned long type, causing truncation of the protection bits when LPAE is enabled. This effectively means that calls to mprotect() will corrupt the upper page attributes, clearing the XN bit unconditionally. This patch uses pteval_t to store the intermediate protection values, preserving the upper bits for 64-bit descriptors. Acked-by: Nicolas Pitre Acked-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Greg Kroah-Hartman --- arch/arm/mm/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 7d419193d49a..5df549244d67 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -497,7 +497,7 @@ static void __init build_mem_type_table(void) #endif for (i = 0; i < 16; i++) { - unsigned long v = pgprot_val(protection_map[i]); + pteval_t v = pgprot_val(protection_map[i]); protection_map[i] = __pgprot(v | user_pgprot); } -- GitLab From ebd3b1a320baa264c7662363fa4b930634470a4b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Dec 2012 00:25:57 +0000 Subject: [PATCH 1326/1799] ARM: missing ->mmap_sem around find_vma() in swp_emulate.c commit 7bf9b7bef881aac820bf1f2e9951a17b09bd7e04 upstream. find_vma() is *not* safe when somebody else is removing vmas. Not just the return value might get bogus just as you are getting it (this instance doesn't try to dereference the resulting vma), the search itself can get buggered in rather spectacular ways. IOW, ->mmap_sem really, really is not optional here. Signed-off-by: Al Viro Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/swp_emulate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c index df745188f5de..ab1017bd1667 100644 --- a/arch/arm/kernel/swp_emulate.c +++ b/arch/arm/kernel/swp_emulate.c @@ -109,10 +109,12 @@ static void set_segfault(struct pt_regs *regs, unsigned long addr) { siginfo_t info; + down_read(¤t->mm->mmap_sem); if (find_vma(current->mm, addr) == NULL) info.si_code = SEGV_MAPERR; else info.si_code = SEGV_ACCERR; + up_read(¤t->mm->mmap_sem); info.si_signo = SIGSEGV; info.si_errno = 0; -- GitLab From 042279bf26576ada65948ea45ab7ac86e0490c0a Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 19 Dec 2012 15:01:50 +0100 Subject: [PATCH 1327/1799] ARM: 7607/1: realview: fix private peripheral memory base for EB rev. B boards commit e6ee4b2b57a8e0d8e551031173de080b338d3969 upstream. Commit 34ae6c96a6a7 ("ARM: 7298/1: realview: fix mapping of MPCore private memory region") accidentally broke the definition for the base address of the private peripheral region on revision B Realview-EB boards. This patch uses the correct address for REALVIEW_EB11MP_PRIV_MEM_BASE. Acked-by: Marc Zyngier Tested-by: Florian Fainelli Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-realview/include/mach/board-eb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-realview/include/mach/board-eb.h b/arch/arm/mach-realview/include/mach/board-eb.h index 124bce6b4d7b..a301e61a5554 100644 --- a/arch/arm/mach-realview/include/mach/board-eb.h +++ b/arch/arm/mach-realview/include/mach/board-eb.h @@ -47,7 +47,7 @@ #define REALVIEW_EB_USB_BASE 0x4F000000 /* USB */ #ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB -#define REALVIEW_EB11MP_PRIV_MEM_BASE 0x1F000000 +#define REALVIEW_EB11MP_PRIV_MEM_BASE 0x10100000 #define REALVIEW_EB11MP_L220_BASE 0x10102000 /* L220 registers */ #define REALVIEW_EB11MP_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */ #else -- GitLab From fdbe6fecef94b6171de7a2ccfe543a694c9c41bc Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 11 Dec 2012 14:57:14 +0000 Subject: [PATCH 1328/1799] solos-pci: fix double-free of TX skb in DMA mode commit cae49ede00ec3d0cda290b03fee55b72b49efc11 upstream. We weren't clearing card->tx_skb[port] when processing the TX done interrupt. If there wasn't another skb ready to transmit immediately, this led to a double-free because we'd free it *again* next time we did have a packet to send. Signed-off-by: David Woodhouse Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/atm/solos-pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 98510931c815..1853a45c668c 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -967,10 +967,11 @@ static uint32_t fpga_tx(struct solos_card *card) for (port = 0; tx_pending; tx_pending >>= 1, port++) { if (tx_pending & 1) { struct sk_buff *oldskb = card->tx_skb[port]; - if (oldskb) + if (oldskb) { pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr, oldskb->len, PCI_DMA_TODEVICE); - + card->tx_skb[port] = NULL; + } spin_lock(&card->tx_queue_lock); skb = skb_dequeue(&card->tx_queue[port]); if (!skb) -- GitLab From 7164ac211086207dc371e3b32165226e28e2dcfa Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sat, 1 Dec 2012 12:37:20 -0800 Subject: [PATCH 1329/1799] PCI: Reduce Ricoh 0xe822 SD card reader base clock frequency to 50MHz commit 812089e01b9f65f90fc8fc670d8cce72a0e01fbb upstream. Otherwise it fails like this on cards like the Transcend 16GB SDHC card: mmc0: new SDHC card at address b368 mmcblk0: mmc0:b368 SDC 15.0 GiB mmcblk0: error -110 sending status command, retrying mmcblk0: error -84 transferring data, sector 0, nr 8, cmd response 0x900, card status 0xb0 Tested on my Lenovo x200 laptop. [bhelgaas: changelog] Signed-off-by: Andy Lutomirski Signed-off-by: Bjorn Helgaas Acked-by: Chris Ball CC: Manoj Iyer Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 7 +++++-- include/linux/pci_ids.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 4bf71028556b..680dbfa1b614 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2708,7 +2708,7 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) if (PCI_FUNC(dev->devfn)) return; /* - * RICOH 0xe823 SD/MMC card reader fails to recognize + * RICOH 0xe822 and 0xe823 SD/MMC card readers fail to recognize * certain types of SD/MMC cards. Lowering the SD base * clock frequency from 200Mhz to 50Mhz fixes this issue. * @@ -2719,7 +2719,8 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) * 0xf9 - Key register for 0x150 * 0xfc - key register for 0xe1 */ - if (dev->device == PCI_DEVICE_ID_RICOH_R5CE823) { + if (dev->device == PCI_DEVICE_ID_RICOH_R5CE822 || + 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); @@ -2746,6 +2747,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_R5CE822, ricoh_mmc_fixup_r5c832); +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE822, 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*/ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index bf7934f4268f..d7dbf4ec89d2 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1565,6 +1565,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_R5CE822 0xe822 #define PCI_DEVICE_ID_RICOH_R5CE823 0xe823 #define PCI_DEVICE_ID_RICOH_R5C832 0x0832 #define PCI_DEVICE_ID_RICOH_R5C843 0x0843 -- GitLab From 2145cea1e0be3262768fef384a87f426ecad06fe Mon Sep 17 00:00:00 2001 From: Marcos Chaparro Date: Tue, 6 Nov 2012 16:19:11 -0300 Subject: [PATCH 1330/1799] Bluetooth: ath3k: Add support for VAIO VPCEH [0489:e027] commit acd9454433e28c1a365d8b069813c35c1c3a8ac3 upstream. Added Atheros AR3011 internal bluetooth device found in Sony VAIO VPCEH to the devices list. Before this, the bluetooth module was identified as an Foxconn / Hai bluetooth device [0489:e027], now it claims to be an AtherosAR3011 Bluetooth [0cf3:3005]. T: Bus=01 Lev=02 Prnt=02 Port=04 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0489 ProdID=e027 Rev= 0.01 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) 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= 25 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 25 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= 33 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 33 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= 49 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms Signed-off-by: Marcos Chaparro Signed-off-by: Gustavo Padovan Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/bluetooth/ath3k.c | 1 + drivers/bluetooth/btusb.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 57fd867553d7..1ae7039f067a 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -66,6 +66,7 @@ static struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x13d3, 0x3304) }, { USB_DEVICE(0x0930, 0x0215) }, { USB_DEVICE(0x0489, 0xE03D) }, + { USB_DEVICE(0x0489, 0xE027) }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03F0, 0x311D) }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 29d31ff7331d..27f9d9fc5a06 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -130,6 +130,7 @@ static struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, -- GitLab From 7e2741804be03faf0eaba1df228e2ba5c07ecdd7 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Tue, 20 Nov 2012 23:25:54 -0200 Subject: [PATCH 1331/1799] Bluetooth: Add missing lock nesting notation commit dc2a0e20fbc85a71c63aa4330b496fda33f6bf80 upstream. This patch fixes the following report, it happens when accepting rfcomm connections: [ 228.165378] ============================================= [ 228.165378] [ INFO: possible recursive locking detected ] [ 228.165378] 3.7.0-rc1-00536-gc1d5dc4 #120 Tainted: G W [ 228.165378] --------------------------------------------- [ 228.165378] bluetoothd/1341 is trying to acquire lock: [ 228.165378] (sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM){+.+...}, at: [] bt_accept_dequeue+0xa0/0x180 [bluetooth] [ 228.165378] [ 228.165378] but task is already holding lock: [ 228.165378] (sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM){+.+...}, at: [] rfcomm_sock_accept+0x58/0x2d0 [rfcomm] [ 228.165378] [ 228.165378] other info that might help us debug this: [ 228.165378] Possible unsafe locking scenario: [ 228.165378] [ 228.165378] CPU0 [ 228.165378] ---- [ 228.165378] lock(sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM); [ 228.165378] lock(sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM); [ 228.165378] [ 228.165378] *** DEADLOCK *** [ 228.165378] [ 228.165378] May be due to missing lock nesting notation Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/rfcomm/sock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 717c43ac0c78..8d1edd7207df 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -485,7 +485,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f long timeo; int err = 0; - lock_sock(sk); + lock_sock_nested(sk, SINGLE_DEPTH_NESTING); if (sk->sk_type != SOCK_STREAM) { err = -EINVAL; @@ -522,7 +522,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f release_sock(sk); timeo = schedule_timeout(timeo); - lock_sock(sk); + lock_sock_nested(sk, SINGLE_DEPTH_NESTING); } __set_current_state(TASK_RUNNING); remove_wait_queue(sk_sleep(sk), &wait); -- GitLab From 1a0da46b46bc9b27414fcb1f1ad6f0eeee311f5e Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 21 Nov 2012 00:50:21 -0200 Subject: [PATCH 1332/1799] Bluetooth: cancel power_on work when unregistering the device commit b9b5ef188e5a2222cfc16ef62a4703080750b451 upstream. We need to cancel the hci_power_on work in order to avoid it run when we try to free the hdev. [ 1434.201149] ------------[ cut here ]------------ [ 1434.204998] WARNING: at lib/debugobjects.c:261 debug_print_object+0x8e/0xb0() [ 1434.208324] ODEBUG: free active (active state 0) object type: work_struct hint: hci _power_on+0x0/0x90 [ 1434.210386] Pid: 8564, comm: trinity-child25 Tainted: G W 3.7.0-rc5-next- 20121112-sasha-00018-g2f4ce0e #127 [ 1434.210760] Call Trace: [ 1434.210760] [] ? debug_print_object+0x8e/0xb0 [ 1434.210760] [] warn_slowpath_common+0x87/0xb0 [ 1434.210760] [] warn_slowpath_fmt+0x41/0x50 [ 1434.210760] [] debug_print_object+0x8e/0xb0 [ 1434.210760] [] ? hci_dev_open+0x310/0x310 [ 1434.210760] [] ? _raw_spin_unlock_irqrestore+0x55/0xa0 [ 1434.210760] [] __debug_check_no_obj_freed+0xa5/0x230 [ 1434.210760] [] ? bt_host_release+0x10/0x20 [ 1434.210760] [] debug_check_no_obj_freed+0x15/0x20 [ 1434.210760] [] kfree+0x227/0x330 [ 1434.210760] [] bt_host_release+0x10/0x20 [ 1434.210760] [] device_release+0x65/0xc0 [ 1434.210760] [] kobject_cleanup+0x145/0x190 [ 1434.210760] [] kobject_release+0xd/0x10 [ 1434.210760] [] kobject_put+0x4c/0x60 [ 1434.210760] [] put_device+0x12/0x20 [ 1434.210760] [] hci_free_dev+0x24/0x30 [ 1434.210760] [] vhci_release+0x31/0x60 [ 1434.210760] [] __fput+0x122/0x250 [ 1434.210760] [] ? rcu_user_exit+0x9d/0xd0 [ 1434.210760] [] ____fput+0x9/0x10 [ 1434.210760] [] task_work_run+0xb2/0xf0 [ 1434.210760] [] do_notify_resume+0x77/0xa0 [ 1434.210760] [] int_signal+0x12/0x17 [ 1434.210760] ---[ end trace a6d57fefbc8a8cc7 ]--- Reported-by: Sasha Levin Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hci_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 0a30ec10d40f..13b6c28df1f1 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1866,6 +1866,8 @@ void hci_unregister_dev(struct hci_dev *hdev) for (i = 0; i < NUM_REASSEMBLY; i++) kfree_skb(hdev->reassembly[i]); + cancel_work_sync(&hdev->power_on); + if (!test_bit(HCI_INIT, &hdev->flags) && !test_bit(HCI_SETUP, &hdev->dev_flags)) { hci_dev_lock(hdev); -- GitLab From 0f7ac9c81bdb08763e7ca02317592281e22542bc Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 19 Dec 2012 23:39:48 -0800 Subject: [PATCH 1333/1799] lib: atomic64: Initialize locks statically to fix early users commit fcc16882ac4532aaa644bff444f0c5d6228ba71e upstream. The atomic64 library uses a handful of static spin locks to implement atomic 64-bit operations on architectures without support for atomic 64-bit instructions. Unfortunately, the spinlocks are initialized in a pure initcall and that is too late for the vfs namespace code which wants to use atomic64 operations before the initcall is run. This became a problem as of commit 8823c079ba71: "vfs: Add setns support for the mount namespace". This leads to BUG messages such as: BUG: spinlock bad magic on CPU#0, swapper/0/0 lock: atomic64_lock+0x240/0x400, .magic: 00000000, .owner: /-1, .owner_cpu: 0 do_raw_spin_lock+0x158/0x198 _raw_spin_lock_irqsave+0x4c/0x58 atomic64_add_return+0x30/0x5c alloc_mnt_ns.clone.14+0x44/0xac create_mnt_ns+0xc/0x54 mnt_init+0x120/0x1d4 vfs_caches_init+0xe0/0x10c start_kernel+0x29c/0x300 coming out early on during boot when spinlock debugging is enabled. Fix this by initializing the spinlocks statically at compile time. Reported-and-tested-by: Vaibhav Bedia Tested-by: Tony Lindgren Cc: Eric W. Biederman Signed-off-by: Stephen Boyd Signed-off-by: Linus Torvalds Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- lib/atomic64.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/lib/atomic64.c b/lib/atomic64.c index 978537809d84..08a4f068e61e 100644 --- a/lib/atomic64.c +++ b/lib/atomic64.c @@ -31,7 +31,11 @@ static union { raw_spinlock_t lock; char pad[L1_CACHE_BYTES]; -} atomic64_lock[NR_LOCKS] __cacheline_aligned_in_smp; +} atomic64_lock[NR_LOCKS] __cacheline_aligned_in_smp = { + [0 ... (NR_LOCKS - 1)] = { + .lock = __RAW_SPIN_LOCK_UNLOCKED(atomic64_lock.lock), + }, +}; static inline raw_spinlock_t *lock_addr(const atomic64_t *v) { @@ -173,14 +177,3 @@ int atomic64_add_unless(atomic64_t *v, long long a, long long u) return ret; } EXPORT_SYMBOL(atomic64_add_unless); - -static int init_atomic64_lock(void) -{ - int i; - - for (i = 0; i < NR_LOCKS; ++i) - raw_spin_lock_init(&atomic64_lock[i].lock); - return 0; -} - -pure_initcall(init_atomic64_lock); -- GitLab From 850fcad11762fae7b25c6a9d3fdb5ff4d7a39420 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 18 Dec 2012 14:21:19 -0800 Subject: [PATCH 1334/1799] CRIS: fix I/O macros commit c24bf9b4cc6a0f330ea355d73bfdf1dae7e63a05 upstream. The inb/outb macros for CRIS are broken from a number of points of view, missing () around parameters and they have an unprotected if statement in them. This was breaking the compile of IPMI on CRIS and thus I was being annoyed by build regressions, so I fixed them. Plus I don't think they would have worked at all, since the data values were missing "&" and the outsl had a "3" instead of a "4" for the size. From what I can tell, this stuff is not used at all, so this can't be any more broken than it was before, anyway. Signed-off-by: Corey Minyard Cc: Jesper Nilsson Cc: Mikael Starvik Acked-by: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/cris/include/asm/io.h | 39 ++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/arch/cris/include/asm/io.h b/arch/cris/include/asm/io.h index 32567bc2a421..ac12ae2b9286 100644 --- a/arch/cris/include/asm/io.h +++ b/arch/cris/include/asm/io.h @@ -133,12 +133,39 @@ static inline void writel(unsigned int b, volatile void __iomem *addr) #define insb(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,1,count) : 0) #define insw(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,2,count) : 0) #define insl(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,4,count) : 0) -#define outb(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,1,1) -#define outw(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,2,1) -#define outl(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,4,1) -#define outsb(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,1,count) -#define outsw(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,2,count) -#define outsl(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,3,count) +static inline void outb(unsigned char data, unsigned int port) +{ + if (cris_iops) + cris_iops->write_io(port, (void *) &data, 1, 1); +} +static inline void outw(unsigned short data, unsigned int port) +{ + if (cris_iops) + cris_iops->write_io(port, (void *) &data, 2, 1); +} +static inline void outl(unsigned int data, unsigned int port) +{ + if (cris_iops) + cris_iops->write_io(port, (void *) &data, 4, 1); +} +static inline void outsb(unsigned int port, const void *addr, + unsigned long count) +{ + if (cris_iops) + cris_iops->write_io(port, (void *)addr, 1, count); +} +static inline void outsw(unsigned int port, const void *addr, + unsigned long count) +{ + if (cris_iops) + cris_iops->write_io(port, (void *)addr, 2, count); +} +static inline void outsl(unsigned int port, const void *addr, + unsigned long count) +{ + if (cris_iops) + cris_iops->write_io(port, (void *)addr, 4, count); +} /* * Convert a physical pointer to a virtual kernel pointer for /dev/mem -- GitLab From 8f4d9c2f748cab8ef5a30e9d9e5261679af3462f Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Fri, 4 Jan 2013 15:35:47 -0800 Subject: [PATCH 1335/1799] drivers/rtc/rtc-vt8500.c: correct handling of CR_24H bitfield commit 532db570e5181abc8f4f7bfa6c77c69ec2240198 upstream. Control register bitfield for 12H/24H mode is handled incorrectly. Setting CR_24H actually enables 12H mode. This patch renames the define and changes the initialization code to correctly set 24H mode. Signed-off-by: Tony Prisk Cc: Edgar Toernig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-vt8500.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index 9e94fb147c26..5641ac5c65fa 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -69,7 +69,7 @@ | ALARM_SEC_BIT) #define VT8500_RTC_CR_ENABLE (1 << 0) /* Enable RTC */ -#define VT8500_RTC_CR_24H (1 << 1) /* 24h time format */ +#define VT8500_RTC_CR_12H (1 << 1) /* 12h time format */ #define VT8500_RTC_CR_SM_ENABLE (1 << 2) /* Enable periodic irqs */ #define VT8500_RTC_CR_SM_SEC (1 << 3) /* 0: 1Hz/60, 1: 1Hz */ #define VT8500_RTC_CR_CALIB (1 << 4) /* Enable calibration */ @@ -248,7 +248,7 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev) } /* Enable RTC and set it to 24-hour mode */ - writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H, + writel(VT8500_RTC_CR_ENABLE, vt8500_rtc->regbase + VT8500_RTC_CR); vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev, -- GitLab From e0996e350216f727b0f0e6219e79c8da5b3d1416 Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Fri, 4 Jan 2013 15:35:48 -0800 Subject: [PATCH 1336/1799] drivers/rtc/rtc-vt8500.c: fix handling of data passed in struct rtc_time commit 2f90b68309683f2c5765a1b04ca23d71e51f1494 upstream. tm_mon is 0..11, whereas vt8500 expects 1..12 for the month field, causing invalid date errors for January, and causing the day field to roll over incorrectly. The century flag is only handled in vt8500_rtc_read_time, but not set in vt8500_rtc_set_time. This patch corrects the behaviour of the century flag. Signed-off-by: Edgar Toernig Signed-off-by: Tony Prisk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-vt8500.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index 5641ac5c65fa..44878da1f064 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -118,7 +118,7 @@ static int vt8500_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_min = bcd2bin((time & TIME_MIN_MASK) >> TIME_MIN_S); tm->tm_hour = bcd2bin((time & TIME_HOUR_MASK) >> TIME_HOUR_S); tm->tm_mday = bcd2bin(date & DATE_DAY_MASK); - tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S); + tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S) - 1; tm->tm_year = bcd2bin((date & DATE_YEAR_MASK) >> DATE_YEAR_S) + ((date >> DATE_CENTURY_S) & 1 ? 200 : 100); tm->tm_wday = (time & TIME_DOW_MASK) >> TIME_DOW_S; @@ -137,8 +137,9 @@ static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm) } writel((bin2bcd(tm->tm_year - 100) << DATE_YEAR_S) - | (bin2bcd(tm->tm_mon) << DATE_MONTH_S) - | (bin2bcd(tm->tm_mday)), + | (bin2bcd(tm->tm_mon + 1) << DATE_MONTH_S) + | (bin2bcd(tm->tm_mday)) + | ((tm->tm_year >= 200) << DATE_CENTURY_S), vt8500_rtc->regbase + VT8500_RTC_DS); writel((bin2bcd(tm->tm_wday) << TIME_DOW_S) | (bin2bcd(tm->tm_hour) << TIME_HOUR_S) -- GitLab From b14d552774ed848ca1ca94d8adedcd743e3aa671 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Fri, 4 Jan 2013 15:35:12 -0800 Subject: [PATCH 1337/1799] mm: limit mmu_gather batching to fix soft lockups on !CONFIG_PREEMPT commit 53a59fc67f97374758e63a9c785891ec62324c81 upstream. Since commit e303297e6c3a ("mm: extended batches for generic mmu_gather") we are batching pages to be freed until either tlb_next_batch cannot allocate a new batch or we are done. This works just fine most of the time but we can get in troubles with non-preemptible kernel (CONFIG_PREEMPT_NONE or CONFIG_PREEMPT_VOLUNTARY) on large machines where too aggressive batching might lead to soft lockups during process exit path (exit_mmap) because there are no scheduling points down the free_pages_and_swap_cache path and so the freeing can take long enough to trigger the soft lockup. The lockup is harmless except when the system is setup to panic on softlockup which is not that unusual. The simplest way to work around this issue is to limit the maximum number of batches in a single mmu_gather. 10k of collected pages should be safe to prevent from soft lockups (we would have 2ms for one) even if they are all freed without an explicit scheduling point. This patch doesn't add any new explicit scheduling points because it relies on zap_pmd_range during page tables zapping which calls cond_resched per PMD. The following lockup has been reported for 3.0 kernel with a huge process (in order of hundreds gigs but I do know any more details). BUG: soft lockup - CPU#56 stuck for 22s! [kernel:31053] Modules linked in: af_packet nfs lockd fscache auth_rpcgss nfs_acl sunrpc mptctl mptbase autofs4 binfmt_misc dm_round_robin dm_multipath bonding cpufreq_conservative cpufreq_userspace cpufreq_powersave pcc_cpufreq mperf microcode fuse loop osst sg sd_mod crc_t10dif st qla2xxx scsi_transport_fc scsi_tgt netxen_nic i7core_edac iTCO_wdt joydev e1000e serio_raw pcspkr edac_core iTCO_vendor_support acpi_power_meter rtc_cmos hpwdt hpilo button container usbhid hid dm_mirror dm_region_hash dm_log linear uhci_hcd ehci_hcd usbcore usb_common scsi_dh_emc scsi_dh_alua scsi_dh_hp_sw scsi_dh_rdac scsi_dh dm_snapshot pcnet32 mii edd dm_mod raid1 ext3 mbcache jbd fan thermal processor thermal_sys hwmon cciss scsi_mod Supported: Yes CPU 56 Pid: 31053, comm: kernel Not tainted 3.0.31-0.9-default #1 HP ProLiant DL580 G7 RIP: 0010: _raw_spin_unlock_irqrestore+0x8/0x10 RSP: 0018:ffff883ec1037af0 EFLAGS: 00000206 RAX: 0000000000000e00 RBX: ffffea01a0817e28 RCX: ffff88803ffd9e80 RDX: 0000000000000200 RSI: 0000000000000206 RDI: 0000000000000206 RBP: 0000000000000002 R08: 0000000000000001 R09: ffff887ec724a400 R10: 0000000000000000 R11: dead000000200200 R12: ffffffff8144c26e R13: 0000000000000030 R14: 0000000000000297 R15: 000000000000000e FS: 00007ed834282700(0000) GS:ffff88c03f200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 000000000068b240 CR3: 0000003ec13c5000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process kernel (pid: 31053, threadinfo ffff883ec1036000, task ffff883ebd5d4100) Call Trace: release_pages+0xc5/0x260 free_pages_and_swap_cache+0x9d/0xc0 tlb_flush_mmu+0x5c/0x80 tlb_finish_mmu+0xe/0x50 exit_mmap+0xbd/0x120 mmput+0x49/0x120 exit_mm+0x122/0x160 do_exit+0x17a/0x430 do_group_exit+0x3d/0xb0 get_signal_to_deliver+0x247/0x480 do_signal+0x71/0x1b0 do_notify_resume+0x98/0xb0 int_signal+0x12/0x17 DWARF2 unwinder stuck at int_signal+0x12/0x17 Signed-off-by: Michal Hocko Cc: Mel Gorman Cc: Rik van Riel Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/asm-generic/tlb.h | 9 +++++++++ mm/memory.c | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h index f96a5b58a975..979ed15724a2 100644 --- a/include/asm-generic/tlb.h +++ b/include/asm-generic/tlb.h @@ -78,6 +78,14 @@ struct mmu_gather_batch { #define MAX_GATHER_BATCH \ ((PAGE_SIZE - sizeof(struct mmu_gather_batch)) / sizeof(void *)) +/* + * Limit the maximum number of mmu_gather batches to reduce a risk of soft + * lockups for non-preemptible kernels on huge machines when a lot of memory + * is zapped during unmapping. + * 10K pages freed at once should be safe even without a preemption point. + */ +#define MAX_GATHER_BATCH_COUNT (10000UL/MAX_GATHER_BATCH) + /* struct mmu_gather is an opaque type used by the mm code for passing around * any data needed by arch specific code for tlb_remove_page. */ @@ -94,6 +102,7 @@ struct mmu_gather { struct mmu_gather_batch *active; struct mmu_gather_batch local; struct page *__pages[MMU_GATHER_BUNDLE]; + unsigned int batch_count; }; #define HAVE_GENERIC_MMU_GATHER diff --git a/mm/memory.c b/mm/memory.c index 6105f475fa86..024b4afc41fc 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -182,10 +182,14 @@ static int tlb_next_batch(struct mmu_gather *tlb) return 1; } + if (tlb->batch_count == MAX_GATHER_BATCH_COUNT) + return 0; + batch = (void *)__get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0); if (!batch) return 0; + tlb->batch_count++; batch->next = NULL; batch->nr = 0; batch->max = MAX_GATHER_BATCH; @@ -212,6 +216,7 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm) tlb->local.nr = 0; tlb->local.max = ARRAY_SIZE(tlb->__pages); tlb->active = &tlb->local; + tlb->batch_count = 0; #ifdef CONFIG_HAVE_RCU_TABLE_FREE tlb->batch = NULL; -- GitLab From c0c7cf289528474c46ce4e851ed33c467c32720c Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 2 Dec 2012 14:38:23 +0000 Subject: [PATCH 1338/1799] HID: Add Apple wireless keyboard 2011 ANSI to special driver list commit f9af7b9edccb87d4d80b58687ab63e58f3b64c4c upstream. Commit 0a97e1e9f9a6 ('HID: apple: Add Apple wireless keyboard 2011 ANSI PID') did not update the special driver list in hid-core.c, so hid-generic may still bind to this device. Reported-by: Ari Pollak References: http://bugs.debian.org/694546 Signed-off-by: Ben Hutchings Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 41d4437411c3..1a92a271adb6 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1385,6 +1385,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { 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) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) }, { 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) }, -- GitLab From 4ca05c86fde5ea8fd6b1929cb0e14b7993de9ba1 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Tue, 27 Nov 2012 08:52:34 +0100 Subject: [PATCH 1339/1799] can: Do not call dev_put if restart timer is running upon close commit ab48b03ec9ae1840a1e427e2375bd0d9d554b4ed upstream. If the restart timer is running due to BUS-OFF and the device is disconnected an dev_put will decrease the usage counter to -1 thus blocking the interface removal, resulting in the following dmesg lines repeating every 10s: can: notifier: receive list not found for dev can0 can: notifier: receive list not found for dev can0 can: notifier: receive list not found for dev can0 unregister_netdevice: waiting for can0 to become free. Usage count = -1 Signed-off-by: Alexander Stein Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/dev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index c5fe3a3db8c9..e86f4c37f981 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -576,8 +576,7 @@ void close_candev(struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); - if (del_timer_sync(&priv->restart_timer)) - dev_put(dev); + del_timer_sync(&priv->restart_timer); can_flush_echo_skb(dev); } EXPORT_SYMBOL_GPL(close_candev); -- GitLab From 0ba1cd8da86b7c4717852e786bacc7154b62d95c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 11 Jan 2013 09:09:13 -0800 Subject: [PATCH 1340/1799] Linux 3.4.25 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a3e12e687c67..0913881e4568 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 24 +SUBLEVEL = 25 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 7e7791e17f932363b8194a68f531d11952861993 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 20 Nov 2012 10:02:06 +0900 Subject: [PATCH 1341/1799] regulator: wm831x: Set the new rather than old value for DVS VSEL commit 13ae633cf729b0ecb677b75b04886ff8fada8fad upstream. Reported-by: Guennadi Liakhovetski Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/regulator/wm831x-dcdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index ff810e787eac..97bb31d0bbef 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -330,7 +330,7 @@ static int wm831x_buckv_set_voltage(struct regulator_dev *rdev, if (vsel > dcdc->dvs_vsel) { ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, - dcdc->dvs_vsel); + vsel); if (ret == 0) dcdc->dvs_vsel = vsel; else -- GitLab From 2686f897e696630f02455b5fa269dd90312f5c8d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 10 Dec 2012 16:40:41 +0100 Subject: [PATCH 1342/1799] ath5k: fix tx path skb leaks commit 596ab5ec3bf10a22be30d7cb1d903a4b83fd607c upstream. ieee80211_free_txskb() needs to be used instead of dev_kfree_skb_any for tx packets passed to the driver from mac80211 Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath5k/base.c | 4 ++-- drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 0e643b016b32..c7d1437c7709 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -843,7 +843,7 @@ ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf) return; dma_unmap_single(ah->dev, bf->skbaddr, bf->skb->len, DMA_TO_DEVICE); - dev_kfree_skb_any(bf->skb); + ieee80211_free_txskb(ah->hw, bf->skb); bf->skb = NULL; bf->skbaddr = 0; bf->desc->ds_data = 0; @@ -1570,7 +1570,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, return; drop_packet: - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); } static void diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 5c5329955414..5d1be4daa56a 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -59,7 +59,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) u16 qnum = skb_get_queue_mapping(skb); if (WARN_ON(qnum >= ah->ah_capabilities.cap_queues.q_tx_num)) { - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); return; } -- GitLab From 8fcd6a440a3d01216bd6d88ce00e7353b1813ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 10 Dec 2012 07:53:56 +0100 Subject: [PATCH 1343/1799] bcma: mips: fix clearing device IRQ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit cbbc0138efe1dcd5426b8fc5d87741f5057aee72 upstream. We were using wrong IRQ number so clearing wasn't working at all. Depending on a platform this could result in a one device having two interrupts assigned. On BCM4706 this resulted in all IRQs being broken. Signed-off-by: Rafał Miłecki Cc: Hauke Mehrtens Acked-by: Hauke Mehrtens Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/bcma/driver_mips.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c index c3e9dff4224e..041fddfd01a0 100644 --- a/drivers/bcma/driver_mips.c +++ b/drivers/bcma/driver_mips.c @@ -115,7 +115,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) & ~(1 << irqflag)); else - bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0); + bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0); /* assign the new one */ if (irq == 0) { -- GitLab From 55800cd51f64300f66c9c0e6eda015e1d6626a57 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sun, 11 Nov 2012 19:01:05 +0000 Subject: [PATCH 1344/1799] powerpc: Fix CONFIG_RELOCATABLE=y CONFIG_CRASH_DUMP=n build commit 11ee7e99f35ecb15f59b21da6a82d96d2cd3fcc8 upstream. If we build a kernel with CONFIG_RELOCATABLE=y CONFIG_CRASH_DUMP=n, the kernel fails when we run at a non zero offset. It turns out we were incorrectly wrapping some of the relocatable kernel code with CONFIG_CRASH_DUMP. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/head_64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 58bddee8e1e8..9e07bd038dda 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -422,7 +422,7 @@ _STATIC(__after_prom_start) tovirt(r6,r6) /* on booke, we already run at PAGE_OFFSET */ #endif -#ifdef CONFIG_CRASH_DUMP +#ifdef CONFIG_RELOCATABLE /* * Check if the kernel has to be running as relocatable kernel based on the * variable __run_at_load, if it is set the kernel is treated as relocatable -- GitLab From 23c4e04a835e6b538efc431e7310af9e924d6978 Mon Sep 17 00:00:00 2001 From: Shan Hai Date: Thu, 8 Nov 2012 15:57:49 +0000 Subject: [PATCH 1345/1799] powerpc/vdso: Remove redundant locking in update_vsyscall_tz() commit ce73ec6db47af84d1466402781ae0872a9e7873c upstream. The locking in update_vsyscall_tz() is not only unnecessary because the vdso code copies the data unproteced in __kernel_gettimeofday() but also introduces a hard to reproduce race condition between update_vsyscall() and update_vsyscall_tz(), which causes user space process to loop forever in vdso code. The following patch removes the locking from update_vsyscall_tz(). Locking is not only unnecessary because the vdso code copies the data unprotected in __kernel_gettimeofday() but also erroneous because updating the tb_update_count is not atomic and introduces a hard to reproduce race condition between update_vsyscall() and update_vsyscall_tz(), which further causes user space process to loop forever in vdso code. The below scenario describes the race condition, x==0 Boot CPU other CPU proc_P: x==0 timer interrupt update_vsyscall x==1 x++;sync settimeofday update_vsyscall_tz x==2 x++;sync x==3 sync;x++ sync;x++ proc_P: x==3 (loops until x becomes even) Because the ++ operator would be implemented as three instructions and not atomic on powerpc. A similar change was made for x86 in commit 6c260d58634 ("x86: vdso: Remove bogus locking in update_vsyscall_tz") Signed-off-by: Shan Hai Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/time.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 730e69cb7e9b..e7dba0b2a170 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -749,13 +749,8 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm, void update_vsyscall_tz(void) { - /* Make userspace gettimeofday spin until we're done. */ - ++vdso_data->tb_update_count; - smp_mb(); vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; vdso_data->tz_dsttime = sys_tz.tz_dsttime; - smp_mb(); - ++vdso_data->tb_update_count; } static void __init clocksource_init(void) -- GitLab From 91534f7365982fa0c29192e73416dd798397310a Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 20 Dec 2012 03:44:28 +0000 Subject: [PATCH 1346/1799] powerpc: Add missing NULL terminator to avoid boot panic on PPC40x commit e6449c9b2d90c1bd9a5985bf05ddebfd1631cd6b upstream. The missing NULL terminator can cause a panic on PPC405 boards during boot: Linux/PowerPC load: console=ttyS0,115200 root=/dev/mtdblock1 rootfstype=squashfs,jffs2 noinitrd init=/etc/preinit Finalizing device tree... flat tree at 0x6a5160 bootconsole [udbg0] enabled Page fault in user mode with in_atomic() = 1 mm = (null) NIP = c0275f50 MSR = fffffffe Oops: Weird page fault, sig: 11 [#1] PowerPC 40x Platform Modules linked in: NIP: c0275f50 LR: c0275f60 CTR: c0280000 REGS: c0275eb0 TRAP: 636f7265 Not tainted (3.7.1) MSR: fffffffe CR: c06a6190 XER: 00000001 TASK = c02662a8[0] 'swapper' THREAD: c0274000 GPR00: c0275ec0 c000c658 c027c4bf 00000000 c0275ee0 c000a0ec c020a1a8 c020a1f0 GPR08: c020f631 c020f404 c025f078 c025f080 c0275f10 Call Trace: ---[ end trace 31fd0ba7d8756001 ]--- Kernel panic - not syncing: Attempted to kill the idle task! The panic happens since commit 9597abe00c1bab2aedce6b49866bf6d1e81c9eed (sections: fix section conflicts in arch/powerpc), however the root cause of this is that the NULL terminator were not added in commit a4f740cf33f7f6c164bbde3c0cdbcc77b0c4997c (of/flattree: Add of_flat_dt_match() helper function). Signed-off-by: Gabor Juhos Cc: Grant Likely Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/40x/ppc40x_simple.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/40x/ppc40x_simple.c b/arch/powerpc/platforms/40x/ppc40x_simple.c index 97612068fae3..f0eee75ac05f 100644 --- a/arch/powerpc/platforms/40x/ppc40x_simple.c +++ b/arch/powerpc/platforms/40x/ppc40x_simple.c @@ -57,7 +57,8 @@ static const char *board[] __initdata = { "amcc,makalu", "apm,klondike", "est,hotfoot", - "plathome,obs600" + "plathome,obs600", + NULL }; static int __init ppc40x_probe(void) -- GitLab From 9d4c74b86237ac64376b92c54cf7b471e7e75f76 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 29 Nov 2012 14:07:59 -0700 Subject: [PATCH 1347/1799] KVM: Fix user memslot overlap check commit 5419369ed6bd4cf711fdda5e52a5999b940413f5 upstream. Prior to memory slot sorting this loop compared all of the user memory slots for overlap with new entries. With memory slot sorting, we're just checking some number of entries in the array that may or may not be user slots. Instead, walk all the slots with kvm_for_each_memslot, which has the added benefit of terminating early when we hit the first empty slot, and skip comparison to private slots. Signed-off-by: Alex Williamson Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- virt/kvm/kvm_main.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 9739b533ca2e..71b9036644a1 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -693,8 +693,7 @@ int __kvm_set_memory_region(struct kvm *kvm, int r; gfn_t base_gfn; unsigned long npages; - unsigned long i; - struct kvm_memory_slot *memslot; + struct kvm_memory_slot *memslot, *slot; struct kvm_memory_slot old, new; struct kvm_memslots *slots, *old_memslots; @@ -741,13 +740,11 @@ int __kvm_set_memory_region(struct kvm *kvm, /* Check for overlaps */ r = -EEXIST; - for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { - struct kvm_memory_slot *s = &kvm->memslots->memslots[i]; - - if (s == memslot || !s->npages) + kvm_for_each_memslot(slot, kvm->memslots) { + if (slot->id >= KVM_MEMORY_SLOTS || slot == memslot) continue; - if (!((base_gfn + npages <= s->base_gfn) || - (base_gfn >= s->base_gfn + s->npages))) + if (!((base_gfn + npages <= slot->base_gfn) || + (base_gfn >= slot->base_gfn + slot->npages))) goto out_free; } -- GitLab From 4305c46a628974e21e7939893476e4e735cd603c Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Fri, 30 Nov 2012 16:48:59 +0100 Subject: [PATCH 1348/1799] s390/cio: fix pgid reserved check commit d99e79ec5574fc556c988f613ed6175f6de66f4a upstream. The check to whom a device is reserved is done by checking the path state of the affected channel paths. If it turns out that one path is flagged as reserved by someone else the whole device is marked as such. However the meaning of the RESVD_ELSE bit is that the addressed device is reserved to a different pathgroup (and not reserved to a different LPAR). If we do this test on a path which is currently not a member of the pathgroup we could erroneously mark the device as reserved to someone else. To fix this collect the reserved state for all potential members of the pathgroup and only mark the device as reserved if all of those potential members have the RESVD_ELSE bit set. Acked-by: Peter Oberparleiter Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- drivers/s390/cio/device_pgid.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c index 07a4fd29f096..daa6b903aa91 100644 --- a/drivers/s390/cio/device_pgid.c +++ b/drivers/s390/cio/device_pgid.c @@ -234,7 +234,7 @@ static int pgid_cmp(struct pgid *p1, struct pgid *p2) * Determine pathgroup state from PGID data. */ static void pgid_analyze(struct ccw_device *cdev, struct pgid **p, - int *mismatch, int *reserved, u8 *reset) + int *mismatch, u8 *reserved, u8 *reset) { struct pgid *pgid = &cdev->private->pgid[0]; struct pgid *first = NULL; @@ -248,7 +248,7 @@ static void pgid_analyze(struct ccw_device *cdev, struct pgid **p, if ((cdev->private->pgid_valid_mask & lpm) == 0) continue; if (pgid->inf.ps.state2 == SNID_STATE2_RESVD_ELSE) - *reserved = 1; + *reserved |= lpm; if (pgid_is_reset(pgid)) { *reset |= lpm; continue; @@ -316,14 +316,14 @@ static void snid_done(struct ccw_device *cdev, int rc) struct subchannel *sch = to_subchannel(cdev->dev.parent); struct pgid *pgid; int mismatch = 0; - int reserved = 0; + u8 reserved = 0; u8 reset = 0; u8 donepm; if (rc) goto out; pgid_analyze(cdev, &pgid, &mismatch, &reserved, &reset); - if (reserved) + if (reserved == cdev->private->pgid_valid_mask) rc = -EUSERS; else if (mismatch) rc = -EOPNOTSUPP; @@ -336,7 +336,7 @@ static void snid_done(struct ccw_device *cdev, int rc) } out: CIO_MSG_EVENT(2, "snid: device 0.%x.%04x: rc=%d pvm=%02x vpm=%02x " - "todo=%02x mism=%d rsvd=%d reset=%02x\n", id->ssid, + "todo=%02x mism=%d rsvd=%02x reset=%02x\n", id->ssid, id->devno, rc, cdev->private->pgid_valid_mask, sch->vpm, cdev->private->pgid_todo_mask, mismatch, reserved, reset); switch (rc) { -- GitLab From b1ca420793e505d04f3a47a74651af7c037774b7 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Mon, 13 Aug 2012 20:52:24 +0800 Subject: [PATCH 1349/1799] MIPS: Fix poweroff failure when HOTPLUG_CPU configured. commit 8add1ecb81f541ef2fcb0b85a5470ad9ecfb4a84 upstream. When poweroff machine, kernel_power_off() call disable_nonboot_cpus(). And if we have HOTPLUG_CPU configured, disable_nonboot_cpus() is not an empty function but attempt to actually disable the nonboot cpus. Since system state is SYSTEM_POWER_OFF, play_dead() won't be called and thus disable_nonboot_cpus() hangs. Therefore, we make this patch to avoid poweroff failure. Signed-off-by: Huacai Chen Signed-off-by: Hongliang Tao Signed-off-by: Hua Yan Cc: Yong Zhang Cc: Fuxin Zhang Cc: Zhangjin Wu Patchwork: https://patchwork.linux-mips.org/patch/4211/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- arch/mips/kernel/process.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index e9a5fd7277f4..69b17a920049 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -72,9 +72,7 @@ void __noreturn cpu_idle(void) } } #ifdef CONFIG_HOTPLUG_CPU - if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) && - (system_state == SYSTEM_RUNNING || - system_state == SYSTEM_BOOTING)) + if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map)) play_dead(); #endif rcu_idle_exit(); -- GitLab From c0b96525363543a1ba6a277546ebc26ad9a53aa1 Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Fri, 11 Jan 2013 14:31:47 -0800 Subject: [PATCH 1350/1799] mm: compaction: fix echo 1 > compact_memory return error issue commit 7964c06d66c76507d8b6b662bffea770c29ef0ce upstream. when run the folloing command under shell, it will return error sh/$ echo 1 > /proc/sys/vm/compact_memory sh/$ sh: write error: Bad address After strace, I found the following log: ... write(1, "1\n", 2) = 3 write(1, "", 4294967295) = -1 EFAULT (Bad address) write(2, "echo: write error: Bad address\n", 31echo: write error: Bad address ) = 31 This tells system return 3(COMPACT_COMPLETE) after write data to compact_memory. The fix is to make the system just return 0 instead 3(COMPACT_COMPLETE) from sysctl_compaction_handler after compaction_nodes finished. Signed-off-by: Jason Liu Suggested-by: David Rientjes Acked-by: Mel Gorman Cc: Rik van Riel Cc: Minchan Kim Cc: KAMEZAWA Hiroyuki Acked-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/compaction.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mm/compaction.c b/mm/compaction.c index 459b0ab60524..3c8d7fe4410b 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -736,7 +736,7 @@ static int compact_node(int nid) } /* Compact all nodes in the system */ -static int compact_nodes(void) +static void compact_nodes(void) { int nid; @@ -745,8 +745,6 @@ static int compact_nodes(void) for_each_online_node(nid) compact_node(nid); - - return COMPACT_COMPLETE; } /* The written value is actually unused, all memory is compacted */ @@ -757,7 +755,7 @@ int sysctl_compaction_handler(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) { if (write) - return compact_nodes(); + compact_nodes(); return 0; } -- GitLab From ce19422296fb5fb5997d81e1b0043d771def7996 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Fri, 11 Jan 2013 14:31:51 -0800 Subject: [PATCH 1351/1799] mm: use aligned zone start for pfn_to_bitidx calculation commit c060f943d0929f3e429c5d9522290584f6281d6e upstream. The current calculation in pfn_to_bitidx assumes that (pfn - zone->zone_start_pfn) >> pageblock_order will return the same bit for all pfn in a pageblock. If zone_start_pfn is not aligned to pageblock_nr_pages, this may not always be correct. Consider the following with pageblock order = 10, zone start 2MB: pfn | pfn - zone start | (pfn - zone start) >> page block order ---------------------------------------------------------------- 0x26000 | 0x25e00 | 0x97 0x26100 | 0x25f00 | 0x97 0x26200 | 0x26000 | 0x98 0x26300 | 0x26100 | 0x98 This means that calling {get,set}_pageblock_migratetype on a single page will not set the migratetype for the full block. Fix this by rounding down zone_start_pfn when doing the bitidx calculation. For our use case, the effects of this bug were mostly tied to the fact that CMA allocations would either take a long time or fail to happen. Depending on the driver using CMA, this could result in anything from visual glitches to application failures. Signed-off-by: Laura Abbott Acked-by: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/page_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 88a6d87041df..691b8ecdaa69 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5340,7 +5340,7 @@ static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn) pfn &= (PAGES_PER_SECTION-1); return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; #else - pfn = pfn - zone->zone_start_pfn; + pfn = pfn - round_down(zone->zone_start_pfn, pageblock_nr_pages); return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; #endif /* CONFIG_SPARSEMEM */ } -- GitLab From 867f263c648dee508e0cdd857a44f69a1bc2fad7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 6 Dec 2012 18:40:11 +0100 Subject: [PATCH 1352/1799] Revert "ath9k_hw: Update AR9003 high_power tx gain table" commit 9c170e068636deb3e3f96114034bb711675f0faa upstream. This reverts commit f74b9d365ddd33a375802b064f96a5d0e99af7c0. Turns out reverting commit a240dc7b3c7463bd60cf0a9b2a90f52f78aae0fd "ath9k_hw: Updated AR9003 tx gain table for 5GHz" was not enough to bring the tx power back to normal levels on devices like the Buffalo WZR-HP-G450H, this one needs to be reverted as well. This revert improves tx power by ~10 db on that device Signed-off-by: Felix Fietkau Cc: rmanohar@qca.qualcomm.com Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- .../wireless/ath/ath9k/ar9003_2p2_initvals.h | 172 +++++++++--------- 1 file changed, 86 insertions(+), 86 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 2b4b63318da6..4e2a52c342db 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -533,98 +533,98 @@ static const u32 ar9300_2p2_baseband_core[][2] = { static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, - {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, - {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, - {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, - {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, + {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, + {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, + {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, + {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, + {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, + {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, + {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, + {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, + {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, - {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, - {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, - {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, + {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, + {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, + {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, + {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, + {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, -- GitLab From 324b9bebea9e335c8588bf5eefdcca7d932508e6 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sun, 9 Dec 2012 23:57:09 +0100 Subject: [PATCH 1353/1799] ath9k: ar9003: fix OTP register offsets for AR9340 commit b3cd8021379306c0be6932e4d3b4b01efc681769 upstream. Trying to access the OTP memory on the AR9340 causes a data bus error like this: Data bus error, epc == 86e84164, ra == 86e84164 Oops[#1]: Cpu 0 $ 0 : 00000000 00000061 deadc0de 00000000 $ 4 : b8115f18 00015f18 00000007 00000004 $ 8 : 00000001 7c7c3c7c 7c7c7c7c 7c7c7c7c $12 : 7c7c3c7c 001f0041 00000000 7c7c7c3c $16 : 86ee0000 00015f18 00000000 00000007 $20 : 00000004 00000064 00000004 86d71c44 $24 : 00000000 86e6ca00 $28 : 86d70000 86d71b20 86ece0c0 86e84164 Hi : 00000000 Lo : 00000064 epc : 86e84164 ath9k_hw_wait+0x58/0xb0 [ath9k_hw] Tainted: G O ra : 86e84164 ath9k_hw_wait+0x58/0xb0 [ath9k_hw] Status: 1100d403 KERNEL EXL IE Cause : 4080801c PrId : 0001974c (MIPS 74Kc) Modules linked in: ath9k(O+) ath9k_common(O) ath9k_hw(O) ath(O) ar934x_nfc mac80211(O) usbcore usb_common scsi_mod nls_base nand nand_ecc nand_ids crc_ccitt cfg80211(O) compat(O) arc4 aes_generic crypto_blkcipher cryptomgr aead crypto_hash crypto_algapi ledtrig_timer ledtrig_default_on leds_gpio Process insmod (pid: 459, threadinfo=86d70000, task=87942140, tls=779ac440) Stack : 802fb500 000200da 804db150 804e0000 87816130 86ee0000 00010000 86d71b88 86d71bc0 00000004 00000003 86e9fcd0 80305300 0002c0d0 86e74c50 800b4c20 000003e8 00000001 00000000 86ee0000 000003ff 86e9fd64 80305300 80123938 fffffffc 00000004 000058bc 00000000 86ea0000 86ee0000 000001ff 878d6000 99999999 86e9fdc0 86ee0fcc 86e9e664 0000c0d0 86ee0000 0000700000007000 ... Call Trace: [<86e84164>] ath9k_hw_wait+0x58/0xb0 [ath9k_hw] [<86e9fcd0>] ath9k_hw_setup_statusring+0x16b8/0x1c7c [ath9k_hw] Code: 0000a812 0040f809 00000000 <00531024> 1054000b 24020001 0c05b5dc 2404000a 26520001 The cause of the error is that the OTP register offsets are different on the AR9340 than the actually used values. Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index bb223fe82816..582ebc4bc5e0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -69,13 +69,13 @@ #define AR9300_BASE_ADDR 0x3ff #define AR9300_BASE_ADDR_512 0x1ff -#define AR9300_OTP_BASE 0x14000 -#define AR9300_OTP_STATUS 0x15f18 +#define AR9300_OTP_BASE (AR_SREV_9340(ah) ? 0x30000 : 0x14000) +#define AR9300_OTP_STATUS (AR_SREV_9340(ah) ? 0x30018 : 0x15f18) #define AR9300_OTP_STATUS_TYPE 0x7 #define AR9300_OTP_STATUS_VALID 0x4 #define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 #define AR9300_OTP_STATUS_SM_BUSY 0x1 -#define AR9300_OTP_READ_DATA 0x15f1c +#define AR9300_OTP_READ_DATA (AR_SREV_9340(ah) ? 0x3001c : 0x15f1c) enum targetPowerHTRates { HT_TARGET_RATE_0_8_16, -- GitLab From 5004c75870b05d2ffd5974d1fd681a5a1b0d9f4c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 10 Dec 2012 14:03:17 +0100 Subject: [PATCH 1354/1799] ath9k_hw: Fix signal strength / channel noise reporting commit b7c0c238898d200e80487516e2b67aba2a522cc0 upstream. While AR_PHY_CCA_NOM_VAL_* does contain the expected internal noise floor for a chip measured in clean air, it refers to the lowest expected reading. Depending on the frequency, this measurement can vary by about 6db, thus causing a higher reported channel noise and signal strength. Factor in the 6db offset when converting internal noisefloor to channel noise. This patch makes the reported values more accurate for all chips without affecting NF calibration behavior. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/calib.c | 1 + drivers/net/wireless/ath/ath9k/calib.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index e5cceb077574..bbd249df23e3 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -69,6 +69,7 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) if (chan && chan->noisefloor) { s8 delta = chan->noisefloor - + ATH9K_NF_CAL_NOISE_THRESH - ath9k_hw_get_default_nf(ah, chan); if (delta > 0) noise += delta; diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 3b33996d97df..1f2e01a96d22 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -21,6 +21,9 @@ #define AR_PHY_CCA_FILTERWINDOW_LENGTH 5 +/* Internal noise floor can vary by about 6db depending on the frequency */ +#define ATH9K_NF_CAL_NOISE_THRESH 6 + #define NUM_NF_READINGS 6 #define ATH9K_NF_CAL_HIST_MAX 5 -- GitLab From 2d2b65eeb598b687403aa0f06d4d7da97661958a Mon Sep 17 00:00:00 2001 From: Stephan Gatzka Date: Wed, 28 Nov 2012 20:04:32 +0100 Subject: [PATCH 1355/1799] firewire: net: Fix handling of fragmented multicast/broadcast packets. commit 9d2373420900a39f5212a3b289331aa3535b1000 upstream. This patch fixes both the transmit and receive portion of sending fragmented mutlicast and broadcast packets. The transmit section was broken because the offset for INTFRAG and LASTFRAG packets were just miscalculated by IEEE1394_GASP_HDR_SIZE (which was reserved with skb_push() in fwnet_send_packet). The receive section was broken because in fwnet_incoming_packet is a call to fwnet_peer_find_by_node_id(). Called with generation == -1 it will not find a peer and the partial datagrams are associated to a peer. [Stefan R: The fix to use context->card->generation is not perfect. It relies on the IR tasklet which processes packets from the prior bus generation to run before the self-ID-complete worklet which sets the current card generation. Alas, there is no simple way of a race-free implementation. Let's do it this way for now.] Signed-off-by: Stephan Gatzka Signed-off-by: Stefan Richter Signed-off-by: Greg Kroah-Hartman --- drivers/firewire/net.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 08c674957af8..638e1f71284a 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -861,8 +861,8 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context, if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) { buf_ptr += 2; length -= IEEE1394_GASP_HDR_SIZE; - fwnet_incoming_packet(dev, buf_ptr, length, - source_node_id, -1, true); + fwnet_incoming_packet(dev, buf_ptr, length, source_node_id, + context->card->generation, true); } packet.payload_length = dev->rcv_buffer_size; @@ -958,7 +958,12 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask) break; } - skb_pull(skb, ptask->max_payload); + if (ptask->dest_node == IEEE1394_ALL_NODES) { + skb_pull(skb, + ptask->max_payload + IEEE1394_GASP_HDR_SIZE); + } else { + skb_pull(skb, ptask->max_payload); + } if (ptask->outstanding_pkts > 1) { fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG, dg_size, fg_off, datagram_label); @@ -1062,7 +1067,7 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask) smp_rmb(); node_id = dev->card->node_id; - p = skb_push(ptask->skb, 8); + p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE); put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p); put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24 | RFC2734_SW_VERSION, &p[4]); -- GitLab From a565623f44aeafafc74a5763f765d5c8224bc4ad Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 7 Dec 2012 18:30:51 +0100 Subject: [PATCH 1356/1799] ASoC: sigmadsp: Fix endianness conversion issue commit a3adb1432d7a3ad86bb17a1638e44414537e4118 upstream. The 'addr' field of the sigma_action struct is stored as big endian in the firmware file. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/sigmadsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c index 5be42bf56996..4068f2491232 100644 --- a/sound/soc/codecs/sigmadsp.c +++ b/sound/soc/codecs/sigmadsp.c @@ -225,7 +225,7 @@ EXPORT_SYMBOL(process_sigma_firmware); static int sigma_action_write_regmap(void *control_data, const struct sigma_action *sa, size_t len) { - return regmap_raw_write(control_data, le16_to_cpu(sa->addr), + return regmap_raw_write(control_data, be16_to_cpu(sa->addr), sa->payload, len - 2); } -- GitLab From 8f735b2774f5e200a65c5fe9143fb431023a5267 Mon Sep 17 00:00:00 2001 From: Jianpeng Ma Date: Sat, 4 Aug 2012 10:34:14 +0800 Subject: [PATCH 1357/1799] SCSI: mvsas: Fix oops when ata commond timeout. commit 95ab000388974d8ffef8257306b4be6e8778b768 upstream. Kernel message follows: [ 511.712011] sd 11:0:0:0: [sdf] command ffff8800a4e81400 timed out [ 511.712022] sas: Enter sas_scsi_recover_host busy: 1 failed: 1 [ 511.712024] sas: trying to find task 0xffff8800a4d24c80 [ 511.712026] sas: sas_scsi_find_task: aborting task 0xffff8800a4d24c80 [ 511.712029] drivers/scsi/mvsas/mv_sas.c 1631:mvs_abort_task() mvi=ffff8800b5300000 task=ffff8800a4d24c80 slot=ffff8800b5325038 slot_idx=x0 [ 511.712035] BUG: unable to handle kernel NULL pointer dereference at 0000000000000058 [ 511.712040] IP: [] _raw_spin_lock_irqsave+0xc/0x30 [ 511.712047] PGD 0 [ 511.712049] Oops: 0002 [#1] SMP [ 511.712052] Modules linked in: mvsas libsas scsi_transport_sas raid456 async_pq async_xor xor async_memcpy async_raid6_recov raid6_pq async_tx [last unloaded: mvsas] [ 511.712062] CPU 3 [ 511.712066] Pid: 7322, comm: scsi_eh_11 Not tainted 3.5.0+ #106 To Be Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M. [ 511.712068] RIP: 0010:[] [] _raw_spin_lock_irqsave+0xc/0x30 [ 511.712073] RSP: 0018:ffff880098d3bcb0 EFLAGS: 00010086 [ 511.712074] RAX: 0000000000000286 RBX: 0000000000000058 RCX: 00000000000000c3 [ 511.712076] RDX: 0000000000000100 RSI: 0000000000000046 RDI: 0000000000000058 [ 511.712078] RBP: ffff880098d3bcb0 R08: 000000000000000a R09: 0000000000000000 [ 511.712080] R10: 00000000000004e8 R11: 00000000000004e7 R12: ffff8800a4d24c80 [ 511.712082] R13: 0000000000000050 R14: ffff8800b5325038 R15: ffff8800a4eafe00 [ 511.712084] FS: 0000000000000000(0000) GS:ffff8800bdb80000(0000) knlGS:0000000000000000 [ 511.712086] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 511.712088] CR2: 0000000000000058 CR3: 00000000a4ce6000 CR4: 00000000000407e0 [ 511.712090] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 511.712091] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 511.712093] Process scsi_eh_11 (pid: 7322, threadinfo ffff880098d3a000, task ffff8800a61dde40) [ 511.712095] Stack: [ 511.712096] ffff880098d3bce0 ffffffff81060683 ffff880000000000 0000000000000000 [ 511.712099] ffff8800a4d24c80 ffff8800b5300000 ffff880098d3bcf0 ffffffffa0076a88 [ 511.712102] ffff880098d3bd50 ffffffffa0079bb5 ffff880000000000 ffff880000000018 [ 511.712106] Call Trace: [ 511.712110] [] complete+0x23/0x60 [ 511.712115] [] mvs_tmf_timedout+0x18/0x20 [mvsas] [ 511.712119] [] mvs_slot_complete+0x765/0x7d0 [mvsas] [ 511.712125] [] sas_scsi_recover_host+0x55d/0xdb0 [libsas] [ 511.712128] [] ? idle_balance+0xe0/0x130 [ 511.712133] [] scsi_error_handler+0xcc/0x470 [ 511.712136] [] ? __schedule+0x370/0x730 [ 511.712139] [] ? __wake_up_common+0x58/0x90 [ 511.712142] [] ? scsi_eh_get_sense+0x110/0x110 [ 511.712146] [] kthread+0x8e/0xa0 [ 511.712150] [] kernel_thread_helper+0x4/0x10 [ 511.712153] [] ? flush_kthread_work+0x120/0x120 [ 511.712156] [] ? gs_change+0xb/0xb [ 511.712157] Code: 8a 00 01 00 00 89 d0 f0 66 0f b1 0f 66 39 d0 0f 94 c0 0f b6 c0 5d c3 0f 1f 84 00 00 00 00 00 55 48 89 e5 9c 58 fa ba 00 01 00 00 66 0f c1 17 0f b6 ce 38 d1 74 11 0f 1f 84 00 00 00 00 00 f3 [ 511.712191] RIP [] _raw_spin_lock_irqsave+0xc/0x30 [ 511.712194] RSP [ 511.712196] CR2: 0000000000000058 [ 511.712198] ---[ end trace a781c7b1e65db92c ]--- Signed-off-by: Jianpeng Ma Signed-off-by: James Bottomley Cc: CAI Qian Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/mvsas/mv_sas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 3006ec9aa690..dbb8edfc8baa 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -1629,7 +1629,7 @@ int mvs_abort_task(struct sas_task *task) mv_dprintk("mvs_abort_task() mvi=%p task=%p " "slot=%p slot_idx=x%x\n", mvi, task, slot, slot_idx); - mvs_tmf_timedout((unsigned long)task); + task->task_state_flags |= SAS_TASK_STATE_ABORTED; mvs_slot_task_free(mvi, task, slot, slot_idx); rc = TMF_RESP_FUNC_COMPLETE; goto out; -- GitLab From 3814b31a89b1fbb5c6f92c11c8371a2e4c97d2f1 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Fri, 16 Nov 2012 14:40:03 -0500 Subject: [PATCH 1358/1799] SCSI: mvsas: fix undefined bit shift commit beecadea1b8d67f591b13f7099559f32f3fd601d upstream. The macro bit(n) is defined as ((u32)1 << n), and thus it doesn't work with n >= 32, such as in mvs_94xx_assign_reg_set(): if (i >= 32) { mvi->sata_reg_set |= bit(i); ... } The shift ((u32)1 << n) with n >= 32 also leads to undefined behavior. The result varies depending on the architecture. This patch changes bit(n) to do a 64-bit shift. It also simplifies mv_ffc64() using __ffs64(), since invoking ffz() with ~0 is undefined. Signed-off-by: Xi Wang Acked-by: Xiangliang Yu Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/mvsas/mv_94xx.h | 14 ++------------ drivers/scsi/mvsas/mv_sas.h | 2 +- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/mvsas/mv_94xx.h b/drivers/scsi/mvsas/mv_94xx.h index 8f7eb4f21140..487aa6f97412 100644 --- a/drivers/scsi/mvsas/mv_94xx.h +++ b/drivers/scsi/mvsas/mv_94xx.h @@ -258,21 +258,11 @@ enum sas_sata_phy_regs { #define SPI_ADDR_VLD_94XX (1U << 1) #define SPI_CTRL_SpiStart_94XX (1U << 0) -#define mv_ffc(x) ffz(x) - static inline int mv_ffc64(u64 v) { - int i; - i = mv_ffc((u32)v); - if (i >= 0) - return i; - i = mv_ffc((u32)(v>>32)); - - if (i != 0) - return 32 + i; - - return -1; + u64 x = ~v; + return x ? __ffs64(x) : -1; } #define r_reg_set_enable(i) \ diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index c04a4f5b5972..da249553858c 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h @@ -69,7 +69,7 @@ extern struct kmem_cache *mvs_task_list_cache; #define DEV_IS_EXPANDER(type) \ ((type == EDGE_DEV) || (type == FANOUT_DEV)) -#define bit(n) ((u32)1 << n) +#define bit(n) ((u64)1 << n) #define for_each_phy(__lseq_mask, __mc, __lseq) \ for ((__mc) = (__lseq_mask), (__lseq) = 0; \ -- GitLab From e21c4b90fb7881357c81a5f68d676747b7dddbb1 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 15 Nov 2012 15:51:46 -0500 Subject: [PATCH 1359/1799] SCSI: prevent stack buffer overflow in host_reset commit 072f19b4bea31cdd482d79f805413f2f9ac9e233 upstream. store_host_reset() has tried to re-invent the wheel to compare sysfs strings. Unfortunately it did so poorly and never bothered to check the input from userspace before overwriting stack with it, so something simple as: echo "WoopsieWoopsie" > /sys/devices/pseudo_0/adapter0/host0/scsi_host/host0/host_reset would result in: [ 316.310101] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff81f5bac7 [ 316.310101] [ 316.320051] Pid: 6655, comm: sh Tainted: G W 3.7.0-rc5-next-20121114-sasha-00016-g5c9d68d-dirty #129 [ 316.320051] Call Trace: [ 316.340058] pps pps0: PPS event at 1352918752.620355751 [ 316.340062] pps pps0: capture assert seq #303 [ 316.320051] [] panic+0xcd/0x1f4 [ 316.320051] [] ? store_host_reset+0xd7/0x100 [ 316.320051] [] __stack_chk_fail+0x16/0x20 [ 316.320051] [] store_host_reset+0xd7/0x100 [ 316.320051] [] dev_attr_store+0x13/0x30 [ 316.320051] [] sysfs_write_file+0x101/0x170 [ 316.320051] [] vfs_write+0xb8/0x180 [ 316.320051] [] sys_write+0x50/0xa0 [ 316.320051] [] tracesys+0xe1/0xe6 Fix this by uninventing whatever was going on there and just use sysfs_streq. Bug introduced by 29443691 ("[SCSI] scsi: Added support for adapter and firmware reset"). [jejb: added necessary const to prevent compile warnings] Signed-off-by: Sasha Levin Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_sysfs.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 08d48a3b7679..72ca515a4304 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -246,11 +246,11 @@ show_shost_active_mode(struct device *dev, static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL); -static int check_reset_type(char *str) +static int check_reset_type(const char *str) { - if (strncmp(str, "adapter", 10) == 0) + if (sysfs_streq(str, "adapter")) return SCSI_ADAPTER_RESET; - else if (strncmp(str, "firmware", 10) == 0) + else if (sysfs_streq(str, "firmware")) return SCSI_FIRMWARE_RESET; else return 0; @@ -263,12 +263,9 @@ store_host_reset(struct device *dev, struct device_attribute *attr, struct Scsi_Host *shost = class_to_shost(dev); struct scsi_host_template *sht = shost->hostt; int ret = -EINVAL; - char str[10]; int type; - sscanf(buf, "%s", str); - type = check_reset_type(str); - + type = check_reset_type(buf); if (!type) goto exit_store_host_reset; -- GitLab From 2e4be18823cb686f1316ac856ce1fbc651dd28e1 Mon Sep 17 00:00:00 2001 From: David Jeffery Date: Wed, 21 Nov 2012 02:39:54 -0500 Subject: [PATCH 1360/1799] SCSI: qla2xxx: Test and clear FCPORT_UPDATE_NEEDED atomically. commit a394aac88506159e047630fc90dc2242568382d8 upstream. When the qla2xxx driver loses access to multiple, remote ports, there is a race condition which can occur which will keep the request stuck on a scsi request queue indefinitely. This bad state occurred do to a race condition with how the FCPORT_UPDATE_NEEDED bit is set in qla2x00_schedule_rport_del(), and how it is cleared in qla2x00_do_dpc(). The problem port has its drport pointer set, but it has never been processed by the driver to inform the fc transport that the port has been lost. qla2x00_schedule_rport_del() sets drport, and then sets the FCPORT_UPDATE_NEEDED bit. In qla2x00_do_dpc(), the port lists are walked and any drport pointer is handled and the fc transport informed of the port loss, then the FCPORT_UPDATE_NEEDED bit is cleared. This leaves a race where the dpc thread is processing one port removal, another port removal is marked with a call to qla2x00_schedule_rport_del(), and the dpc thread clears the bit for both removals, even though only the first removal was actually handled. Until another event occurs to set FCPORT_UPDATE_NEEDED, the later port removal is never finished and qla2xxx stays in a bad state which causes requests to become stuck on request queues. This patch updates the driver to test and clear FCPORT_UPDATE_NEEDED atomically. This ensures the port state changes are processed and not lost. Signed-off-by: David Jeffery Signed-off-by: Chad Dupuis Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/qla2xxx/qla_os.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7db803377c64..da1315ede009 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3735,9 +3735,9 @@ qla2x00_do_dpc(void *data) "ISP abort end.\n"); } - if (test_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) { + if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, + &base_vha->dpc_flags)) { qla2x00_update_fcports(base_vha); - clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); } if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) { -- GitLab From 370caef9e8e2800a759d9c29e2c4d41375bdad62 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 23 Nov 2012 12:07:39 +0800 Subject: [PATCH 1361/1799] iscsit: use GFP_ATOMIC under spin lock commit 3c989d7603872bf878840f7ce3ea49b73bea4c6c upstream. The function iscsit_build_conn_drop_async_message() is called from iscsit_close_connection() with spin lock 'sess->conn_lock' held, so we should use GFP_ATOMIC instead of GFP_KERNEL. Signed-off-by: Wei Yongjun Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/iscsi/iscsi_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index ad202b342bf5..486c5dd45016 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -2359,7 +2359,7 @@ static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn) if (!conn_p) return; - cmd = iscsit_allocate_cmd(conn_p, GFP_KERNEL); + cmd = iscsit_allocate_cmd(conn_p, GFP_ATOMIC); if (!cmd) { iscsit_dec_conn_usage_count(conn_p); return; -- GitLab From 4b693aca7e346fcff0ea5c1548e7b5545bfbfd04 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Sun, 16 Sep 2012 20:53:43 +0200 Subject: [PATCH 1362/1799] sata_promise: fix hardreset lockdep error commit 3100d49d3cd236443faae9d81137c81b22d36003 upstream. sata_promise's pdc_hard_reset_port() needs to serialize because it flips a port-specific bit in controller register that's shared by all ports. The code takes the ata host lock for this, but that's broken because an interrupt may arrive on our irq during the hard reset sequence, and that too will take the ata host lock. With lockdep enabled a big nasty warning is seen. Fixed by adding private state to the ata host structure, containing a second lock used only for serializing the hard reset sequences. This eliminated the lockdep warnings both on my test rig and on the original reporter's machine. Signed-off-by: Mikael Pettersson Tested-by: Adko Branil Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/sata_promise.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 000fcc99e01d..ef6e328784e9 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -147,6 +147,10 @@ struct pdc_port_priv { dma_addr_t pkt_dma; }; +struct pdc_host_priv { + spinlock_t hard_reset_lock; +}; + static int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); static int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -801,9 +805,10 @@ static void pdc_hard_reset_port(struct ata_port *ap) void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1; unsigned int ata_no = pdc_ata_port_to_ata_no(ap); + struct pdc_host_priv *hpriv = ap->host->private_data; u8 tmp; - spin_lock(&ap->host->lock); + spin_lock(&hpriv->hard_reset_lock); tmp = readb(pcictl_b1_mmio); tmp &= ~(0x10 << ata_no); @@ -814,7 +819,7 @@ static void pdc_hard_reset_port(struct ata_port *ap) writeb(tmp, pcictl_b1_mmio); readb(pcictl_b1_mmio); /* flush */ - spin_unlock(&ap->host->lock); + spin_unlock(&hpriv->hard_reset_lock); } static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, @@ -1182,6 +1187,7 @@ static int pdc_ata_init_one(struct pci_dev *pdev, const struct ata_port_info *pi = &pdc_port_info[ent->driver_data]; const struct ata_port_info *ppi[PDC_MAX_PORTS]; struct ata_host *host; + struct pdc_host_priv *hpriv; void __iomem *host_mmio; int n_ports, i, rc; int is_sataii_tx4; @@ -1218,6 +1224,11 @@ static int pdc_ata_init_one(struct pci_dev *pdev, dev_err(&pdev->dev, "failed to allocate host\n"); return -ENOMEM; } + hpriv = devm_kzalloc(&pdev->dev, sizeof *hpriv, GFP_KERNEL); + if (!hpriv) + return -ENOMEM; + spin_lock_init(&hpriv->hard_reset_lock); + host->private_data = hpriv; host->iomap = pcim_iomap_table(pdev); is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags); -- GitLab From d8876cb61d0bd9002cedcd720ce13ad7f2e32cf7 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Mon, 3 Dec 2012 11:35:02 +0800 Subject: [PATCH 1363/1799] libata: set dma_mode to 0xff in reset commit 5416912af75de9cba5d1c75b99a7888b0bbbd2fb upstream. ata_device->dma_mode's initial value is zero, which is not a valid dma mode, but ata_dma_enabled will return true for this value. This patch sets dma_mode to 0xff in reset function, so that ata_dma_enabled will not return true for this case, or it will cause problem for pata_acpi. The corrsponding bugzilla page is at: https://bugzilla.kernel.org/show_bug.cgi?id=49151 Reported-by: Phillip Wood Signed-off-by: Aaron Lu Tested-by: Szymon Janc Tested-by: Dutra Julio Acked-by: Alan Cox Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-core.c | 1 + drivers/ata/libata-eh.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index cf4837f3ded7..4b4caa3db6ca 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2536,6 +2536,7 @@ int ata_bus_probe(struct ata_port *ap) * bus as we may be talking too fast. */ dev->pio_mode = XFER_PIO_0; + dev->dma_mode = 0xff; /* If the controller has a pio mode setup function * then use it to set the chipset to rights. Don't diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index d1fbd59ead16..e47c224d7c28 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2600,6 +2600,7 @@ int ata_eh_reset(struct ata_link *link, int classify, * bus as we may be talking too fast. */ dev->pio_mode = XFER_PIO_0; + dev->dma_mode = 0xff; /* If the controller has a pio mode setup function * then use it to set the chipset to rights. Don't -- GitLab From 93269101285d5bfd18b1f3b7078a76ed87e7a834 Mon Sep 17 00:00:00 2001 From: Xiaotian Feng Date: Thu, 13 Dec 2012 16:12:18 +0800 Subject: [PATCH 1364/1799] libata: fix Null pointer dereference on disk error commit 26cd4d65deba587f3cf2329b6869ce02bcbe68ec upstream. Following oops were observed when disk error happened: [ 4272.896937] sd 0:0:0:0: [sda] Unhandled error code [ 4272.896939] sd 0:0:0:0: [sda] Result: hostbyte=DID_BAD_TARGET driverbyte=DRIVER_OK [ 4272.896942] sd 0:0:0:0: [sda] CDB: Read(10): 28 00 00 5a de a7 00 00 08 00 [ 4272.896951] end_request: I/O error, dev sda, sector 5955239 [ 4291.574947] BUG: unable to handle kernel NULL pointer dereference at (null) [ 4291.658305] IP: [] ahci_activity_show+0x1/0x40 [ 4291.730090] PGD 76dbbc067 PUD 6c4fba067 PMD 0 [ 4291.783408] Oops: 0000 [#1] SMP [ 4291.822100] last sysfs file: /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sw_activity [ 4291.934235] CPU 9 [ 4291.958301] Pid: 27942, comm: hwinfo ...... ata_scsi_find_dev could return NULL, so ata_scsi_activity_{show,store} should check if atadev is NULL. Signed-off-by: Xiaotian Feng Cc: James Bottomley Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-scsi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 22226350cd0c..15863a4b6190 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -309,7 +309,8 @@ ata_scsi_activity_show(struct device *dev, struct device_attribute *attr, struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); - if (ap->ops->sw_activity_show && (ap->flags & ATA_FLAG_SW_ACTIVITY)) + if (atadev && ap->ops->sw_activity_show && + (ap->flags & ATA_FLAG_SW_ACTIVITY)) return ap->ops->sw_activity_show(atadev, buf); return -EINVAL; } @@ -324,7 +325,8 @@ ata_scsi_activity_store(struct device *dev, struct device_attribute *attr, enum sw_activity val; int rc; - if (ap->ops->sw_activity_store && (ap->flags & ATA_FLAG_SW_ACTIVITY)) { + if (atadev && ap->ops->sw_activity_store && + (ap->flags & ATA_FLAG_SW_ACTIVITY)) { val = simple_strtoul(buf, NULL, 0); switch (val) { case OFF: case BLINK_ON: case BLINK_OFF: -- GitLab From 28a63b67b3d52e40826d82425307e8f067551106 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Mon, 10 Dec 2012 17:04:00 -0800 Subject: [PATCH 1365/1799] target/tcm_fc: fix the lockdep warning due to inconsistent lock state commit 9f4ad44b264f8bb61ffdd607148215566568430d upstream. The lockdep warning below is in theory correct but it will be in really weird rare situation that ends up that deadlock since the tcm fc session is hashed based the rport id. Nonetheless, the complaining below is about rcu callback that does the transport_deregister_session() is happening in softirq, where transport_register_session() that happens earlier is not. This triggers the lockdep warning below. So, just fix this to make lockdep happy by disabling the soft irq before calling transport_register_session() in ft_prli. BTW, this was found in FCoE VN2VN over two VMs, couple of create and destroy would get this triggered. v1: was enforcing register to be in softirq context which was not righ. See, http://www.spinics.net/lists/target-devel/msg03614.html v2: following comments from Roland&Nick (thanks), it seems we don't have to do transport_deregister_session() in rcu callback, so move it into ft_sess_free() but still do kfree() of the corresponding ft_sess struct in rcu callback to make sure the ft_sess is not freed till the rcu callback. ... [ 1328.370592] scsi2 : FCoE Driver [ 1328.383429] fcoe: No FDMI support. [ 1328.384509] host2: libfc: Link up on port (000000) [ 1328.934229] host2: Assigned Port ID 00a292 [ 1357.232132] host2: rport 00a393: Remove port [ 1357.232568] host2: rport 00a393: Port sending LOGO from Ready state [ 1357.233692] host2: rport 00a393: Delete port [ 1357.234472] host2: rport 00a393: work event 3 [ 1357.234969] host2: rport 00a393: callback ev 3 [ 1357.235979] host2: rport 00a393: Received a LOGO response closed [ 1357.236706] host2: rport 00a393: work delete [ 1357.237481] [ 1357.237631] ================================= [ 1357.238064] [ INFO: inconsistent lock state ] [ 1357.238450] 3.7.0-rc7-yikvm+ #3 Tainted: G O [ 1357.238450] --------------------------------- [ 1357.238450] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. [ 1357.238450] ksoftirqd/0/3 [HC0[0]:SC1[1]:HE0:SE0] takes: [ 1357.238450] (&(&se_tpg->session_lock)->rlock){+.?...}, at: [] transport_deregister_session+0x41/0x148 [target_core_mod] [ 1357.238450] {SOFTIRQ-ON-W} state was registered at: [ 1357.238450] [] mark_held_locks+0x6d/0x95 [ 1357.238450] [] trace_hardirqs_on_caller+0x12d/0x197 [ 1357.238450] [] trace_hardirqs_on+0xd/0xf [ 1357.238450] [] _raw_spin_unlock_irq+0x2d/0x45 [ 1357.238450] [] __transport_register_session+0xb8/0x122 [target_core_mod] [ 1357.238450] [] transport_register_session+0x44/0x5a [target_core_mod] [ 1357.238450] [] ft_prli+0x1e3/0x275 [tcm_fc] [ 1357.238450] [] fc_rport_recv_req+0x95e/0xdc5 [libfc] [ 1357.238450] [] fc_lport_recv_els_req+0xc4/0xd5 [libfc] [ 1357.238450] [] fc_lport_recv_req+0x12f/0x18f [libfc] [ 1357.238450] [] fc_exch_recv+0x8ba/0x981 [libfc] [ 1357.238450] [] fcoe_percpu_receive_thread+0x47a/0x4e2 [fcoe] [ 1357.238450] [] kthread+0xb1/0xb9 [ 1357.238450] [] ret_from_fork+0x7c/0xb0 [ 1357.238450] irq event stamp: 275411 [ 1357.238450] hardirqs last enabled at (275410): [] rcu_process_callbacks+0x229/0x42a [ 1357.238450] hardirqs last disabled at (275411): [] _raw_spin_lock_irqsave+0x22/0x8e [ 1357.238450] softirqs last enabled at (275394): [] __do_softirq+0x246/0x26f [ 1357.238450] softirqs last disabled at (275399): [] run_ksoftirqd+0x29/0x62 [ 1357.238450] [ 1357.238450] other info that might help us debug this: [ 1357.238450] Possible unsafe locking scenario: [ 1357.238450] [ 1357.238450] CPU0 [ 1357.238450] ---- [ 1357.238450] lock(&(&se_tpg->session_lock)->rlock); [ 1357.238450] [ 1357.238450] lock(&(&se_tpg->session_lock)->rlock); [ 1357.238450] [ 1357.238450] *** DEADLOCK *** [ 1357.238450] [ 1357.238450] no locks held by ksoftirqd/0/3. [ 1357.238450] [ 1357.238450] stack backtrace: [ 1357.238450] Pid: 3, comm: ksoftirqd/0 Tainted: G O 3.7.0-rc7-yikvm+ #3 [ 1357.238450] Call Trace: [ 1357.238450] [] print_usage_bug+0x1f5/0x206 [ 1357.238450] [] ? save_stack_trace+0x2c/0x49 [ 1357.238450] [] ? print_irq_inversion_bug.part.14+0x1ae/0x1ae [ 1357.238450] [] mark_lock+0x106/0x258 [ 1357.238450] [] __lock_acquire+0x2e7/0xe53 [ 1357.238450] [] ? pvclock_clocksource_read+0x48/0xb4 [ 1357.238450] [] ? rcu_process_gp_end+0xc0/0xc9 [ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] [ 1357.238450] [] lock_acquire+0x119/0x143 [ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] [ 1357.238450] [] _raw_spin_lock_irqsave+0x54/0x8e [ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] [ 1357.238450] [] transport_deregister_session+0x41/0x148 [target_core_mod] [ 1357.238450] [] ? rcu_process_callbacks+0x229/0x42a [ 1357.238450] [] ft_sess_rcu_free+0x17/0x24 [tcm_fc] [ 1357.238450] [] ? ft_sess_free+0x1b/0x1b [tcm_fc] [ 1357.238450] [] rcu_process_callbacks+0x260/0x42a [ 1357.238450] [] __do_softirq+0x13a/0x26f [ 1357.238450] [] ? __schedule+0x65f/0x68e [ 1357.238450] [] run_ksoftirqd+0x29/0x62 [ 1357.238450] [] smpboot_thread_fn+0x1a5/0x1aa [ 1357.238450] [] ? smpboot_unregister_percpu_thread+0x47/0x47 [ 1357.238450] [] kthread+0xb1/0xb9 [ 1357.238450] [] ? wait_for_common+0xbb/0x10a [ 1357.238450] [] ? __init_kthread_worker+0x59/0x59 [ 1357.238450] [] ret_from_fork+0x7c/0xb0 [ 1357.238450] [] ? __init_kthread_worker+0x59/0x59 [ 1417.440099] rport-2:0-0: blocked FC remote port time out: removing rport Signed-off-by: Yi Zou Cc: Open-FCoE Cc: Nicholas A. Bellinger Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/tcm_fc/tfc_sess.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 87901fa74dd7..a426c4020be0 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -431,7 +431,6 @@ static void ft_sess_rcu_free(struct rcu_head *rcu) { struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu); - transport_deregister_session(sess->se_sess); kfree(sess); } @@ -439,6 +438,7 @@ static void ft_sess_free(struct kref *kref) { struct ft_sess *sess = container_of(kref, struct ft_sess, kref); + transport_deregister_session(sess->se_sess); call_rcu(&sess->rcu, ft_sess_rcu_free); } -- GitLab From 4bc4d7ec50d4811610197ee7707559022250724a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Nov 2012 12:05:33 +0900 Subject: [PATCH 1366/1799] mfd: wm8994: Add support for WM1811 rev E commit fee546ce8cfd9dea1f53175f627e17ef5ff05df4 upstream. This is supported identically to the previous revisions. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/wm8994-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 9d7ca1e978fa..8d46e68cb178 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -541,6 +541,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) case 1: case 2: case 3: + case 4: regmap_patch = wm1811_reva_patch; patch_regs = ARRAY_SIZE(wm1811_reva_patch); break; -- GitLab From af713fb8e79809aa46f16de4f209245c39b9d7eb Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 9 Nov 2012 16:15:28 +0000 Subject: [PATCH 1367/1799] mfd: Only unregister platform devices allocated by the mfd core commit b9fbb62eb61452d728c39b2e5020739c575aac53 upstream. mfd_remove_devices would iterate over all devices sharing a parent with an mfd device regardless of whether they were allocated by the mfd core or not. This especially caused problems when the device structure was not contained within a platform_device, because to_platform_device is used on each device pointer. This patch defines a device_type for mfd devices and checks this is present from mfd_remove_devices_fn before processing the device. Signed-off-by: Charles Keepax Tested-by: Peter Tyser Reviewed-by: Mark Brown Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/mfd-core.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index ffc3d48676ae..ef80da67eb53 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -19,6 +19,10 @@ #include #include +static struct device_type mfd_dev_type = { + .name = "mfd_device", +}; + int mfd_cell_enable(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); @@ -88,6 +92,7 @@ static int mfd_add_device(struct device *parent, int id, goto fail_device; pdev->dev.parent = parent; + pdev->dev.type = &mfd_dev_type; if (cell->pdata_size) { ret = platform_device_add_data(pdev, @@ -183,10 +188,16 @@ EXPORT_SYMBOL(mfd_add_devices); static int mfd_remove_devices_fn(struct device *dev, void *c) { - struct platform_device *pdev = to_platform_device(dev); - const struct mfd_cell *cell = mfd_get_cell(pdev); + struct platform_device *pdev; + const struct mfd_cell *cell; atomic_t **usage_count = c; + if (dev->type != &mfd_dev_type) + return 0; + + pdev = to_platform_device(dev); + cell = mfd_get_cell(pdev); + /* find the base address of usage_count pointers (for freeing) */ if (!*usage_count || (cell->usage_count < *usage_count)) *usage_count = cell->usage_count; -- GitLab From aadee0f004ac85d2afd1cd03279d3dc01363258c Mon Sep 17 00:00:00 2001 From: Eugene Shatokhin Date: Thu, 8 Nov 2012 15:11:11 -0500 Subject: [PATCH 1368/1799] ext4: fix memory leak in ext4_xattr_set_acl()'s error path commit 24ec19b0ae83a385ad9c55520716da671274b96c upstream. In ext4_xattr_set_acl(), if ext4_journal_start() returns an error, posix_acl_release() will not be called for 'acl' which may result in a memory leak. This patch fixes that. Reviewed-by: Lukas Czerner Signed-off-by: Eugene Shatokhin Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/acl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index a5c29bb3b835..8535c45dfceb 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c @@ -410,8 +410,10 @@ ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value, retry: handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb)); - if (IS_ERR(handle)) - return PTR_ERR(handle); + if (IS_ERR(handle)) { + error = PTR_ERR(handle); + goto release_and_out; + } error = ext4_set_acl(handle, inode, type, acl); ext4_journal_stop(handle); if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) -- GitLab From 6b4b4679f40d6d112eda435a9dde937bb41c9bfc Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 29 Nov 2012 21:21:22 -0500 Subject: [PATCH 1369/1799] ext4: fix possible use after free with metadata csum commit aeb1e5d69a5be592e86a926be73efb38c55af404 upstream. Commit fa77dcfafeaa introduces block bitmap checksum calculation into ext4_new_inode() in the case that block group was uninitialized. However we brelse() the bitmap buffer before we attempt to checksum it so we have no guarantee that the buffer is still there. Fix this by releasing the buffer after the possible checksum computation. Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" Acked-by: Darrick J. Wong Signed-off-by: Greg Kroah-Hartman --- fs/ext4/ialloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 556cc821652c..902544e7ee5c 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -734,7 +734,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap"); err = ext4_handle_dirty_metadata(handle, NULL, block_bitmap_bh); - brelse(block_bitmap_bh); /* recheck and clear flag under lock if we still need to */ ext4_lock_group(sb, group); @@ -746,6 +745,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, gdp); } ext4_unlock_group(sb, group); + brelse(block_bitmap_bh); if (err) goto fail; -- GitLab From 272965fcdaf55d0930dbc594fdfd93cd13fcc8cd Mon Sep 17 00:00:00 2001 From: Nathan Williams Date: Thu, 22 Nov 2012 10:42:52 +1100 Subject: [PATCH 1370/1799] mtd cs553x_nand: Initialise ecc.strength before nand_scan() commit d1f3b65d2d6fdb4bf0edd4b67e86e191af48daee upstream. Loading cs553x_nand with Hynix H27U1G8F2BTR NAND flash causes this bug: kernel BUG at drivers/mtd/nand/nand_base.c:3345! invalid opcode: 0000 [#1] Modules linked in: cs553x_nand(+) vfat fat usb_storage ehci_hcd usbcore usb_comr Pid: 436, comm: modprobe Not tainted 3.6.7 #1 EIP: 0060:[] EFLAGS: 00010296 CPU: 0 EIP is at nand_scan_tail+0x64c/0x69c EAX: 00000034 EBX: cea6ed98 ECX: 00000000 EDX: 00000000 ESI: cea6ec00 EDI: cea6ec00 EBP: 20000000 ESP: cdd17e48 DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068 CR0: 8005003b CR2: 0804e119 CR3: 0d850000 CR4: 00000090 DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 DR6: ffff0ff0 DR7: 00000400 Process modprobe (pid: 436, ti=cdd16000 task=cdd1c320 task.ti=cdd16000) Stack: c12e962c c118f7ef 00000003 cea6ed98 d014b25c 20000000 fffff007 00000001 00000000 cdd53b00 d014b000 c1001021 cdd53b00 d01493c0 cdd53b00 cdd53b00 d01493c0 c1047f83 d014b4a0 00000000 cdd17f9c ce4be454 cdd17f48 cdd1c320 Call Trace: [] ? nand_scan+0x1b/0x4d [] ? init_module+0x25c/0x2de [cs553x_nand] [] ? 0xd014afff [] ? do_one_initcall+0x21/0x111 [] ? sys_init_module+0xe4/0x1261 [] ? task_work_run+0x36/0x43 [] ? syscall_call+0x7/0xb Code: fa ff ff c7 86 d8 00 00 00 01 00 00 00 e9 5f fc ff ff 68 f8 26 2e c1 e8 a7 EIP: [] nand_scan_tail+0x64c/0x69c SS:ESP 0068:cdd17e48 Initialising ecc.strength before the call to nand_scan() fixes this. Signed-off-by: Nathan Williams Acked-by: Brian Norris Acked-by: Mike Dunn Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/cs553x_nand.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index 821c34c62500..0b9b472b52be 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c @@ -237,6 +237,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) this->ecc.hwctl = cs_enable_hwecc; this->ecc.calculate = cs_calculate_ecc; this->ecc.correct = nand_correct_data; + this->ecc.strength = 1; /* Enable the following for a flash based bad block table */ this->bbt_options = NAND_BBT_USE_FLASH; @@ -248,8 +249,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) goto out_ior; } - this->ecc.strength = 1; - new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs); cs553x_mtd[cs] = new_mtd; -- GitLab From b53673dcf8a31a4b2f41fdf2fa168b7c693fd7b3 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 5 Dec 2012 21:46:02 +0100 Subject: [PATCH 1371/1799] mtd: nand: gpmi: reset BCH earlier, too, to avoid NAND startup problems commit 6f2a6a52560ad8d85710aabd92b7a3239b3a6b07 upstream. It could happen (1 out of 100 times) that NAND did not start up correctly after warm rebooting, so the kernel could not find the UBI or DMA timed out due to a stalled BCH. When resetting BCH together with GPMI, the issue could not be observed anymore (after 10000+ reboots). We probably need the consistent state already before sending any command to NAND, even when no ECC is needed. I chose to keep the extra reset for BCH when changing the flash layout to be on the safe side. Signed-off-by: Wolfram Sang Acked-by: Huang Shijie Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/gpmi-nand/gpmi-lib.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index e8ea7107932e..022feb45c15e 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -135,6 +135,15 @@ int gpmi_init(struct gpmi_nand_data *this) if (ret) goto err_out; + /* + * Reset BCH here, too. We got failures otherwise :( + * See later BCH reset for explanation of MX23 handling + */ + ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); + if (ret) + goto err_out; + + /* Choose NAND mode. */ writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR); -- GitLab From 65ac5efcd7e36ddf4cbe7d9e7f844a016dba4f7d Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Mon, 17 Dec 2012 20:18:52 +0300 Subject: [PATCH 1372/1799] SUNRPC: continue run over clients list on PipeFS event instead of break commit cd6c5968582a273561464fe6b1e8cc8214be02df upstream. There are SUNRPC clients, which program doesn't have pipe_dir_name. These clients can be skipped on PipeFS events, because nothing have to be created or destroyed. But instead of breaking in case of such a client was found, search for suitable client over clients list have to be continued. Otherwise some clients could not be covered by PipeFS event handler. Signed-off-by: Stanislav Kinsbursky Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/clnt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 57f2731d957a..a28a2111297e 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -236,7 +236,7 @@ static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event) spin_lock(&sn->rpc_client_lock); list_for_each_entry(clnt, &sn->all_clients, cl_clients) { if (clnt->cl_program->pipe_dir_name == NULL) - break; + continue; if (rpc_clnt_skip_event(clnt, event)) continue; if (atomic_inc_not_zero(&clnt->cl_count) == 0) -- GitLab From d5b319960ab9e0770b6ecae94045b512cd3029b7 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 4 Jan 2013 12:23:21 -0500 Subject: [PATCH 1373/1799] SUNRPC: Ensure that we free the rpc_task after cleanups are done commit c6567ed1402c55e19b012e66a8398baec2a726f3 upstream. This patch ensures that we free the rpc_task after the cleanup callbacks are done in order to avoid a deadlock problem that can be triggered if the callback needs to wait for another workqueue item to complete. Signed-off-by: Trond Myklebust Cc: Weston Andros Adamson Cc: Tejun Heo Cc: Bruce Fields Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/sched.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index eda32ae7dec4..fe2cf2f18d2c 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -915,16 +915,35 @@ struct rpc_task *rpc_new_task(const struct rpc_task_setup *setup_data) return task; } +/* + * rpc_free_task - release rpc task and perform cleanups + * + * Note that we free up the rpc_task _after_ rpc_release_calldata() + * in order to work around a workqueue dependency issue. + * + * Tejun Heo states: + * "Workqueue currently considers two work items to be the same if they're + * on the same address and won't execute them concurrently - ie. it + * makes a work item which is queued again while being executed wait + * for the previous execution to complete. + * + * If a work function frees the work item, and then waits for an event + * which should be performed by another work item and *that* work item + * recycles the freed work item, it can create a false dependency loop. + * There really is no reliable way to detect this short of verifying + * every memory free." + * + */ static void rpc_free_task(struct rpc_task *task) { - const struct rpc_call_ops *tk_ops = task->tk_ops; - void *calldata = task->tk_calldata; + unsigned short tk_flags = task->tk_flags; + + rpc_release_calldata(task->tk_ops, task->tk_calldata); - if (task->tk_flags & RPC_TASK_DYNAMIC) { + if (tk_flags & RPC_TASK_DYNAMIC) { dprintk("RPC: %5u freeing task\n", task->tk_pid); mempool_free(task, rpc_task_mempool); } - rpc_release_calldata(tk_ops, calldata); } static void rpc_async_release(struct work_struct *work) -- GitLab From 11d607dd94b7e1e4190f20581643555e620e3366 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 7 Jan 2013 14:30:46 -0500 Subject: [PATCH 1374/1799] SUNRPC: Ensure we release the socket write lock if the rpc_task exits early commit 87ed50036b866db2ec2ba16b2a7aec4a2b0b7c39 upstream. If the rpc_task exits while holding the socket write lock before it has allocated an rpc slot, then the usual mechanism for releasing the write lock in xprt_release() is defeated. The problem occurs if the call to xprt_lock_write() initially fails, so that the rpc_task is put on the xprt->sending wait queue. If the task exits after being assigned the lock by __xprt_lock_write_func, but before it has retried the call to xprt_lock_and_alloc_slot(), then it calls xprt_release() while holding the write lock, but will immediately exit due to the test for task->tk_rqstp != NULL. Reported-by: Chris Perl Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/sched.c | 3 +-- net/sunrpc/xprt.c | 12 ++++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index fe2cf2f18d2c..85b9235fbee2 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -953,8 +953,7 @@ static void rpc_async_release(struct work_struct *work) static void rpc_release_resources_task(struct rpc_task *task) { - if (task->tk_rqstp) - xprt_release(task); + xprt_release(task); if (task->tk_msg.rpc_cred) { put_rpccred(task->tk_msg.rpc_cred); task->tk_msg.rpc_cred = NULL; diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 176a24f0153b..feea4741edda 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -1139,10 +1139,18 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) void xprt_release(struct rpc_task *task) { struct rpc_xprt *xprt; - struct rpc_rqst *req; + struct rpc_rqst *req = task->tk_rqstp; - if (!(req = task->tk_rqstp)) + if (req == NULL) { + if (task->tk_client) { + rcu_read_lock(); + xprt = rcu_dereference(task->tk_client->cl_xprt); + if (xprt->snd_task == task) + xprt_release_write(xprt, task); + rcu_read_unlock(); + } return; + } xprt = req->rq_xprt; if (task->tk_ops->rpc_count_stats != NULL) -- GitLab From 7e94f31b2b9c1a1e976a7123ca9b96dddb3eeaae Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Mon, 5 Nov 2012 22:40:14 +0400 Subject: [PATCH 1375/1799] jffs2: hold erase_completion_lock on exit commit 2cbba75a56ea78e6876b4e2547a882f10b3fe72b upstream. Users of jffs2_do_reserve_space() expect they still held erase_completion_lock after call to it. But there is a path where jffs2_do_reserve_space() leaves erase_completion_lock unlocked. The patch fixes it. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- fs/jffs2/nodemgmt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 6784d1e7a7eb..ffa8f12c7a54 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -375,14 +375,16 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, spin_unlock(&c->erase_completion_lock); ret = jffs2_prealloc_raw_node_refs(c, jeb, 1); - if (ret) - return ret; + /* Just lock it again and continue. Nothing much can change because we hold c->alloc_sem anyway. In fact, it's not entirely clear why we hold c->erase_completion_lock in the majority of this function... but that's a question for another (more caffeine-rich) day. */ spin_lock(&c->erase_completion_lock); + if (ret) + return ret; + waste = jeb->free_size; jffs2_link_node_ref(c, jeb, (jeb->offset + c->sector_size - waste) | REF_OBSOLETE, -- GitLab From 9aba4c8888212a4a281107fec875eb1fd14cbb43 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 14 Dec 2012 13:10:50 +0000 Subject: [PATCH 1376/1799] i2400m: add Intel 6150 device IDs commit 999a7c5776a0ed2133645fa7e008bec05bda9254 upstream. Add device IDs for WiMAX function of Intel 6150 cards. Signed-off-by: Dan Williams Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/wimax/i2400m/i2400m-usb.h | 3 +++ drivers/net/wimax/i2400m/usb.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h index 6650fde99e1d..9f1e947f3557 100644 --- a/drivers/net/wimax/i2400m/i2400m-usb.h +++ b/drivers/net/wimax/i2400m/i2400m-usb.h @@ -152,6 +152,9 @@ enum { /* Device IDs */ USB_DEVICE_ID_I6050 = 0x0186, USB_DEVICE_ID_I6050_2 = 0x0188, + USB_DEVICE_ID_I6150 = 0x07d6, + USB_DEVICE_ID_I6150_2 = 0x07d7, + USB_DEVICE_ID_I6150_3 = 0x07d9, USB_DEVICE_ID_I6250 = 0x0187, }; diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 29b1e033a10b..f0f16e0c6127 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -510,6 +510,9 @@ int i2400mu_probe(struct usb_interface *iface, switch (id->idProduct) { case USB_DEVICE_ID_I6050: case USB_DEVICE_ID_I6050_2: + case USB_DEVICE_ID_I6150: + case USB_DEVICE_ID_I6150_2: + case USB_DEVICE_ID_I6150_3: case USB_DEVICE_ID_I6250: i2400mu->i6050 = 1; break; @@ -759,6 +762,9 @@ static struct usb_device_id i2400mu_id_table[] = { { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) }, { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) }, + { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150) }, + { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_2) }, + { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_3) }, { USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) }, { USB_DEVICE(0x8086, 0x0181) }, { USB_DEVICE(0x8086, 0x1403) }, -- GitLab From 16639bce521c713cf623ac4a4ff085c18a48674e Mon Sep 17 00:00:00 2001 From: "Woodhouse, David" Date: Wed, 19 Dec 2012 13:25:35 +0000 Subject: [PATCH 1377/1799] intel-iommu: Free old page tables before creating superpage commit 6491d4d02893d9787ba67279595990217177b351 upstream. The dma_pte_free_pagetable() function will only free a page table page if it is asked to free the *entire* 2MiB range that it covers. So if a page table page was used for one or more small mappings, it's likely to end up still present in the page tables... but with no valid PTEs. This was fine when we'd only be repopulating it with 4KiB PTEs anyway but the same virtual address range can end up being reused for a *large-page* mapping. And in that case were were trying to insert the large page into the second-level page table, and getting a complaint from the sanity check in __domain_mapping() because there was already a corresponding entry. This was *relatively* harmless; it led to a memory leak of the old page table page, but no other ill-effects. Fix it by calling dma_pte_clear_range (hopefully redundant) and dma_pte_free_pagetable() before setting up the new large page. Signed-off-by: David Woodhouse Tested-by: Ravi Murty Tested-by: Sudeep Dutt Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel-iommu.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 0d251d301be6..9c34db8e7295 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1826,10 +1826,17 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, if (!pte) return -ENOMEM; /* It is large page*/ - if (largepage_lvl > 1) + if (largepage_lvl > 1) { pteval |= DMA_PTE_LARGE_PAGE; - else + /* Ensure that old small page tables are removed to make room + for superpage, if they exist. */ + dma_pte_clear_range(domain, iov_pfn, + iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); + dma_pte_free_pagetable(domain, iov_pfn, + iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); + } else { pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE; + } } /* We don't need lock here, nobody else -- GitLab From a98843e161b490b91fac1b7e0daa4ba9517bf65a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 4 Dec 2012 16:50:28 -0500 Subject: [PATCH 1378/1799] drm/radeon: fix eDP clk and lane setup for scaled modes commit 93927f9c1db5f55085457e820f0631064c7bfa34 upstream. Need to use the adjusted mode since we are sending native timing and using the scaler for non-native modes. Signed-off-by: Alex Deucher Reviewed-by: Jerome Glisse Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_encoders.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index f6176bc90f12..23e3ea6ba148 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -95,7 +95,7 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); - radeon_dp_set_link_config(connector, mode); + radeon_dp_set_link_config(connector, adjusted_mode); } return true; -- GitLab From e4a5d6d17f6dff0174ba1c0b2041d73ec7d0c1dd Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 20 Dec 2012 21:19:32 -0500 Subject: [PATCH 1379/1799] drm/radeon: add WAIT_UNTIL to evergreen VM safe reg list commit 668bbc81baf0f34df832d8aca5c7d5e19a493c68 upstream. It's used in a recent mesa commit: http://cgit.freedesktop.org/mesa/mesa/commit/?id=24b1206ab2dcd506aaac3ef656aebc8bc20cd27a and there may be some other cases in the future where it's required. Signed-off-by: Alex Deucher Reviewed-by: Jerome Glisse Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen_cs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 22c84bcfaebf..2cbd369e0fcb 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -2670,6 +2670,7 @@ static bool evergreen_vm_reg_valid(u32 reg) /* check config regs */ switch (reg) { + case WAIT_UNTIL: case GRBM_GFX_INDEX: case CP_STRMOUT_CNTL: case CP_COHER_CNTL: -- GitLab From 5df148ba552817a8d3eb9d2ace557deb178192e6 Mon Sep 17 00:00:00 2001 From: Niels Ole Salscheider Date: Thu, 3 Jan 2013 19:09:28 +0100 Subject: [PATCH 1380/1799] drm/radeon: Properly handle DDC probe for DP bridges commit 0a9069d34918659bc8a89e21e69e60b2b83291a3 upstream. DDC information can be accessed using AUX CH Fixes failure to probe monitors on some systems with DP bridge chips. agd5f: minor fixes Signed-off-by: Niels Ole Salscheider Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_connectors.c | 10 ++++++---- drivers/gpu/drm/radeon/radeon_display.c | 13 +++++++++---- drivers/gpu/drm/radeon/radeon_i2c.c | 10 ++++++++-- drivers/gpu/drm/radeon/radeon_mode.h | 2 +- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 3fb7ca922069..ab63bcd17277 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -689,7 +689,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force) ret = connector_status_disconnected; if (radeon_connector->ddc_bus) - dret = radeon_ddc_probe(radeon_connector); + dret = radeon_ddc_probe(radeon_connector, false); if (dret) { radeon_connector->detected_by_load = false; if (radeon_connector->edid) { @@ -895,7 +895,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) return connector->status; if (radeon_connector->ddc_bus) - dret = radeon_ddc_probe(radeon_connector); + dret = radeon_ddc_probe(radeon_connector, false); if (dret) { radeon_connector->detected_by_load = false; if (radeon_connector->edid) { @@ -1335,7 +1335,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force) if (encoder) { /* setup ddc on the bridge */ radeon_atom_ext_encoder_setup_ddc(encoder); - if (radeon_ddc_probe(radeon_connector)) /* try DDC */ + /* bridge chips are always aux */ + if (radeon_ddc_probe(radeon_connector, true)) /* try DDC */ ret = connector_status_connected; else if (radeon_connector->dac_load_detect) { /* try load detection */ struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; @@ -1353,7 +1354,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force) if (radeon_dp_getdpcd(radeon_connector)) ret = connector_status_connected; } else { - if (radeon_ddc_probe(radeon_connector)) + /* try non-aux ddc (DP to DVI/HMDI/etc. adapter) */ + if (radeon_ddc_probe(radeon_connector, false)) ret = connector_status_connected; } } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 0a1d4bd65edc..173b97b2819b 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -713,10 +713,15 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) if (radeon_connector->router.ddc_valid) radeon_router_select_ddc_port(radeon_connector); - if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || - (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) || - (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != - ENCODER_OBJECT_ID_NONE)) { + if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != + ENCODER_OBJECT_ID_NONE) { + struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; + + if (dig->dp_i2c_bus) + radeon_connector->edid = drm_get_edid(&radeon_connector->base, + &dig->dp_i2c_bus->adapter); + } else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || + (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 3edec1c198e3..6076e85aa5da 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -39,7 +39,7 @@ extern u32 radeon_atom_hw_i2c_func(struct i2c_adapter *adap); * radeon_ddc_probe * */ -bool radeon_ddc_probe(struct radeon_connector *radeon_connector) +bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux) { u8 out = 0x0; u8 buf[8]; @@ -63,7 +63,13 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector) if (radeon_connector->router.ddc_valid) radeon_router_select_ddc_port(radeon_connector); - ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); + if (use_aux) { + struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; + ret = i2c_transfer(&dig->dp_i2c_bus->adapter, msgs, 2); + } else { + ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); + } + if (ret != 2) /* Couldn't find an accessible DDC on this connector */ return false; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 778c1f0d7b81..dabfefda8f55 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -527,7 +527,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c, u8 val); extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector); extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); -extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); +extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux); extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); -- GitLab From 297456d8fe2b141f0f05b5d6ff48a4cd0b5f5889 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 20 Nov 2012 13:27:41 -0200 Subject: [PATCH 1381/1799] drm/i915: make the panel fitter work on pipes B and C on IVB commit 13888d78c664a1f61d7b09d282f5916993827a40 upstream. I actually found this problem on Haswell, but then discovered Ivy Bridge also has it by reading the spec. I don't have the hardware to test this. Signed-off-by: Paulo Zanoni Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_display.c | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 29bfd8995738..cd1a85a68809 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3015,6 +3015,8 @@ #define _PFA_CTL_1 0x68080 #define _PFB_CTL_1 0x68880 #define PF_ENABLE (1<<31) +#define PF_PIPE_SEL_MASK_IVB (3<<29) +#define PF_PIPE_SEL_IVB(pipe) ((pipe)<<29) #define PF_FILTER_MASK (3<<23) #define PF_FILTER_PROGRAMMED (0<<23) #define PF_FILTER_MED_3x3 (1<<23) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index dd3e7e44023e..fd150a98a626 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3095,7 +3095,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) * as some pre-programmed values are broken, * e.g. x201. */ - I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3); + if (IS_IVYBRIDGE(dev)) + I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 | + PF_PIPE_SEL_IVB(pipe)); + else + I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3); I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos); I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size); } -- GitLab From c7cde2b3d27a5417021d7fc6da0f7941eab63769 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 8 Nov 2012 10:01:26 -0500 Subject: [PATCH 1382/1799] SUNRPC: Fix validity issues with rpc_pipefs sb->s_fs_info commit 642fe4d00db56d65060ce2fd4c105884414acb16 upstream. rpc_kill_sb() must defer calling put_net() until after the notifier has been called, since most (all?) of the notifier callbacks assume that sb->s_fs_info points to a valid net namespace. It also must not call put_net() if the call to rpc_fill_super was unsuccessful. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=48421 Signed-off-by: Trond Myklebust Cc: Stanislav Kinsbursky Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/rpc_pipe.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index faa078f74b27..b8bda4434c05 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -1157,14 +1157,19 @@ static void rpc_kill_sb(struct super_block *sb) struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); mutex_lock(&sn->pipefs_sb_lock); + if (sn->pipefs_sb != sb) { + mutex_unlock(&sn->pipefs_sb_lock); + goto out; + } sn->pipefs_sb = NULL; mutex_unlock(&sn->pipefs_sb_lock); - put_net(net); dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", net, NET_NAME(net)); blocking_notifier_call_chain(&rpc_pipefs_notifier_list, RPC_PIPEFS_UMOUNT, sb); + put_net(net); +out: kill_litter_super(sb); } -- GitLab From e5ca2896f817ef43802387ae2f41a9c70e30ee86 Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Thu, 6 Dec 2012 20:05:02 +0000 Subject: [PATCH 1383/1799] RDMA/nes: Fix for crash when registering zero length MR for CQ commit 7d9c199a55200c9b9fcad08e150470d02fb385be upstream. Signed-off-by: Tatyana Nikolova Signed-off-by: Roland Dreier Signed-off-by: CAI Qian Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/nes/nes_verbs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 8b8812de4b5c..7082c36d57ca 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -2559,6 +2559,11 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, return ibmr; case IWNES_MEMREG_TYPE_QP: case IWNES_MEMREG_TYPE_CQ: + if (!region->length) { + nes_debug(NES_DBG_MR, "Unable to register zero length region for CQ\n"); + ib_umem_release(region); + return ERR_PTR(-EINVAL); + } nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL); if (!nespbl) { nes_debug(NES_DBG_MR, "Unable to allocate PBL\n"); -- GitLab From 0d38a8789caf511e5b997caf76eb32fddbff051c Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Thu, 6 Dec 2012 19:58:27 +0000 Subject: [PATCH 1384/1799] RDMA/nes: Fix for terminate timer crash commit 7bfcfa51c35cdd2d37e0d70fc11790642dd11fb3 upstream. The terminate timer needs to be initialized just once. Signed-off-by: Tatyana Nikolova Signed-off-by: Roland Dreier Signed-off-by: CAI Qian Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/nes/nes.h | 1 + drivers/infiniband/hw/nes/nes_hw.c | 9 ++------- drivers/infiniband/hw/nes/nes_verbs.c | 4 +++- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index c438e4691b3c..3f41d9f5f703 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h @@ -524,6 +524,7 @@ void nes_iwarp_ce_handler(struct nes_device *, struct nes_hw_cq *); int nes_destroy_cqp(struct nes_device *); int nes_nic_cm_xmit(struct sk_buff *, struct net_device *); void nes_recheck_link_status(struct work_struct *work); +void nes_terminate_timeout(unsigned long context); /* nes_nic.c */ struct net_device *nes_netdev_init(struct nes_device *, void __iomem *); diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index d42c9f435b1b..96801c3a1fe8 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -75,7 +75,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, static void process_critical_error(struct nes_device *nesdev); static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number); static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode); -static void nes_terminate_timeout(unsigned long context); static void nes_terminate_start_timer(struct nes_qp *nesqp); #ifdef CONFIG_INFINIBAND_NES_DEBUG @@ -3522,7 +3521,7 @@ static void nes_terminate_received(struct nes_device *nesdev, } /* Timeout routine in case terminate fails to complete */ -static void nes_terminate_timeout(unsigned long context) +void nes_terminate_timeout(unsigned long context) { struct nes_qp *nesqp = (struct nes_qp *)(unsigned long)context; @@ -3532,11 +3531,7 @@ static void nes_terminate_timeout(unsigned long context) /* Set a timer in case hw cannot complete the terminate sequence */ static void nes_terminate_start_timer(struct nes_qp *nesqp) { - init_timer(&nesqp->terminate_timer); - nesqp->terminate_timer.function = nes_terminate_timeout; - nesqp->terminate_timer.expires = jiffies + HZ; - nesqp->terminate_timer.data = (unsigned long)nesqp; - add_timer(&nesqp->terminate_timer); + mod_timer(&nesqp->terminate_timer, (jiffies + HZ)); } /** diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 7082c36d57ca..da84ea383f93 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1404,6 +1404,9 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, } nesqp->sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR); + init_timer(&nesqp->terminate_timer); + nesqp->terminate_timer.function = nes_terminate_timeout; + nesqp->terminate_timer.data = (unsigned long)nesqp; /* update the QP table */ nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp; @@ -1413,7 +1416,6 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, return &nesqp->ibqp; } - /** * nes_clean_cq */ -- GitLab From 4d7981bfc21f7b6ef48f9a819d2c9969ad6eea71 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 29 Nov 2012 22:31:16 -0500 Subject: [PATCH 1385/1799] ring-buffer: Fix race between integrity check and readers commit 9366c1ba13fbc41bdb57702e75ca4382f209c82f upstream. The function rb_check_pages() was added to make sure the ring buffer's pages were sane. This check is done when the ring buffer size is modified as well as when the iterator is released (closing the "trace" file), as that was considered a non fast path and a good place to do a sanity check. The problem is that the check does not have any locks around it. If one process were to read the trace file, and another were to read the raw binary file, the check could happen while the reader is reading the file. The issues with this is that the check requires to clear the HEAD page before doing the full check and it restores it afterward. But readers require the HEAD page to exist before it can read the buffer, otherwise it gives a nasty warning and disables the buffer. By adding the reader lock around the check, this keeps the race from happening. Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ring_buffer.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index cf8d11e91efd..28667834181e 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -2708,7 +2708,7 @@ unsigned long ring_buffer_oldest_event_ts(struct ring_buffer *buffer, int cpu) unsigned long flags; struct ring_buffer_per_cpu *cpu_buffer; struct buffer_page *bpage; - unsigned long ret; + unsigned long ret = 0; if (!cpumask_test_cpu(cpu, buffer->cpumask)) return 0; @@ -2723,7 +2723,8 @@ unsigned long ring_buffer_oldest_event_ts(struct ring_buffer *buffer, int cpu) bpage = cpu_buffer->reader_page; else bpage = rb_set_head_page(cpu_buffer); - ret = bpage->page->time_stamp; + if (bpage) + ret = bpage->page->time_stamp; raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); return ret; @@ -3030,6 +3031,8 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) * Splice the empty reader page into the list around the head. */ reader = rb_set_head_page(cpu_buffer); + if (!reader) + goto out; cpu_buffer->reader_page->list.next = rb_list_head(reader->list.next); cpu_buffer->reader_page->list.prev = reader->list.prev; -- GitLab From 38d67580f65e46ec13c65c8ebb0666134f167658 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Fri, 21 Dec 2012 20:23:30 +0000 Subject: [PATCH 1386/1799] dm persistent data: rename node to btree_node commit 550929faf89e2e2cdb3e9945ea87d383989274cf upstream. This patch fixes a compilation failure on sparc32 by renaming struct node. struct node is already defined in include/linux/node.h. On sparc32, it happens to be included through other dependencies and persistent-data doesn't compile because of conflicting declarations. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- .../md/persistent-data/dm-btree-internal.h | 16 +++--- drivers/md/persistent-data/dm-btree-remove.c | 50 +++++++++---------- drivers/md/persistent-data/dm-btree-spine.c | 6 +-- drivers/md/persistent-data/dm-btree.c | 22 ++++---- 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/persistent-data/dm-btree-internal.h index 5709bfeab1e8..accbb05f17b6 100644 --- a/drivers/md/persistent-data/dm-btree-internal.h +++ b/drivers/md/persistent-data/dm-btree-internal.h @@ -36,13 +36,13 @@ struct node_header { __le32 padding; } __packed; -struct node { +struct btree_node { struct node_header header; __le64 keys[0]; } __packed; -void inc_children(struct dm_transaction_manager *tm, struct node *n, +void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, struct dm_btree_value_type *vt); int new_block(struct dm_btree_info *info, struct dm_block **result); @@ -64,7 +64,7 @@ struct ro_spine { void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info); int exit_ro_spine(struct ro_spine *s); int ro_step(struct ro_spine *s, dm_block_t new_child); -struct node *ro_node(struct ro_spine *s); +struct btree_node *ro_node(struct ro_spine *s); struct shadow_spine { struct dm_btree_info *info; @@ -98,17 +98,17 @@ int shadow_root(struct shadow_spine *s); /* * Some inlines. */ -static inline __le64 *key_ptr(struct node *n, uint32_t index) +static inline __le64 *key_ptr(struct btree_node *n, uint32_t index) { return n->keys + index; } -static inline void *value_base(struct node *n) +static inline void *value_base(struct btree_node *n) { return &n->keys[le32_to_cpu(n->header.max_entries)]; } -static inline void *value_ptr(struct node *n, uint32_t index) +static inline void *value_ptr(struct btree_node *n, uint32_t index) { uint32_t value_size = le32_to_cpu(n->header.value_size); return value_base(n) + (value_size * index); @@ -117,7 +117,7 @@ static inline void *value_ptr(struct node *n, uint32_t index) /* * Assumes the values are suitably-aligned and converts to core format. */ -static inline uint64_t value64(struct node *n, uint32_t index) +static inline uint64_t value64(struct btree_node *n, uint32_t index) { __le64 *values_le = value_base(n); @@ -127,7 +127,7 @@ static inline uint64_t value64(struct node *n, uint32_t index) /* * Searching for a key within a single node. */ -int lower_bound(struct node *n, uint64_t key); +int lower_bound(struct btree_node *n, uint64_t key); extern struct dm_block_validator btree_node_validator; diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c index aa71e2359a07..c4f28133ef82 100644 --- a/drivers/md/persistent-data/dm-btree-remove.c +++ b/drivers/md/persistent-data/dm-btree-remove.c @@ -53,7 +53,7 @@ /* * Some little utilities for moving node data around. */ -static void node_shift(struct node *n, int shift) +static void node_shift(struct btree_node *n, int shift) { uint32_t nr_entries = le32_to_cpu(n->header.nr_entries); uint32_t value_size = le32_to_cpu(n->header.value_size); @@ -79,7 +79,7 @@ static void node_shift(struct node *n, int shift) } } -static void node_copy(struct node *left, struct node *right, int shift) +static void node_copy(struct btree_node *left, struct btree_node *right, int shift) { uint32_t nr_left = le32_to_cpu(left->header.nr_entries); uint32_t value_size = le32_to_cpu(left->header.value_size); @@ -108,7 +108,7 @@ static void node_copy(struct node *left, struct node *right, int shift) /* * Delete a specific entry from a leaf node. */ -static void delete_at(struct node *n, unsigned index) +static void delete_at(struct btree_node *n, unsigned index) { unsigned nr_entries = le32_to_cpu(n->header.nr_entries); unsigned nr_to_copy = nr_entries - (index + 1); @@ -128,7 +128,7 @@ static void delete_at(struct node *n, unsigned index) n->header.nr_entries = cpu_to_le32(nr_entries - 1); } -static unsigned merge_threshold(struct node *n) +static unsigned merge_threshold(struct btree_node *n) { return le32_to_cpu(n->header.max_entries) / 3; } @@ -136,7 +136,7 @@ static unsigned merge_threshold(struct node *n) struct child { unsigned index; struct dm_block *block; - struct node *n; + struct btree_node *n; }; static struct dm_btree_value_type le64_type = { @@ -147,7 +147,7 @@ static struct dm_btree_value_type le64_type = { .equal = NULL }; -static int init_child(struct dm_btree_info *info, struct node *parent, +static int init_child(struct dm_btree_info *info, struct btree_node *parent, unsigned index, struct child *result) { int r, inc; @@ -177,7 +177,7 @@ static int exit_child(struct dm_btree_info *info, struct child *c) return dm_tm_unlock(info->tm, c->block); } -static void shift(struct node *left, struct node *right, int count) +static void shift(struct btree_node *left, struct btree_node *right, int count) { uint32_t nr_left = le32_to_cpu(left->header.nr_entries); uint32_t nr_right = le32_to_cpu(right->header.nr_entries); @@ -203,11 +203,11 @@ static void shift(struct node *left, struct node *right, int count) right->header.nr_entries = cpu_to_le32(nr_right + count); } -static void __rebalance2(struct dm_btree_info *info, struct node *parent, +static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent, struct child *l, struct child *r) { - struct node *left = l->n; - struct node *right = r->n; + struct btree_node *left = l->n; + struct btree_node *right = r->n; uint32_t nr_left = le32_to_cpu(left->header.nr_entries); uint32_t nr_right = le32_to_cpu(right->header.nr_entries); unsigned threshold = 2 * merge_threshold(left) + 1; @@ -239,7 +239,7 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info, unsigned left_index) { int r; - struct node *parent; + struct btree_node *parent; struct child left, right; parent = dm_block_data(shadow_current(s)); @@ -270,9 +270,9 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info, * in right, then rebalance2. This wastes some cpu, but I want something * simple atm. */ -static void delete_center_node(struct dm_btree_info *info, struct node *parent, +static void delete_center_node(struct dm_btree_info *info, struct btree_node *parent, struct child *l, struct child *c, struct child *r, - struct node *left, struct node *center, struct node *right, + struct btree_node *left, struct btree_node *center, struct btree_node *right, uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) { uint32_t max_entries = le32_to_cpu(left->header.max_entries); @@ -301,9 +301,9 @@ static void delete_center_node(struct dm_btree_info *info, struct node *parent, /* * Redistributes entries among 3 sibling nodes. */ -static void redistribute3(struct dm_btree_info *info, struct node *parent, +static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, struct child *l, struct child *c, struct child *r, - struct node *left, struct node *center, struct node *right, + struct btree_node *left, struct btree_node *center, struct btree_node *right, uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) { int s; @@ -343,12 +343,12 @@ static void redistribute3(struct dm_btree_info *info, struct node *parent, *key_ptr(parent, r->index) = right->keys[0]; } -static void __rebalance3(struct dm_btree_info *info, struct node *parent, +static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent, struct child *l, struct child *c, struct child *r) { - struct node *left = l->n; - struct node *center = c->n; - struct node *right = r->n; + struct btree_node *left = l->n; + struct btree_node *center = c->n; + struct btree_node *right = r->n; uint32_t nr_left = le32_to_cpu(left->header.nr_entries); uint32_t nr_center = le32_to_cpu(center->header.nr_entries); @@ -371,7 +371,7 @@ static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info, unsigned left_index) { int r; - struct node *parent = dm_block_data(shadow_current(s)); + struct btree_node *parent = dm_block_data(shadow_current(s)); struct child left, center, right; /* @@ -421,7 +421,7 @@ static int get_nr_entries(struct dm_transaction_manager *tm, { int r; struct dm_block *block; - struct node *n; + struct btree_node *n; r = dm_tm_read_lock(tm, b, &btree_node_validator, &block); if (r) @@ -438,7 +438,7 @@ static int rebalance_children(struct shadow_spine *s, { int i, r, has_left_sibling, has_right_sibling; uint32_t child_entries; - struct node *n; + struct btree_node *n; n = dm_block_data(shadow_current(s)); @@ -483,7 +483,7 @@ static int rebalance_children(struct shadow_spine *s, return r; } -static int do_leaf(struct node *n, uint64_t key, unsigned *index) +static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index) { int i = lower_bound(n, key); @@ -506,7 +506,7 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info, uint64_t key, unsigned *index) { int i = *index, r; - struct node *n; + struct btree_node *n; for (;;) { r = shadow_step(s, root, vt); @@ -556,7 +556,7 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root, unsigned level, last_level = info->levels - 1; int index = 0, r = 0; struct shadow_spine spine; - struct node *n; + struct btree_node *n; init_shadow_spine(&spine, info); for (level = 0; level < info->levels; level++) { diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c index d9a7912ee8ee..2f0805c3263e 100644 --- a/drivers/md/persistent-data/dm-btree-spine.c +++ b/drivers/md/persistent-data/dm-btree-spine.c @@ -23,7 +23,7 @@ static void node_prepare_for_write(struct dm_block_validator *v, struct dm_block *b, size_t block_size) { - struct node *n = dm_block_data(b); + struct btree_node *n = dm_block_data(b); struct node_header *h = &n->header; h->blocknr = cpu_to_le64(dm_block_location(b)); @@ -38,7 +38,7 @@ static int node_check(struct dm_block_validator *v, struct dm_block *b, size_t block_size) { - struct node *n = dm_block_data(b); + struct btree_node *n = dm_block_data(b); struct node_header *h = &n->header; size_t value_size; __le32 csum_disk; @@ -164,7 +164,7 @@ int ro_step(struct ro_spine *s, dm_block_t new_child) return r; } -struct node *ro_node(struct ro_spine *s) +struct btree_node *ro_node(struct ro_spine *s) { struct dm_block *block; diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c index d12b2cc51f1a..371f3d49d18e 100644 --- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c @@ -38,7 +38,7 @@ static void array_insert(void *base, size_t elt_size, unsigned nr_elts, /*----------------------------------------------------------------*/ /* makes the assumption that no two keys are the same. */ -static int bsearch(struct node *n, uint64_t key, int want_hi) +static int bsearch(struct btree_node *n, uint64_t key, int want_hi) { int lo = -1, hi = le32_to_cpu(n->header.nr_entries); @@ -58,12 +58,12 @@ static int bsearch(struct node *n, uint64_t key, int want_hi) return want_hi ? hi : lo; } -int lower_bound(struct node *n, uint64_t key) +int lower_bound(struct btree_node *n, uint64_t key) { return bsearch(n, key, 0); } -void inc_children(struct dm_transaction_manager *tm, struct node *n, +void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, struct dm_btree_value_type *vt) { unsigned i; @@ -77,7 +77,7 @@ void inc_children(struct dm_transaction_manager *tm, struct node *n, vt->inc(vt->context, value_ptr(n, i)); } -static int insert_at(size_t value_size, struct node *node, unsigned index, +static int insert_at(size_t value_size, struct btree_node *node, unsigned index, uint64_t key, void *value) __dm_written_to_disk(value) { @@ -122,7 +122,7 @@ int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root) { int r; struct dm_block *b; - struct node *n; + struct btree_node *n; size_t block_size; uint32_t max_entries; @@ -154,7 +154,7 @@ EXPORT_SYMBOL_GPL(dm_btree_empty); #define MAX_SPINE_DEPTH 64 struct frame { struct dm_block *b; - struct node *n; + struct btree_node *n; unsigned level; unsigned nr_children; unsigned current_child; @@ -295,7 +295,7 @@ EXPORT_SYMBOL_GPL(dm_btree_del); /*----------------------------------------------------------------*/ static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key, - int (*search_fn)(struct node *, uint64_t), + int (*search_fn)(struct btree_node *, uint64_t), uint64_t *result_key, void *v, size_t value_size) { int i, r; @@ -406,7 +406,7 @@ static int btree_split_sibling(struct shadow_spine *s, dm_block_t root, size_t size; unsigned nr_left, nr_right; struct dm_block *left, *right, *parent; - struct node *ln, *rn, *pn; + struct btree_node *ln, *rn, *pn; __le64 location; left = shadow_current(s); @@ -491,7 +491,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key) size_t size; unsigned nr_left, nr_right; struct dm_block *left, *right, *new_parent; - struct node *pn, *ln, *rn; + struct btree_node *pn, *ln, *rn; __le64 val; new_parent = shadow_current(s); @@ -576,7 +576,7 @@ static int btree_insert_raw(struct shadow_spine *s, dm_block_t root, uint64_t key, unsigned *index) { int r, i = *index, top = 1; - struct node *node; + struct btree_node *node; for (;;) { r = shadow_step(s, root, vt); @@ -643,7 +643,7 @@ static int insert(struct dm_btree_info *info, dm_block_t root, unsigned level, index = -1, last_level = info->levels - 1; dm_block_t block = root; struct shadow_spine spine; - struct node *n; + struct btree_node *n; struct dm_btree_value_type le64_type; le64_type.context = NULL; -- GitLab From 61652b1acea31009aff707b975a171567095df81 Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Fri, 21 Dec 2012 20:23:30 +0000 Subject: [PATCH 1387/1799] dm ioctl: prevent unsafe change to dm_ioctl data_size commit e910d7ebecd1aac43125944a8641b6cb1a0dfabe upstream. Abort dm ioctl processing if userspace changes the data_size parameter after we validated it but before we finished copying the data buffer from userspace. The dm ioctl parameters are processed in the following sequence: 1. ctl_ioctl() calls copy_params(); 2. copy_params() makes a first copy of the fixed-sized portion of the userspace parameters into the local variable "tmp"; 3. copy_params() then validates tmp.data_size and allocates a new structure big enough to hold the complete data and copies the whole userspace buffer there; 4. ctl_ioctl() reads userspace data the second time and copies the whole buffer into the pointer "param"; 5. ctl_ioctl() reads param->data_size without any validation and stores it in the variable "input_param_size"; 6. "input_param_size" is further used as the authoritative size of the kernel buffer. The problem is that userspace code could change the contents of user memory between steps 2 and 4. In particular, the data_size parameter can be changed to an invalid value after the kernel has validated it. This lets userspace force the kernel to access invalid kernel memory. The fix is to ensure that the size has not changed at step 4. This patch shouldn't have a security impact because CAP_SYS_ADMIN is required to run this code, but it should be fixed anyway. Reported-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-ioctl.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index a1a3e6df17b8..f011d4b3c139 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1563,6 +1563,14 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param) if (copy_from_user(dmi, user, tmp.data_size)) goto bad; + /* + * Abort if something changed the ioctl data while it was being copied. + */ + if (dmi->data_size != tmp.data_size) { + DMERR("rejecting ioctl: data size modified while processing parameters"); + goto bad; + } + /* Wipe the user buffer so we do not return it to userspace */ if (secure_data && clear_user(user, tmp.data_size)) goto bad; -- GitLab From 97e3cb7f7a27f4902fe75880149517713570da0e Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 7 Oct 2012 08:27:00 +0100 Subject: [PATCH 1388/1799] staging: vt6656: [BUG] out of bound array reference in RFbSetPower. commit ab1dd9963137a1e122004d5378a581bf16ae9bc8 upstream. Calling RFbSetPower with uCH zero value will cause out of bound array reference. This causes 64 bit kernels to oops on boot. Note: Driver does not function on 64 bit kernels and should be blacklisted on them. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/rf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c index 3fd0478a9a54..8cf0881888b2 100644 --- a/drivers/staging/vt6656/rf.c +++ b/drivers/staging/vt6656/rf.c @@ -769,6 +769,9 @@ BYTE byPwr = pDevice->byCCKPwr; return TRUE; } + if (uCH == 0) + return -EINVAL; + switch (uRATE) { case RATE_1M: case RATE_2M: -- GitLab From 27c1026faf863a716c5dcd61e479c10f215dce39 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 11 Nov 2012 15:32:05 +0000 Subject: [PATCH 1389/1799] staging: vt6656: 64 bit fixes: use u32 for QWORD definition. commit a552397d5e4ef0cc0bd3e9595d6acc9a3b381171 upstream. Size of long issues replace with u32. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/ttype.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/vt6656/ttype.h b/drivers/staging/vt6656/ttype.h index 8e9450ef3997..0f70562c0563 100644 --- a/drivers/staging/vt6656/ttype.h +++ b/drivers/staging/vt6656/ttype.h @@ -29,6 +29,8 @@ #ifndef __TTYPE_H__ #define __TTYPE_H__ +#include + /******* Common definitions and typedefs ***********************************/ typedef int BOOL; @@ -51,8 +53,8 @@ typedef unsigned long DWORD; // 32-bit // which is NOT really a floating point number. typedef union tagUQuadWord { struct { - DWORD dwLowDword; - DWORD dwHighDword; + u32 dwLowDword; + u32 dwHighDword; } u; double DoNotUseThisField; } UQuadWord; -- GitLab From a17de003d22c2dc9ddce8278d3c2be740e15da43 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 11 Nov 2012 15:41:25 +0000 Subject: [PATCH 1390/1799] staging: vt6656: 64 bit fixes : correct all type sizes commit 7730492855a2f9c828599bcd8d62760f96d319e4 upstream. After this patch all BYTE/WORD/DWORD types can be replaced with the appropriate u sizes. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/ttype.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/vt6656/ttype.h b/drivers/staging/vt6656/ttype.h index 0f70562c0563..dfbf74713a80 100644 --- a/drivers/staging/vt6656/ttype.h +++ b/drivers/staging/vt6656/ttype.h @@ -44,9 +44,9 @@ typedef int BOOL; /****** Simple typedefs ***************************************************/ -typedef unsigned char BYTE; // 8-bit -typedef unsigned short WORD; // 16-bit -typedef unsigned long DWORD; // 32-bit +typedef u8 BYTE; +typedef u16 WORD; +typedef u32 DWORD; // QWORD is for those situation that we want // an 8-byte-aligned 8 byte long structure @@ -62,8 +62,8 @@ typedef UQuadWord QWORD; // 64-bit /****** Common pointer types ***********************************************/ -typedef unsigned long ULONG_PTR; // 32-bit -typedef unsigned long DWORD_PTR; // 32-bit +typedef u32 ULONG_PTR; +typedef u32 DWORD_PTR; // boolean pointer -- GitLab From 4a3e24ba6b9f06ccfb1f583cad23dc6f508e1752 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 11 Nov 2012 15:45:52 +0000 Subject: [PATCH 1391/1799] staging: vt6656: 64 bit fixes: fix long warning messages. commit b4dc03af5513774277c9c36b12a25cd3f25f4404 upstream. Fixes long warning messages from patch [PATCH 08/14] staging: vt6656: 64 bit fixes : correct all type sizes Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/dpc.c | 4 +-- drivers/staging/vt6656/key.c | 47 ++++++++++++++++++++++++----------- drivers/staging/vt6656/mac.c | 6 +++-- drivers/staging/vt6656/rxtx.c | 18 +++++++++----- 4 files changed, 51 insertions(+), 24 deletions(-) diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 08021f4d5236..4664e9d81d04 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -1238,7 +1238,7 @@ static BOOL s_bHandleRxEncryption ( PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); if (byDecMode == KEY_CTL_TKIP) { *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); } else { @@ -1349,7 +1349,7 @@ static BOOL s_bHostWepRxEncryption ( PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); if (byDecMode == KEY_CTL_TKIP) { *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c index ee62a06a75f4..94b3e67658c5 100644 --- a/drivers/staging/vt6656/key.c +++ b/drivers/staging/vt6656/key.c @@ -235,7 +235,8 @@ BOOL KeybSetKey( PSKeyItem pKey; unsigned int uKeyIdx; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetKey: %lX\n", dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Enter KeybSetKey: %X\n", dwKeyIndex); j = (MAX_KEY_TABLE-1); for (i=0;i<(MAX_KEY_TABLE-1);i++) { @@ -261,7 +262,9 @@ BOOL KeybSetKey( if ((dwKeyIndex & TRANSMIT_KEY) != 0) { // Group transmit key pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Group transmit key(R)[%X]: %d\n", + pTable->KeyTable[i].dwGTKeyIndex, i); } pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4); @@ -302,9 +305,12 @@ BOOL KeybSetKey( } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", + pKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", + pKey->wTSC15_0); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", + pKey->dwKeyIndex); return (TRUE); } @@ -326,7 +332,9 @@ BOOL KeybSetKey( if ((dwKeyIndex & TRANSMIT_KEY) != 0) { // Group transmit key pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(N)[%lX]: %d\n", pTable->KeyTable[j].dwGTKeyIndex, j); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Group transmit key(N)[%X]: %d\n", + pTable->KeyTable[j].dwGTKeyIndex, j); } pTable->KeyTable[j].wKeyCtl &= 0xFF0F; // clear group key control filed pTable->KeyTable[j].wKeyCtl |= (byKeyDecMode << 4); @@ -367,9 +375,11 @@ BOOL KeybSetKey( } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", + pKey->dwTSC47_16); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", + pKey->dwKeyIndex); return (TRUE); } @@ -597,7 +607,8 @@ BOOL KeybGetTransmitKey(PSKeyManagement pTable, PBYTE pbyBSSID, DWORD dwKeyType, DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]); } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %lX\n", pTable->KeyTable[i].dwGTKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %X\n", + pTable->KeyTable[i].dwGTKeyIndex); return (TRUE); } @@ -696,7 +707,10 @@ BOOL KeybSetDefaultKey( if ((dwKeyIndex & TRANSMIT_KEY) != 0) { // Group transmit key pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, MAX_KEY_TABLE-1); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Group transmit key(R)[%X]: %d\n", + pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, + MAX_KEY_TABLE-1); } pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00; // clear all key control filed @@ -747,9 +761,11 @@ BOOL KeybSetDefaultKey( } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n", pKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n", + pKey->dwTSC47_16); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n", pKey->wTSC15_0); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n", pKey->dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n", + pKey->dwKeyIndex); return (TRUE); } @@ -787,7 +803,8 @@ BOOL KeybSetAllGroupKey( PSKeyItem pKey; unsigned int uKeyIdx; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %X\n", + dwKeyIndex); if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key @@ -804,7 +821,9 @@ BOOL KeybSetAllGroupKey( if ((dwKeyIndex & TRANSMIT_KEY) != 0) { // Group transmit key pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Group transmit key(R)[%X]: %d\n", + pTable->KeyTable[i].dwGTKeyIndex, i); } pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c index af4a29d14775..8fddc7b3930b 100644 --- a/drivers/staging/vt6656/mac.c +++ b/drivers/staging/vt6656/mac.c @@ -260,7 +260,8 @@ BYTE pbyData[24]; dwData1 <<= 16; dwData1 |= MAKEWORD(*(pbyAddr+4), *(pbyAddr+5)); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %lX, KeyCtl:%X\n", wOffset, dwData1, wKeyCtl); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %X,"\ + " KeyCtl:%X\n", wOffset, dwData1, wKeyCtl); //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); @@ -277,7 +278,8 @@ BYTE pbyData[24]; dwData2 <<= 8; dwData2 |= *(pbyAddr+0); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %lX\n", wOffset, dwData2); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %X\n", + wOffset, dwData2); //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index fe218689a0a4..3beb126e90f8 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -377,7 +377,8 @@ s_vFillTxKey ( *(pbyIVHead+3) = (BYTE)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV // Append IV&ExtIV after Mac Header *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %lx\n", *pdwExtIV); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %x\n", + *pdwExtIV); } else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { pTransmitKey->wTSC15_0++; @@ -1753,7 +1754,8 @@ s_bPacketToWirelessUsb( MIC_vAppend((PBYTE)&(psEthHeader->abyDstAddr[0]), 12); dwMIC_Priority = 0; MIC_vAppend((PBYTE)&dwMIC_Priority, 4); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %X, %X\n", + dwMICKey0, dwMICKey1); /////////////////////////////////////////////////////////////////// @@ -2635,7 +2637,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb) { MIC_vAppend((PBYTE)&(sEthHeader.abyDstAddr[0]), 12); dwMIC_Priority = 0; MIC_vAppend((PBYTE)&dwMIC_Priority, 4); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY:"\ + " %X, %X\n", dwMICKey0, dwMICKey1); uLength = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen; @@ -2655,7 +2658,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderSize, uPadding, cbIVlen); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%x, %x\n", + *pdwMIC_L, *pdwMIC_R); } @@ -3029,7 +3033,8 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"error: KEY is GTK!!~~\n"); } else { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n", + pTransmitKey->dwKeyIndex); bNeedEncryption = TRUE; } } @@ -3043,7 +3048,8 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) if (pDevice->bEnableHostWEP) { if ((uNodeIndex != 0) && (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n", + pTransmitKey->dwKeyIndex); bNeedEncryption = TRUE; } } -- GitLab From 82b2729dac2da860dd30d46753ac18ba7ad8888f Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 11 Nov 2012 15:49:59 +0000 Subject: [PATCH 1392/1799] staging: vt6656: 64bit fixes: key.c/h change unsigned long to u32 commit c0d05b305b00c698b0a8c1b3d46c9380bce9db45 upstream. Fixes long issues. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/key.c | 6 +++--- drivers/staging/vt6656/key.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c index 94b3e67658c5..ba3a561a79a2 100644 --- a/drivers/staging/vt6656/key.c +++ b/drivers/staging/vt6656/key.c @@ -223,7 +223,7 @@ BOOL KeybSetKey( PSKeyManagement pTable, PBYTE pbyBSSID, DWORD dwKeyIndex, - unsigned long uKeyLength, + u32 uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode @@ -675,7 +675,7 @@ BOOL KeybSetDefaultKey( void *pDeviceHandler, PSKeyManagement pTable, DWORD dwKeyIndex, - unsigned long uKeyLength, + u32 uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode @@ -791,7 +791,7 @@ BOOL KeybSetAllGroupKey( void *pDeviceHandler, PSKeyManagement pTable, DWORD dwKeyIndex, - unsigned long uKeyLength, + u32 uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h index f749c7a027d3..bd35d39621ae 100644 --- a/drivers/staging/vt6656/key.h +++ b/drivers/staging/vt6656/key.h @@ -58,7 +58,7 @@ typedef struct tagSKeyItem { BOOL bKeyValid; - unsigned long uKeyLength; + u32 uKeyLength; BYTE abyKey[MAX_KEY_LEN]; QWORD KeyRSC; DWORD dwTSC47_16; @@ -107,7 +107,7 @@ BOOL KeybSetKey( PSKeyManagement pTable, PBYTE pbyBSSID, DWORD dwKeyIndex, - unsigned long uKeyLength, + u32 uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode @@ -146,7 +146,7 @@ BOOL KeybSetDefaultKey( void *pDeviceHandler, PSKeyManagement pTable, DWORD dwKeyIndex, - unsigned long uKeyLength, + u32 uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode @@ -156,7 +156,7 @@ BOOL KeybSetAllGroupKey( void *pDeviceHandler, PSKeyManagement pTable, DWORD dwKeyIndex, - unsigned long uKeyLength, + u32 uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode -- GitLab From e239d2d4ea630ddec326a99252888b867d196f5b Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 11 Nov 2012 16:07:57 +0000 Subject: [PATCH 1393/1799] staging: vt6656: 64bit fixes: vCommandTimerWait change calculation of timer. commit 70e227790d4ee4590023d8041a3485f8053593fc upstream. The timer appears to run too fast/race on 64 bit systems. Using msecs_to_jiffies seems to cause a deadlock on 64 bit. A calculation of (MSecond * HZ) / 1000 appears to run satisfactory. Change BSSIDInfoCount to u32. After this patch the driver can be successfully connect on little endian 64/32 bit systems. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/wcmd.c | 20 +++++++++++--------- drivers/staging/vt6656/wpa2.h | 4 ++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 78ea121b7e2e..31fb96a54cff 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -316,17 +316,19 @@ s_MgrMakeProbeRequest( return pTxPacket; } -void vCommandTimerWait(void *hDeviceContext, unsigned int MSecond) +void vCommandTimerWait(void *hDeviceContext, unsigned long MSecond) { - PSDevice pDevice = (PSDevice)hDeviceContext; + PSDevice pDevice = (PSDevice)hDeviceContext; - init_timer(&pDevice->sTimerCommand); - pDevice->sTimerCommand.data = (unsigned long)pDevice; - pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; - // RUN_AT :1 msec ~= (HZ/1024) - pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10); - add_timer(&pDevice->sTimerCommand); - return; + init_timer(&pDevice->sTimerCommand); + + pDevice->sTimerCommand.data = (unsigned long)pDevice; + pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; + pDevice->sTimerCommand.expires = RUN_AT((MSecond * HZ) / 1000); + + add_timer(&pDevice->sTimerCommand); + + return; } void vRunCommand(void *hDeviceContext) diff --git a/drivers/staging/vt6656/wpa2.h b/drivers/staging/vt6656/wpa2.h index 46c295905b48..c359252a6b0e 100644 --- a/drivers/staging/vt6656/wpa2.h +++ b/drivers/staging/vt6656/wpa2.h @@ -45,8 +45,8 @@ typedef struct tagsPMKIDInfo { } PMKIDInfo, *PPMKIDInfo; typedef struct tagSPMKIDCache { - unsigned long BSSIDInfoCount; - PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE]; + u32 BSSIDInfoCount; + PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE]; } SPMKIDCache, *PSPMKIDCache; -- GitLab From fac3e9ef05d5ed0ab475bad3985ff017f5aa79be Mon Sep 17 00:00:00 2001 From: Chris Verges Date: Fri, 21 Dec 2012 01:58:34 -0800 Subject: [PATCH 1394/1799] hwmon: (lm73} Detect and report i2c bus errors commit 0602934f302e016e2ea5dc6951681bfac77455ef upstream. If an LM73 device does not exist on an I2C bus, attempts to communicate with the device result in an error code returned from the i2c read/write functions. The current lm73 driver casts that return value from a s32 type to a s16 type, then converts it to a temperature in celsius. Because negative temperatures are valid, it is difficult to distinguish between an error code printed to the response buffer and a negative temperature recorded by the sensor. The solution is to evaluate the return value from the i2c functions before performing any temperature calculations. If the i2c function did not succeed, the error code should be passed back through the virtual file system layer instead of being printed into the response buffer. Before: $ cat /sys/class/hwmon/hwmon0/device/temp1_input -46 After: $ cat /sys/class/hwmon/hwmon0/device/temp1_input cat: read error: No such device or address Signed-off-by: Chris Verges Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/lm73.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c index 8fa2632cbbaf..7272176a9ec7 100644 --- a/drivers/hwmon/lm73.c +++ b/drivers/hwmon/lm73.c @@ -49,6 +49,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, struct i2c_client *client = to_i2c_client(dev); long temp; short value; + s32 err; int status = kstrtol(buf, 10, &temp); if (status < 0) @@ -57,8 +58,8 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, /* Write value */ value = (short) SENSORS_LIMIT(temp/250, (LM73_TEMP_MIN*4), (LM73_TEMP_MAX*4)) << 5; - i2c_smbus_write_word_swapped(client, attr->index, value); - return count; + err = i2c_smbus_write_word_swapped(client, attr->index, value); + return (err < 0) ? err : count; } static ssize_t show_temp(struct device *dev, struct device_attribute *da, @@ -66,11 +67,16 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da, { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct i2c_client *client = to_i2c_client(dev); + int temp; + + s32 err = i2c_smbus_read_word_swapped(client, attr->index); + if (err < 0) + return err; + /* use integer division instead of equivalent right shift to guarantee arithmetic shift and preserve the sign */ - int temp = ((s16) (i2c_smbus_read_word_swapped(client, - attr->index))*250) / 32; - return sprintf(buf, "%d\n", temp); + temp = (((s16) err) * 250) / 32; + return scnprintf(buf, PAGE_SIZE, "%d\n", temp); } -- GitLab From e80bd5af8e6dc699516696be47bd63b529acc268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Thu, 22 Nov 2012 13:49:14 +0100 Subject: [PATCH 1395/1799] video: mxsfb: fix crash when unblanking the display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 6c1ecba8d84841277d68140ef485335d5be28485 upstream. The VDCTRL4 register does not provide the MXS SET/CLR/TOGGLE feature. The write in mxsfb_disable_controller() sets the data_cnt for the LCD DMA to 0 which obviously means the max. count for the LCD DMA and leads to overwriting arbitrary memory when the display is unblanked. Signed-off-by: Lothar Waßmann Acked-by: Juergen Beisert Tested-by: Lauri Hintsala Signed-off-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- drivers/video/mxsfb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 4a89f889852d..9f8999223f60 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -366,7 +366,8 @@ static void mxsfb_disable_controller(struct fb_info *fb_info) loop--; } - writel(VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4 + REG_CLR); + reg = readl(host->base + LCDC_VDCTRL4); + writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4); clk_disable_unprepare(host->clk); -- GitLab From 2c3a3718da77839d08925a4705802f045faaea06 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Wed, 5 Dec 2012 16:08:33 -0600 Subject: [PATCH 1396/1799] samsung-laptop: Add quirk for broken acpi_video backlight on N250P commit e04c200f1f2de8eaa2f5af6d97e7e213a1abb424 upstream. BugLink: http://bugs.launchpad.net/bugs/1086921 Signed-off-by: Seth Forshee Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/samsung-laptop.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index e2a34b42ddc1..1afbe5e0a348 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -1506,6 +1506,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { }, .driver_data = &samsung_broken_acpi_video, }, + { + .callback = samsung_dmi_matched, + .ident = "N250P", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "N250P"), + DMI_MATCH(DMI_BOARD_NAME, "N250P"), + }, + .driver_data = &samsung_broken_acpi_video, + }, { }, }; MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); -- GitLab From cb832988d64ff38921359cce89093abc60f299b5 Mon Sep 17 00:00:00 2001 From: Forrest Liu Date: Mon, 17 Dec 2012 09:55:39 -0500 Subject: [PATCH 1397/1799] ext4: fix extent tree corruption caused by hole punch commit c36575e663e302dbaa4d16b9c72d2c9a913a9aef upstream. When depth of extent tree is greater than 1, logical start value of interior node is not correctly updated in ext4_ext_rm_idx. Signed-off-by: Forrest Liu Signed-off-by: "Theodore Ts'o" Reviewed-by: Ashish Sangwan Signed-off-by: Greg Kroah-Hartman --- fs/ext4/extents.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index c21598542585..852d4c257ace 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2110,13 +2110,14 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block, * removes index from the index block. */ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, - struct ext4_ext_path *path) + struct ext4_ext_path *path, int depth) { int err; ext4_fsblk_t leaf; /* free index block */ - path--; + depth--; + path = path + depth; leaf = ext4_idx_pblock(path->p_idx); if (unlikely(path->p_hdr->eh_entries == 0)) { EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0"); @@ -2141,6 +2142,19 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, ext4_free_blocks(handle, inode, NULL, leaf, 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); + + while (--depth >= 0) { + if (path->p_idx != EXT_FIRST_INDEX(path->p_hdr)) + break; + path--; + err = ext4_ext_get_access(handle, inode, path); + if (err) + break; + path->p_idx->ei_block = (path+1)->p_idx->ei_block; + err = ext4_ext_dirty(handle, inode, path); + if (err) + break; + } return err; } @@ -2474,7 +2488,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, /* if this leaf is free, then we should * remove it from index block above */ if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL) - err = ext4_ext_rm_idx(handle, inode, path + depth); + err = ext4_ext_rm_idx(handle, inode, path, depth); out: return err; @@ -2675,7 +2689,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, /* index is empty, remove it; * handle must be already prepared by the * truncatei_leaf() */ - err = ext4_ext_rm_idx(handle, inode, path + i); + err = ext4_ext_rm_idx(handle, inode, path, i); } /* root level has p_bh == NULL, brelse() eats this */ brelse(path[i].p_bh); -- GitLab From e307ec213a97ddc33ac6921ba37246548245d027 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 20 Dec 2012 00:07:18 -0500 Subject: [PATCH 1398/1799] ext4: check dioread_nolock on remount commit 261cb20cb2f0737a247aaf08dff7eb065e3e5b66 upstream. Currently we allow enabling dioread_nolock mount option on remount for filesystems where blocksize < PAGE_CACHE_SIZE. This isn't really supported so fix the bug by moving the check for blocksize != PAGE_CACHE_SIZE into parse_options(). Change the original PAGE_SIZE to PAGE_CACHE_SIZE along the way because that's what we are really interested in. Signed-off-by: Jan Kara Signed-off-by: "Theodore Ts'o" Reviewed-by: Eric Sandeen Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index b1c28f18701c..9e4177d6905e 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1599,9 +1599,7 @@ static int parse_options(char *options, struct super_block *sb, unsigned int *journal_ioprio, int is_remount) { -#ifdef CONFIG_QUOTA struct ext4_sb_info *sbi = EXT4_SB(sb); -#endif char *p; substring_t args[MAX_OPT_ARGS]; int token; @@ -1650,6 +1648,16 @@ static int parse_options(char *options, struct super_block *sb, } } #endif + if (test_opt(sb, DIOREAD_NOLOCK)) { + int blocksize = + BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size); + + if (blocksize < PAGE_CACHE_SIZE) { + ext4_msg(sb, KERN_ERR, "can't mount with " + "dioread_nolock if block size != PAGE_SIZE"); + return 0; + } + } return 1; } @@ -3226,15 +3234,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) clear_opt(sb, DELALLOC); } - blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); - if (test_opt(sb, DIOREAD_NOLOCK)) { - if (blocksize < PAGE_SIZE) { - ext4_msg(sb, KERN_ERR, "can't mount with " - "dioread_nolock if block size != PAGE_SIZE"); - goto failed_mount; - } - } - sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); @@ -3276,6 +3275,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY))) goto failed_mount; + blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); if (blocksize < EXT4_MIN_BLOCK_SIZE || blocksize > EXT4_MAX_BLOCK_SIZE) { ext4_msg(sb, KERN_ERR, -- GitLab From b5f0e251211531180989a32ba598968104562c84 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 21 Dec 2012 00:15:51 -0500 Subject: [PATCH 1399/1799] jbd2: fix assertion failure in jbd2_journal_flush() commit d7961c7fa4d2e3c3f12be67e21ba8799b5a7238a upstream. The following race is possible between start_this_handle() and someone calling jbd2_journal_flush(). Process A Process B start_this_handle(). if (journal->j_barrier_count) # false if (!journal->j_running_transaction) { #true read_unlock(&journal->j_state_lock); jbd2_journal_lock_updates() jbd2_journal_flush() write_lock(&journal->j_state_lock); if (journal->j_running_transaction) { # false ... wait for committing trans ... write_unlock(&journal->j_state_lock); ... write_lock(&journal->j_state_lock); if (!journal->j_running_transaction) { # true jbd2_get_transaction(journal, new_transaction); write_unlock(&journal->j_state_lock); goto repeat; # eventually blocks on j_barrier_count > 0 ... J_ASSERT(!journal->j_running_transaction); # fails We fix the race by rechecking j_barrier_count after reacquiring j_state_lock in exclusive mode. Reported-by: yjwsignal@empal.com Signed-off-by: Jan Kara Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/jbd2/transaction.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index ddcd3549c6c2..de8b4cb7c31e 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -209,7 +209,8 @@ static int start_this_handle(journal_t *journal, handle_t *handle, if (!new_transaction) goto alloc_transaction; write_lock(&journal->j_state_lock); - if (!journal->j_running_transaction) { + if (!journal->j_running_transaction && + !journal->j_barrier_count) { jbd2_get_transaction(journal, new_transaction); new_transaction = NULL; } -- GitLab From bd06aeb0ff9b22598851276403a1e90f0b4c2d38 Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Tue, 25 Dec 2012 14:08:16 -0500 Subject: [PATCH 1400/1799] ext4: do not try to write superblock on ro remount w/o journal commit d096ad0f79a782935d2e06ae8fb235e8c5397775 upstream. When a journal-less ext4 filesystem is mounted on a read-only block device (blockdev --setro will do), each remount (for other, unrelated, flags, like suid=>nosuid etc) results in a series of scary messages from kernel telling about I/O errors on the device. This is becauese of the following code ext4_remount(): if (sbi->s_journal == NULL) ext4_commit_super(sb, 1); at the end of remount procedure, which forces writing (flushing) of a superblock regardless whenever it is dirty or not, if the filesystem is readonly or not, and whenever the device itself is readonly or not. We only need call ext4_commit_super when the file system had been previously mounted read/write. Thanks to Eric Sandeen for help in diagnosing this issue. Signed-off-By: Michael Tokarev Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 9e4177d6905e..889577332bae 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -4506,7 +4506,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) } ext4_setup_system_zone(sb); - if (sbi->s_journal == NULL) + if (sbi->s_journal == NULL && !(old_sb_flags & MS_RDONLY)) ext4_commit_super(sb, 1); #ifdef CONFIG_QUOTA -- GitLab From ed8e1a67302762d7a1e56e52ea00dc4a36c6cbf5 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 27 Dec 2012 01:42:48 -0500 Subject: [PATCH 1401/1799] ext4: lock i_mutex when truncating orphan inodes commit 721e3eba21e43532e438652dd8f1fcdfce3187e7 upstream. Commit c278531d39 added a warning when ext4_flush_unwritten_io() is called without i_mutex being taken. It had previously not been taken during orphan cleanup since races weren't possible at that point in the mount process, but as a result of this c278531d39, we will now see a kernel WARN_ON in this case. Take the i_mutex in ext4_orphan_cleanup() to suppress this warning. Reported-by: Alexander Beregalov Signed-off-by: "Theodore Ts'o" Reviewed-by: Zheng Liu Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 889577332bae..288f4c61e975 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -2120,7 +2120,9 @@ static void ext4_orphan_cleanup(struct super_block *sb, __func__, inode->i_ino, inode->i_size); jbd_debug(2, "truncating inode %lu to %lld bytes\n", inode->i_ino, inode->i_size); + mutex_lock(&inode->i_mutex); ext4_truncate(inode); + mutex_unlock(&inode->i_mutex); nr_truncates++; } else { ext4_msg(sb, KERN_DEBUG, -- GitLab From a0e0e463b14280c8b5cb26114ac321d69c6f2aa5 Mon Sep 17 00:00:00 2001 From: Ed Cashin Date: Sat, 12 Jan 2013 06:43:35 -0500 Subject: [PATCH 1402/1799] aoe: do not call bdi_init after blk_alloc_queue commit 0a41409c518083133e79015092585d68915865be upstream, but doesn't apply, so this version is different for older kernels than 3.7.x blk_alloc_queue has already done a bdi_init, so do not bdi_init again in aoeblk_gdalloc. The extra call causes list corruption in the per-CPU backing dev info stats lists. Affected users see console WARNINGs about list_del corruption on percpu_counter_destroy when doing "rmmod aoe" or "aoeflush -a" when AoE targets have been detected and initialized by the system. The patch below applies to v3.6.11, with its v47 aoe driver. It is expected to apply to all currently maintained stable kernels except 3.7.y. A related but different fix has been posted for 3.7.y. References: RedHat bugzilla ticket with original report https://bugzilla.redhat.com/show_bug.cgi?id=853064 LKML discussion of bug and fix http://thread.gmane.org/gmane.linux.kernel/1416336/focus=1416497 Reported-by: Josh Boyer Signed-off-by: Ed Cashin Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoe.h | 2 +- drivers/block/aoe/aoeblk.c | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index db195abad698..e49ddd0aea12 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -1,5 +1,5 @@ /* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ -#define VERSION "47" +#define VERSION "47q" #define AOE_MAJOR 152 #define DEVICE_NAME "aoe" diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 321de7b6c442..7eca46349c4c 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -276,8 +276,6 @@ aoeblk_gdalloc(void *vp) goto err_mempool; blk_queue_make_request(d->blkq, aoeblk_make_request); d->blkq->backing_dev_info.name = "aoe"; - if (bdi_init(&d->blkq->backing_dev_info)) - goto err_blkq; spin_lock_irqsave(&d->lock, flags); gd->major = AOE_MAJOR; gd->first_minor = d->sysminor * AOE_PARTITIONS; @@ -298,9 +296,6 @@ aoeblk_gdalloc(void *vp) aoedisk_add_sysfs(d); return; -err_blkq: - blk_cleanup_queue(d->blkq); - d->blkq = NULL; err_mempool: mempool_destroy(d->bufpool); err_disk: -- GitLab From 8d00c77065819b747c6fc0b56234afea72f17332 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 10 Oct 2012 00:08:56 +0900 Subject: [PATCH 1403/1799] udf: fix memory leak while allocating blocks during write commit 2fb7d99d0de3fd8ae869f35ab682581d8455887a upstream. Need to brelse the buffer_head stored in cur_epos and next_epos. Signed-off-by: Namjae Jeon Signed-off-by: Ashish Sangwan Signed-off-by: Jan Kara Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- fs/udf/inode.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 7d7528008359..ad68793e46bc 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -738,6 +738,8 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, goal, err); if (!newblocknum) { brelse(prev_epos.bh); + brelse(cur_epos.bh); + brelse(next_epos.bh); *err = -ENOSPC; return 0; } @@ -768,6 +770,8 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, udf_update_extents(inode, laarr, startnum, endnum, &prev_epos); brelse(prev_epos.bh); + brelse(cur_epos.bh); + brelse(next_epos.bh); newblock = udf_get_pblock(inode->i_sb, newblocknum, iinfo->i_location.partitionReferenceNum, 0); -- GitLab From 4faf067ae71be3d652e09c3119ce8125498cdf64 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 10 Oct 2012 00:09:12 +0900 Subject: [PATCH 1404/1799] udf: don't increment lenExtents while writing to a hole commit fb719c59bdb4fca86ee1fd1f42ab3735ca12b6b2 upstream. Incrementing lenExtents even while writing to a hole is bad for performance as calls to udf_discard_prealloc and udf_truncate_tail_extent would not return from start if isize != lenExtents Signed-off-by: Namjae Jeon Signed-off-by: Ashish Sangwan Signed-off-by: Jan Kara Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- fs/udf/inode.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index ad68793e46bc..aa70035fb402 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -574,6 +574,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, struct udf_inode_info *iinfo = UDF_I(inode); int goal = 0, pgoal = iinfo->i_location.logicalBlockNum; int lastblock = 0; + bool isBeyondEOF; *err = 0; *new = 0; @@ -653,7 +654,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, /* Are we beyond EOF? */ if (etype == -1) { int ret; - + isBeyondEOF = 1; if (count) { if (c) laarr[0] = laarr[1]; @@ -696,6 +697,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, endnum = c + 1; lastblock = 1; } else { + isBeyondEOF = 0; endnum = startnum = ((count > 2) ? 2 : count); /* if the current extent is in position 0, @@ -743,7 +745,8 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, *err = -ENOSPC; return 0; } - iinfo->i_lenExtents += inode->i_sb->s_blocksize; + if (isBeyondEOF) + iinfo->i_lenExtents += inode->i_sb->s_blocksize; } /* if the extent the requsted block is located in contains multiple -- GitLab From 9035b20988416173a48ad2f00190846faf15ccb7 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 29 May 2012 15:06:23 -0700 Subject: [PATCH 1405/1799] thp, memcg: split hugepage for memcg oom on cow commit 1f1d06c34f7675026326cd9f39ff91e4555cf355 upstream. On COW, a new hugepage is allocated and charged to the memcg. If the system is oom or the charge to the memcg fails, however, the fault handler will return VM_FAULT_OOM which results in an oom kill. Instead, it's possible to fallback to splitting the hugepage so that the COW results only in an order-0 page being allocated and charged to the memcg which has a higher liklihood to succeed. This is expensive because the hugepage must be split in the page fault handler, but it is much better than unnecessarily oom killing a process. Signed-off-by: David Rientjes Cc: Andrea Arcangeli Cc: Johannes Weiner Acked-by: KAMEZAWA Hiroyuki Cc: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/huge_memory.c | 3 +++ mm/memory.c | 18 +++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index f0e5306eeb55..caf15b6fa753 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -950,6 +950,8 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, count_vm_event(THP_FAULT_FALLBACK); ret = do_huge_pmd_wp_page_fallback(mm, vma, address, pmd, orig_pmd, page, haddr); + if (ret & VM_FAULT_OOM) + split_huge_page(page); put_page(page); goto out; } @@ -957,6 +959,7 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) { put_page(new_page); + split_huge_page(page); put_page(page); ret |= VM_FAULT_OOM; goto out; diff --git a/mm/memory.c b/mm/memory.c index 024b4afc41fc..2f42aab50e9b 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3494,6 +3494,7 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, if (unlikely(is_vm_hugetlb_page(vma))) return hugetlb_fault(mm, vma, address, flags); +retry: pgd = pgd_offset(mm, address); pud = pud_alloc(mm, pgd, address); if (!pud) @@ -3507,13 +3508,24 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, pmd, flags); } else { pmd_t orig_pmd = *pmd; + int ret; + barrier(); if (pmd_trans_huge(orig_pmd)) { if (flags & FAULT_FLAG_WRITE && !pmd_write(orig_pmd) && - !pmd_trans_splitting(orig_pmd)) - return do_huge_pmd_wp_page(mm, vma, address, - pmd, orig_pmd); + !pmd_trans_splitting(orig_pmd)) { + ret = do_huge_pmd_wp_page(mm, vma, address, pmd, + orig_pmd); + /* + * If COW results in an oom, the huge pmd will + * have been split, so retry the fault on the + * pte for a smaller charge. + */ + if (unlikely(ret & VM_FAULT_OOM)) + goto retry; + return ret; + } return 0; } } -- GitLab From a0f8b51494051c7bf5d994ac33d2b8ce7c0d5867 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 31 Oct 2012 17:20:50 +0100 Subject: [PATCH 1406/1799] x86, amd: Disable way access filter on Piledriver CPUs commit 2bbf0a1427c377350f001fbc6260995334739ad7 upstream. The Way Access Filter in recent AMD CPUs may hurt the performance of some workloads, caused by aliasing issues in the L1 cache. This patch disables it on the affected CPUs. The issue is similar to that one of last year: http://lkml.indiana.edu/hypermail/linux/kernel/1107.3/00041.html This new patch does not replace the old one, we just need another quirk for newer CPUs. The performance penalty without the patch depends on the circumstances, but is a bit less than the last year's 3%. The workloads affected would be those that access code from the same physical page under different virtual addresses, so different processes using the same libraries with ASLR or multiple instances of PIE-binaries. The code needs to be accessed simultaneously from both cores of the same compute unit. More details can be found here: http://developer.amd.com/Assets/SharedL1InstructionCacheonAMD15hCPU.pdf CPUs affected are anything with the core known as Piledriver. That includes the new parts of the AMD A-Series (aka Trinity) and the just released new CPUs of the FX-Series (aka Vishera). The model numbering is a bit odd here: FX CPUs have model 2, A-Series has model 10h, with possible extensions to 1Fh. Hence the range of model ids. Signed-off-by: Andre Przywara Link: http://lkml.kernel.org/r/1351700450-9277-1-git-send-email-osp@andrep.de Signed-off-by: H. Peter Anvin Signed-off-by: CAI Qian Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/amd.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 6b4976b0cbb2..a9c8a46dd7d3 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -612,6 +612,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) } } + /* + * The way access filter has a performance penalty on some workloads. + * Disable it on the affected CPUs. + */ + if ((c->x86 == 0x15) && + (c->x86_model >= 0x02) && (c->x86_model < 0x20)) { + u64 val; + + if (!rdmsrl_safe(0xc0011021, &val) && !(val & 0x1E)) { + val |= 0x1E; + checking_wrmsrl(0xc0011021, val); + } + } + cpu_detect_cache_sizes(c); /* Multi core CPU? */ -- GitLab From dc4a02c677c9667dcd7d118cee09a99ede9c64f4 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 4 Dec 2012 23:23:16 +0100 Subject: [PATCH 1407/1799] ACPI : do not use Lid and Sleep button for S5 wakeup commit b7e383046c2c7c13ad928cd7407eafff758ddd4b upstream. When system enters power off, the _PSW of Lid device is enabled. But this may cause the system to reboot instead of power off. A proper way to fix this is to always disable lid wakeup capability for S5. References: https://bugzilla.kernel.org/show_bug.cgi?id=35262 Signed-off-by: Zhang Rui Signed-off-by: Rafael J. Wysocki Cc: Joseph Salisbury Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/scan.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index bd3199ce5b27..619a2e4402df 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -789,8 +789,8 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, static void acpi_bus_set_run_wake_flags(struct acpi_device *device) { struct acpi_device_id button_device_ids[] = { - {"PNP0C0D", 0}, {"PNP0C0C", 0}, + {"PNP0C0D", 0}, {"PNP0C0E", 0}, {"", 0}, }; @@ -802,6 +802,11 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) /* Power button, Lid switch always enable wakeup */ if (!acpi_match_device_ids(device, button_device_ids)) { device->wakeup.flags.run_wake = 1; + if (!acpi_match_device_ids(device, &button_device_ids[1])) { + /* Do not use Lid/sleep button for S5 wakeup */ + if (device->wakeup.sleep_state == ACPI_STATE_S5) + device->wakeup.sleep_state = ACPI_STATE_S4; + } device_set_wakeup_capable(&device->dev, true); return; } -- GitLab From ba1de754297ed6756f0a6281f3e41a0ef9ff0d77 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Dec 2012 01:14:11 +0900 Subject: [PATCH 1408/1799] regmap: debugfs: Avoid overflows for very small reads commit db04328c167ff8e7c57f4a3532214aeada3a82fd upstream. If count is less than the size of a register then we may hit integer wraparound when trying to move backwards to check if we're still in the buffer. Instead move the position forwards to check if it's still in the buffer, we are unlikely to be able to allocate a buffer sufficiently big to overflow here. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/base/regmap/regmap-debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 251eb70f83e7..8ab1eab90be7 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -90,7 +90,7 @@ static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf, /* If we're in the region the user is trying to read */ if (p >= *ppos) { /* ...but not beyond it */ - if (buf_pos >= count - 1 - tot_len) + if (buf_pos + 1 + tot_len >= count) break; /* Format the register */ -- GitLab From cbedcb6121561ec79d4cda359e834ca6229786a8 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 1 Jan 2013 21:20:27 +0000 Subject: [PATCH 1409/1799] epoll: prevent missed events on EPOLL_CTL_MOD commit 128dd1759d96ad36c379240f8b9463e8acfd37a1 upstream. EPOLL_CTL_MOD sets the interest mask before calling f_op->poll() to ensure events are not missed. Since the modifications to the interest mask are not protected by the same lock as ep_poll_callback, we need to ensure the change is visible to other CPUs calling ep_poll_callback. We also need to ensure f_op->poll() has an up-to-date view of past events which occured before we modified the interest mask. So this barrier also pairs with the barrier in wq_has_sleeper(). This should guarantee either ep_poll_callback or f_op->poll() (or both) will notice the readiness of a recently-ready/modified item. This issue was encountered by Andreas Voellmy and Junchang(Jason) Wang in: http://thread.gmane.org/gmane.linux.kernel/1408782/ Signed-off-by: Eric Wong Cc: Hans Verkuil Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Al Viro Cc: Davide Libenzi Cc: Hans de Goede Cc: Mauro Carvalho Chehab Cc: David Miller Cc: Eric Dumazet Cc: Andrew Morton Cc: Andreas Voellmy Tested-by: "Junchang(Jason) Wang" Cc: netdev@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/eventpoll.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index c0b3c70ee87a..33c9599c14e7 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1226,10 +1226,30 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even * otherwise we might miss an event that happens between the * f_op->poll() call and the new event set registering. */ - epi->event.events = event->events; + epi->event.events = event->events; /* need barrier below */ pt._key = event->events; epi->event.data = event->data; /* protected by mtx */ + /* + * The following barrier has two effects: + * + * 1) Flush epi changes above to other CPUs. This ensures + * we do not miss events from ep_poll_callback if an + * event occurs immediately after we call f_op->poll(). + * We need this because we did not take ep->lock while + * changing epi above (but ep_poll_callback does take + * ep->lock). + * + * 2) We also need to ensure we do not miss _past_ events + * when calling f_op->poll(). This barrier also + * pairs with the barrier in wq_has_sleeper (see + * comments for wq_has_sleeper). + * + * This barrier will now guarantee ep_poll_callback or f_op->poll + * (or both) will notice the readiness of an item. + */ + smp_mb(); + /* * Get current event bits. We can safely use the file* here because * its usage count has been increased by the caller of this function. -- GitLab From 48f678d27107d31f2ec9ac9c6230883dfaebccb1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 24 Nov 2012 06:15:57 +0100 Subject: [PATCH 1410/1799] HID: add quirk for Freescale i.MX23 ROM recovery commit 436136cec650d661eb662fcb508a99878606d050 upstream. The USB recovery mode present in i.MX23 ROM emulates USB HID. It needs this quirk to behave properly. Even if the official branding of the chip is Freescale i.MX23, I named it Sigmatel STMP3780 since that's what the chip really is and it even reports itself as STMP3780. Signed-off-by: Marek Vasut Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-ids.h | 3 +++ drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 41ad6ff548ce..55838995eca3 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -664,6 +664,9 @@ #define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002 +#define USB_VENDOR_ID_SIGMATEL 0x066F +#define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780 + #define USB_VENDOR_ID_SKYCABLE 0x1223 #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index dc9697c2764f..9fea98f7c374 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -78,6 +78,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, -- GitLab From 4548554e7ca5192d5905a11219afb7de439b17d8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 4 Jan 2013 21:18:12 +0000 Subject: [PATCH 1411/1799] ASoC: wm2000: Fix sense of speech clarity enable commit 267f8fa2e1eef0612b2007e1f1846bcbc35cc1fa upstream. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm2000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index ae6f26f25a67..bb9f07037485 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -190,9 +190,9 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY); if (wm2000->speech_clarity) - ret &= ~WM2000_SPEECH_CLARITY; - else ret |= WM2000_SPEECH_CLARITY; + else + ret &= ~WM2000_SPEECH_CLARITY; wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret); wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33); -- GitLab From bc85643d2ff065c0303a1a0edfd748da4805295e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 21 Dec 2012 16:28:37 +0800 Subject: [PATCH 1412/1799] ASoC: wm2200: Fix setting dai format in wm2200_set_fmt commit 2a5f431592343b78896013b055582f94c12a5049 upstream. According to the defines in wm2200.h: /* * R1284 (0x504) - Audio IF 1_5 */ We should not left shift 1 bit for fmt_val when setting dai format. Signed-off-by: Axel Lin Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index c8bff6da5320..201fc5832171 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1440,7 +1440,7 @@ static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV, lrclk); snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5, - WM2200_AIF1_FMT_MASK << 1, fmt_val << 1); + WM2200_AIF1_FMT_MASK, fmt_val); return 0; } -- GitLab From 6d445a511e85a702a63197a2034c21c1461a1212 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 4 Jan 2013 10:48:10 +0000 Subject: [PATCH 1413/1799] ASoC: wm2200: Remove DSP B and left justified AIF modes commit 0cc411b934c4317b363d1af993549f391852b980 upstream. These are not supported. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm2200.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 201fc5832171..86b84a18ba26 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1380,15 +1380,9 @@ static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_A: fmt_val = 0; break; - case SND_SOC_DAIFMT_DSP_B: - fmt_val = 1; - break; case SND_SOC_DAIFMT_I2S: fmt_val = 2; break; - case SND_SOC_DAIFMT_LEFT_J: - fmt_val = 3; - break; default: dev_err(codec->dev, "Unsupported DAI format %d\n", fmt & SND_SOC_DAIFMT_FORMAT_MASK); -- GitLab From d6ec6c9385c874cc8bdeba4346cf6275a6c811ca Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 4 Jan 2013 21:06:08 +0000 Subject: [PATCH 1414/1799] ASoC: wm5100: Remove DSP B and left justified formats commit 5f960294e2031d12f10c8488c3446fecbf59628d upstream. These are not supported Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm5100.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index b9c185ce64e4..a8d03ab5ea2e 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -1296,15 +1296,9 @@ static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_A: mask = 0; break; - case SND_SOC_DAIFMT_DSP_B: - mask = 1; - break; case SND_SOC_DAIFMT_I2S: mask = 2; break; - case SND_SOC_DAIFMT_LEFT_J: - mask = 3; - break; default: dev_err(codec->dev, "Unsupported DAI format %d\n", fmt & SND_SOC_DAIFMT_FORMAT_MASK); -- GitLab From c876baa8a8eda4a9ffcc6bdc144bb9d0fc3397a0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 11 Jan 2013 12:08:56 +0100 Subject: [PATCH 1415/1799] udldrmfb: Fix EDID not working with monitors with EDID extension blocks commit c930812fe5ebe725760422c9c351d1f6fde1502d upstream. udldrmfb only reads the main EDID block, and if that advertises extensions the drm_edid code expects them to be present, and starts reading beyond the buffer udldrmfb passes it. Although it may be possible to read more EDID info with the udl we simpy don't know how, and even if trial and error gets it working on one device, that is no guarantee it will work on other revisions. So this patch does a simple fix in the form of patching the EDID info to report 0 extension blocks, this fixes udldrmfb only doing 1024x768 on monitors with EDID extension blocks. Signed-off-by: Hans de Goede Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/udl/udl_connector.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index 8d9dc44f1f94..1230bc0ffb0d 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -59,6 +59,14 @@ static int udl_get_modes(struct drm_connector *connector) connector->display_info.raw_edid = (char *)edid; + /* + * We only read the main block, but if the monitor reports extension + * blocks then the drm edid code expects them to be present, so patch + * the extension count to 0. + */ + edid->checksum += edid->extensions; + edid->extensions = 0; + drm_mode_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); connector->display_info.raw_edid = NULL; -- GitLab From b756902ec26992d285937d1b706fc50c9743903d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 11 Jan 2013 12:08:57 +0100 Subject: [PATCH 1416/1799] udldrmfb: udl_get_edid: usb_control_msg buffer must not be on the stack commit 242187b362555849e8c971dfbbfd55f8bd9fa717 upstream. The buffer passed to usb_control_msg may end up in scatter-gather list, and may thus not be on the stack. Having it on the stack usually works on x86, but not on other archs. Signed-off-by: Hans de Goede Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/udl/udl_connector.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index 1230bc0ffb0d..b7780dd91320 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -22,13 +22,17 @@ static u8 *udl_get_edid(struct udl_device *udl) { u8 *block; - char rbuf[3]; + char *rbuf; int ret, i; block = kmalloc(EDID_LENGTH, GFP_KERNEL); if (block == NULL) return NULL; + rbuf = kmalloc(2, GFP_KERNEL); + if (rbuf == NULL) + goto error; + for (i = 0; i < EDID_LENGTH; i++) { ret = usb_control_msg(udl->ddev->usbdev, usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), @@ -42,10 +46,12 @@ static u8 *udl_get_edid(struct udl_device *udl) block[i] = rbuf[1]; } + kfree(rbuf); return block; error: kfree(block); + kfree(rbuf); return NULL; } -- GitLab From f9df20c6468862772f8f63b72b021f62a492548f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 11 Jan 2013 12:08:58 +0100 Subject: [PATCH 1417/1799] udldrmfb: udl_get_edid: drop unneeded i-- commit 7b4cf994e4c6ba48872bb25253cc393b7fb74c82 upstream. This is a left-over from when udl_get_edid returned the amount of bytes successfully read, which it no longer does. Signed-off-by: Hans de Goede Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/udl/udl_connector.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index b7780dd91320..32342247d91b 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -40,7 +40,6 @@ static u8 *udl_get_edid(struct udl_device *udl) HZ); if (ret < 1) { DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); - i--; goto error; } block[i] = rbuf[1]; -- GitLab From b66c35dd91a7476f42134fb44250d24f68181c7b Mon Sep 17 00:00:00 2001 From: Mike Dunn Date: Mon, 7 Jan 2013 13:55:12 -0800 Subject: [PATCH 1418/1799] ALSA: pxa27x: fix ac97 cold reset commit 41b645c8624df6ace020a8863ad1449d69140f7d upstream. Cold reset on the pxa27x currently fails and pxa2xx_ac97_try_cold_reset: cold reset timeout (GSR=0x44) appears in the kernel log. Through trial-and-error (the pxa270 developer's manual is mostly incoherent on the topic of ac97 reset), I got cold reset to complete by setting the WARM_RST bit in the GCR register (and later noticed that pxa3xx does this for cold reset as well). Also, a timeout loop is needed to wait for the reset to complete. Tested on a palm treo 680 machine. Signed-off-by: Mike Dunn Acked-by: Igor Grinberg Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/arm/pxa2xx-ac97-lib.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 48d7c0aa5073..8cfb2c0efcb2 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -148,6 +148,8 @@ static inline void pxa_ac97_warm_pxa27x(void) static inline void pxa_ac97_cold_pxa27x(void) { + unsigned int timeout; + GCR &= GCR_COLD_RST; /* clear everything but nCRST */ GCR &= ~GCR_COLD_RST; /* then assert nCRST */ @@ -157,8 +159,10 @@ static inline void pxa_ac97_cold_pxa27x(void) clk_enable(ac97conf_clk); udelay(5); clk_disable(ac97conf_clk); - GCR = GCR_COLD_RST; - udelay(50); + GCR = GCR_COLD_RST | GCR_WARM_RST; + timeout = 100; /* wait for the codec-ready bit to be set */ + while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) + mdelay(1); } #endif -- GitLab From 1d757c9abbfb218c89d6b0586ff89b4032a3601d Mon Sep 17 00:00:00 2001 From: Mike Dunn Date: Mon, 7 Jan 2013 13:55:13 -0800 Subject: [PATCH 1419/1799] ALSA: pxa27x: fix ac97 warm reset commit 3b4bc7bccc7857274705b05cf81a0c72cfd0b0dd upstream. This patch fixes some code that implements a work-around to a hardware bug in the ac97 controller on the pxa27x. A bug in the controller's warm reset functionality requires that the mfp used by the controller as the AC97_nRESET line be temporarily reconfigured as a generic output gpio (AF0) and manually held high for the duration of the warm reset cycle. This is what was done in the original code, but it was broken long ago by commit fb1bf8cd ([ARM] pxa: introduce processor specific pxa27x_assert_ac97reset()) which changed the mfp to a GPIO input instead of a high output. The fix requires the ac97 controller to obtain the gpio via gpio_request_one(), with arguments that configure the gpio as an output initially driven high. Tested on a palm treo 680 machine. Reportedly, this broken code only prevents a warm reset on hardware that lacks a pull-up on the line, which appears to be the case for me. Signed-off-by: Mike Dunn Signed-off-by: Igor Grinberg Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | 3 +++ arch/arm/mach-pxa/pxa27x.c | 4 ++-- sound/arm/pxa2xx-ac97-lib.c | 18 +++++++++++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h index a65867209aa0..b4eb3daf037b 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h @@ -462,6 +462,9 @@ GPIO76_LCD_PCLK, \ GPIO77_LCD_BIAS +/* these enable a work-around for a hw bug in pxa27x during ac97 warm reset */ +#define GPIO113_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO113, AF0, DEFAULT) +#define GPIO95_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO95, AF0, DEFAULT) extern int keypad_set_wake(unsigned int on); #endif /* __ASM_ARCH_MFP_PXA27X_H */ diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 4726c246dcdc..a2fe795bae14 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -47,9 +47,9 @@ void pxa27x_clear_otgph(void) EXPORT_SYMBOL(pxa27x_clear_otgph); static unsigned long ac97_reset_config[] = { - GPIO113_GPIO, + GPIO113_AC97_nRESET_GPIO_HIGH, GPIO113_AC97_nRESET, - GPIO95_GPIO, + GPIO95_AC97_nRESET_GPIO_HIGH, GPIO95_AC97_nRESET, }; diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 8cfb2c0efcb2..bd3ba8812e13 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -344,8 +345,21 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) } if (cpu_is_pxa27x()) { - /* Use GPIO 113 as AC97 Reset on Bulverde */ + /* + * This gpio is needed for a work-around to a bug in the ac97 + * controller during warm reset. The direction and level is set + * here so that it is an output driven high when switching from + * AC97_nRESET alt function to generic gpio. + */ + ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH, + "pxa27x ac97 reset"); + if (ret < 0) { + pr_err("%s: gpio_request_one() failed: %d\n", + __func__, ret); + goto err_conf; + } pxa27x_assert_ac97reset(reset_gpio, 0); + ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); if (IS_ERR(ac97conf_clk)) { ret = PTR_ERR(ac97conf_clk); @@ -388,6 +402,8 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe); void pxa2xx_ac97_hw_remove(struct platform_device *dev) { + if (cpu_is_pxa27x()) + gpio_free(reset_gpio); GCR |= GCR_ACLINK_OFF; free_irq(IRQ_AC97, NULL); if (ac97conf_clk) { -- GitLab From e7b67acb37508a8a173038a928816d9e826b6363 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 4 Dec 2012 15:59:55 +0000 Subject: [PATCH 1420/1799] staging: comedi: prevent auto-unconfig of manually configured devices commit 7d3135af399e92cf4c9bbc5f86b6c140aab3b88c upstream. When a low-level comedi driver auto-configures a device, a `struct comedi_dev_file_info` is allocated (as well as a `struct comedi_device`) by `comedi_alloc_board_minor()`. A pointer to the hardware `struct device` is stored as a cookie in the `struct comedi_dev_file_info`. When the low-level comedi driver auto-unconfigures the device, `comedi_auto_unconfig()` uses the cookie to find the `struct comedi_dev_file_info` so it can detach the comedi device from the driver, clean it up and free it. A problem arises if the user manually unconfigures and reconfigures the comedi device using the `COMEDI_DEVCONFIG` ioctl so that is no longer associated with the original hardware device. The problem is that the cookie is not cleared, so that a call to `comedi_auto_unconfig()` from the low-level driver will still find it, detach it, clean it up and free it. Stop this problem occurring by always clearing the `hardware_device` cookie in the `struct comedi_dev_file_info` whenever the `COMEDI_DEVCONFIG` ioctl call is successful. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index b719460c4ecf..3fd9772d7a7d 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -138,6 +138,9 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, if (cmd == COMEDI_DEVCONFIG) { rc = do_devconfig_ioctl(dev, (struct comedi_devconfig __user *)arg); + if (rc == 0) + /* Evade comedi_auto_unconfig(). */ + dev_file_info->hardware_device = NULL; goto done; } -- GitLab From a72725d609f46f4099fb2f4bbfb128d2ce84074e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Piel?= Date: Wed, 19 Dec 2012 13:03:13 +0100 Subject: [PATCH 1421/1799] staging: comedi: fix minimum AO period for NI 625x and NI 628x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 34b55d8c48f4f76044d8f4d6ec3dc786cf210312 upstream. The minimum period was set to 357 ns, while the divider for these boards is 50 ns. This prevented to output at maximum speed as ni_ao_cmdtest() would return 357 but would not accept it. Not sure why it was set to 357 ns (this was done before the git history, which starts 5 years ago). My guess is that it comes from reading the specification stating a 2.8 MHz rate (~ 357 ns). The latest specification states a 2.86 MHz rate (~ 350 ns), which makes a lot more sense. Tested on a pci-6251. Signed-off-by: Éric Piel Acked-By: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcimio.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 27baefa32b17..59c1f88894a8 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1023,7 +1023,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1042,7 +1042,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1061,7 +1061,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1097,7 +1097,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 32, .caldac = {caldac_none}, .has_8255 = 0, @@ -1116,7 +1116,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 32, .caldac = {caldac_none}, .has_8255 = 0, @@ -1152,7 +1152,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_628x_ao, .reg_type = ni_reg_628x, .ao_unipolar = 1, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1171,7 +1171,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_628x_ao, .reg_type = ni_reg_628x, .ao_unipolar = 1, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1207,7 +1207,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_628x_ao, .reg_type = ni_reg_628x, .ao_unipolar = 1, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 32, .caldac = {caldac_none}, .has_8255 = 0, -- GitLab From 9a194265172c86fa49299c9fcce7fe9590d66220 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 4 Jan 2013 11:33:21 +0000 Subject: [PATCH 1422/1799] staging: comedi: comedi_test: fix race when cancelling command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c0729eeefdcd76db338f635162bf0739fd2c5f6f upstream. Éric Piel reported a kernel oops in the "comedi_test" module. It was a NULL pointer dereference within `waveform_ai_interrupt()` (actually a timer function) that sometimes occurred when a running asynchronous command is cancelled (either by the `COMEDI_CANCEL` ioctl or by closing the device file). This seems to be a race between the caller of `waveform_ai_cancel()` which on return from that function goes and tears down the running command, and the timer function which uses the command. In particular, `async->cmd.chanlist` gets freed (and the pointer set to NULL) by `do_become_nonbusy()` in "comedi_fops.c" but a previously scheduled `waveform_ai_interrupt()` timer function will dereference that pointer regardless, leading to the oops. Fix it by replacing the `del_timer()` call in `waveform_ai_cancel()` with `del_timer_sync()`. Signed-off-by: Ian Abbott Reported-by: Éric Piel Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/comedi_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index a804742b8022..2567f9ab4167 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -461,7 +461,7 @@ static int waveform_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { devpriv->timer_running = 0; - del_timer(&devpriv->timer); + del_timer_sync(&devpriv->timer); return 0; } -- GitLab From bef86636513cdbdbdd8eeb53ad4403a3e71e5e94 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 29 Dec 2012 11:36:53 -0600 Subject: [PATCH 1423/1799] staging: r8712u: Add new device ID commit da849a92d3bafaf24d770e971c2c9e5c3f60b5d1 upstream. The ISY IWL 1000 USB WLAN stick with USB ID 050d:11f1 is a clone of the Belkin F7D1101 V1 device. Reported-by: Thomas Hartmann Signed-off-by: Larry Finger Cc: Thomas Hartmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/usb_intf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 2c80745a446c..7b3ae00ac54a 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -66,6 +66,8 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = { {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */ /* Belkin */ {USB_DEVICE(0x050D, 0x945A)}, + /* ISY IWL - Belkin clone */ + {USB_DEVICE(0x050D, 0x11F1)}, /* Corega */ {USB_DEVICE(0x07AA, 0x0047)}, /* D-Link */ -- GitLab From 16557f3521d980a2b88c53f9cf3c7d36fbb308a5 Mon Sep 17 00:00:00 2001 From: Nickolai Zeldovich Date: Sat, 5 Jan 2013 14:17:45 -0500 Subject: [PATCH 1424/1799] staging: speakup: avoid out-of-range access in synth_init() commit ae428655b826f2755a8101b27beda42a275ef8ad upstream. Check that array index is in-bounds before accessing the synths[] array. Signed-off-by: Nickolai Zeldovich Cc: Samuel Thibault Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/synth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c index 331eae788700..217fd4a49bdc 100644 --- a/drivers/staging/speakup/synth.c +++ b/drivers/staging/speakup/synth.c @@ -342,7 +342,7 @@ int synth_init(char *synth_name) mutex_lock(&spk_mutex); /* First, check if we already have it loaded. */ - for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) + for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) if (strcmp(synths[i]->name, synth_name) == 0) synth = synths[i]; -- GitLab From 95afecc15423d5ceaeaf26b943cb8891f9e36e26 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 7 Jan 2013 22:03:51 +0100 Subject: [PATCH 1425/1799] staging: speakup: avoid out-of-range access in synth_add() commit 6102c48bd421074a33e102f2ebda3724e8d275f9 upstream. Check that array index is in-bounds before accessing the synths[] array. Signed-off-by: Samuel Thibault Cc: Nickolai Zeldovich Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/synth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c index 217fd4a49bdc..5710fc582beb 100644 --- a/drivers/staging/speakup/synth.c +++ b/drivers/staging/speakup/synth.c @@ -423,7 +423,7 @@ int synth_add(struct spk_synth *in_synth) int i; int status = 0; mutex_lock(&spk_mutex); - for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) + for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) /* synth_remove() is responsible for rotating the array down */ if (in_synth == synths[i]) { mutex_unlock(&spk_mutex); -- GitLab From 4a3b5681d6b64611375903695481641debd1c308 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Tue, 8 Jan 2013 18:41:01 -0500 Subject: [PATCH 1426/1799] radeon/kms: force rn50 chip to always report connected on analog output commit 51861d4eebc2ddc25c77084343d060fa79f6e291 upstream. Those rn50 chip are often connected to console remoting hw and load detection often fails with those. Just don't try to load detect and report connect. Signed-off-by: Jerome Glisse Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index d92f483fed41..53b07a3a8bb3 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -617,6 +617,14 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc enum drm_connector_status found = connector_status_disconnected; bool color = true; + /* just don't bother on RN50 those chip are often connected to remoting + * console hw and often we get failure to load detect those. So to make + * everyone happy report the encoder as always connected. + */ + if (ASIC_IS_RN50(rdev)) { + return connector_status_connected; + } + /* save the regs we need */ vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL); crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); -- GitLab From 5ca99e71a9a6cf33a217690f5d87bc0129d1effd Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 11 Dec 2012 10:48:23 +0100 Subject: [PATCH 1427/1799] mac80211: fix ibss scanning commit 34bcf71502413f8903ade93746f2d0f04b937a78 upstream. Do not scan on no-IBSS and disabled channels in IBSS mode. Doing this can trigger Microcode errors on iwlwifi and iwlegacy drivers. Also rename ieee80211_request_internal_scan() function since it is only used in IBSS mode and simplify calling it from ieee80211_sta_find_ibss(). This patch should address: https://bugzilla.redhat.com/show_bug.cgi?id=883414 https://bugzilla.kernel.org/show_bug.cgi?id=49411 Reported-by: Jesse Kahtava Reported-by: Mikko Rapeli Signed-off-by: Stanislaw Gruszka Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ibss.c | 9 ++++----- net/mac80211/ieee80211_i.h | 6 +++--- net/mac80211/scan.c | 34 ++++++++++++++++++++++++---------- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 7c51bae7f1ca..50191a30207c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -664,8 +664,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " "IBSS networks with same SSID (merge)\n", sdata->name); - ieee80211_request_internal_scan(sdata, - ifibss->ssid, ifibss->ssid_len, NULL); + ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, + NULL); } static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) @@ -772,9 +772,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " "join\n", sdata->name); - ieee80211_request_internal_scan(sdata, - ifibss->ssid, ifibss->ssid_len, - ifibss->fixed_channel ? ifibss->channel : NULL); + ieee80211_request_ibss_scan(sdata, ifibss->ssid, + ifibss->ssid_len, chan); } else { int interval = IEEE80211_SCAN_INTERVAL; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 498e87bcb3eb..f8b5e75be8cb 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1233,9 +1233,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, /* scan/BSS handling */ void ieee80211_scan_work(struct work_struct *work); -int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, - const u8 *ssid, u8 ssid_len, - struct ieee80211_channel *chan); +int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, + const u8 *ssid, u8 ssid_len, + struct ieee80211_channel *chan); int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, struct cfg80211_scan_request *req); void ieee80211_scan_cancel(struct ieee80211_local *local); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index c70e17677135..e95d494f36e0 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -761,9 +761,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, return res; } -int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, - const u8 *ssid, u8 ssid_len, - struct ieee80211_channel *chan) +int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, + const u8 *ssid, u8 ssid_len, + struct ieee80211_channel *chan) { struct ieee80211_local *local = sdata->local; int ret = -EBUSY; @@ -777,22 +777,36 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, /* fill internal scan request */ if (!chan) { - int i, nchan = 0; + int i, max_n; + int n_ch = 0; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { if (!local->hw.wiphy->bands[band]) continue; - for (i = 0; - i < local->hw.wiphy->bands[band]->n_channels; - i++) { - local->int_scan_req->channels[nchan] = + + max_n = local->hw.wiphy->bands[band]->n_channels; + for (i = 0; i < max_n; i++) { + struct ieee80211_channel *tmp_ch = &local->hw.wiphy->bands[band]->channels[i]; - nchan++; + + if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_DISABLED)) + continue; + + local->int_scan_req->channels[n_ch] = tmp_ch; + n_ch++; } } - local->int_scan_req->n_channels = nchan; + if (WARN_ON_ONCE(n_ch == 0)) + goto unlock; + + local->int_scan_req->n_channels = n_ch; } else { + if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_DISABLED))) + goto unlock; + local->int_scan_req->channels[0] = chan; local->int_scan_req->n_channels = 1; } -- GitLab From 848842e67d24fed13a2aece3d03e235267e5a3a6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 13 Dec 2012 23:08:52 +0100 Subject: [PATCH 1428/1799] mac80211: use del_timer_sync for final sta cleanup timer deletion commit a56f992cdabc63f56b4b142885deebebf936ff76 upstream. This is a very old bug, but there's nothing that prevents the timer from running while the module is being removed when we only do del_timer() instead of del_timer_sync(). The timer should normally not be running at this point, but it's not clearly impossible (or we could just remove this.) Tested-by: Ben Greear Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/sta_info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 6d25d7796fc6..e2e0e0bc6622 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -844,7 +844,7 @@ void sta_info_init(struct ieee80211_local *local) void sta_info_stop(struct ieee80211_local *local) { - del_timer(&local->sta_cleanup); + del_timer_sync(&local->sta_cleanup); sta_info_flush(local, NULL); } -- GitLab From 99dd9a98065129261e24ad44f41b26e3a841f654 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Wed, 2 Jan 2013 16:07:35 -0800 Subject: [PATCH 1429/1799] mwifiex: check wait_event_interruptible return value commit 9c969d8ccb1e17bd20742f4ac9f00c1a64487234 upstream. wait_event_interruptible function returns -ERESTARTSYS if it's interrupted by a signal. Driver should check the return value and handle this case properly. In mwifiex_wait_queue_complete() routine, as we are now checking wait_event_interruptible return value, the condition check is not required. Also, we have removed mwifiex_cancel_pending_ioctl() call to avoid a chance of sending second command to FW by other path as soon as we clear current command node. FW can not handle two commands simultaneously. Signed-off-by: Bing Zhao Signed-off-by: Amitkumar Karwar Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mwifiex/sta_ioctl.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index d7b11defafe0..4fb146a8fac2 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -53,7 +53,6 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, */ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) { - bool cancel_flag = false; int status; struct cmd_ctrl_node *cmd_queued; @@ -70,14 +69,11 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) queue_work(adapter->workqueue, &adapter->main_work); /* Wait for completion */ - wait_event_interruptible(adapter->cmd_wait_q.wait, - *(cmd_queued->condition)); - if (!*(cmd_queued->condition)) - cancel_flag = true; - - if (cancel_flag) { - mwifiex_cancel_pending_ioctl(adapter); - dev_dbg(adapter->dev, "cmd cancel\n"); + status = wait_event_interruptible(adapter->cmd_wait_q.wait, + *(cmd_queued->condition)); + if (status) { + dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); + return status; } status = adapter->cmd_wait_q.status; @@ -436,8 +432,11 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) return false; } - wait_event_interruptible(adapter->hs_activate_wait_q, - adapter->hs_activate_wait_q_woken); + if (wait_event_interruptible(adapter->hs_activate_wait_q, + adapter->hs_activate_wait_q_woken)) { + dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); + return false; + } return true; } -- GitLab From 16fc9b0aa12763fb66e1bd702714c7e3da38cd0f Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 20 Dec 2012 15:55:01 -0600 Subject: [PATCH 1430/1799] b43: Fix firmware loading when driver is built into the kernel commit 5e20a4b53094651d80f856ff55a916b999dbb57a upstream. Recent versions of udev cause synchronous firmware loading from the probe routine to fail because the request to user space would time out. The original fix for b43 (commit 6b6fa58) moved the firmware load from the probe routine to a work queue, but it still used synchronous firmware loading. This method is OK when b43 is built as a module; however, it fails when the driver is compiled into the kernel. This version changes the code to load the initial firmware file using request_firmware_nowait(). A completion event is used to hold the work queue until that file is available. This driver reads several firmware files - the remainder can be read synchronously. On some test systems, the async read fails; however, a following synch read works, thus the async failure falls through to the sync try. Reported-and-Tested by: Felix Janda Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/b43/b43.h | 5 +++ drivers/net/wireless/b43/main.c | 54 +++++++++++++++++++++++++-------- drivers/net/wireless/b43/main.h | 5 ++- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 67c13af6f206..05cb5f6b8d48 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "debugfs.h" @@ -718,6 +719,10 @@ enum b43_firmware_file_type { struct b43_request_fw_context { /* The device we are requesting the fw for. */ struct b43_wldev *dev; + /* a completion event structure needed if this call is asynchronous */ + struct completion fw_load_complete; + /* a pointer to the firmware object */ + const struct firmware *blob; /* The type of firmware to request. */ enum b43_firmware_file_type req_type; /* Error messages for each firmware type. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 4e465c5b2df7..14fd2caa1f9f 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2088,11 +2088,18 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) b43warn(wl, text); } +static void b43_fw_cb(const struct firmware *firmware, void *context) +{ + struct b43_request_fw_context *ctx = context; + + ctx->blob = firmware; + complete(&ctx->fw_load_complete); +} + int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, - struct b43_firmware_file *fw) + struct b43_firmware_file *fw, bool async) { - const struct firmware *blob; struct b43_fw_header *hdr; u32 size; int err; @@ -2131,11 +2138,31 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, B43_WARN_ON(1); return -ENOSYS; } - err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); + if (async) { + /* do this part asynchronously */ + init_completion(&ctx->fw_load_complete); + err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, + ctx->dev->dev->dev, GFP_KERNEL, + ctx, b43_fw_cb); + if (err < 0) { + pr_err("Unable to load firmware\n"); + return err; + } + /* stall here until fw ready */ + wait_for_completion(&ctx->fw_load_complete); + if (ctx->blob) + goto fw_ready; + /* On some ARM systems, the async request will fail, but the next sync + * request works. For this reason, we dall through here + */ + } + err = request_firmware(&ctx->blob, ctx->fwname, + ctx->dev->dev->dev); if (err == -ENOENT) { snprintf(ctx->errors[ctx->req_type], sizeof(ctx->errors[ctx->req_type]), - "Firmware file \"%s\" not found\n", ctx->fwname); + "Firmware file \"%s\" not found\n", + ctx->fwname); return err; } else if (err) { snprintf(ctx->errors[ctx->req_type], @@ -2144,14 +2171,15 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, ctx->fwname, err); return err; } - if (blob->size < sizeof(struct b43_fw_header)) +fw_ready: + if (ctx->blob->size < sizeof(struct b43_fw_header)) goto err_format; - hdr = (struct b43_fw_header *)(blob->data); + hdr = (struct b43_fw_header *)(ctx->blob->data); switch (hdr->type) { case B43_FW_TYPE_UCODE: case B43_FW_TYPE_PCM: size = be32_to_cpu(hdr->size); - if (size != blob->size - sizeof(struct b43_fw_header)) + if (size != ctx->blob->size - sizeof(struct b43_fw_header)) goto err_format; /* fallthrough */ case B43_FW_TYPE_IV: @@ -2162,7 +2190,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, goto err_format; } - fw->data = blob; + fw->data = ctx->blob; fw->filename = name; fw->type = ctx->req_type; @@ -2172,7 +2200,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, snprintf(ctx->errors[ctx->req_type], sizeof(ctx->errors[ctx->req_type]), "Firmware file \"%s\" format error.\n", ctx->fwname); - release_firmware(blob); + release_firmware(ctx->blob); return -EPROTO; } @@ -2223,7 +2251,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) goto err_no_ucode; } } - err = b43_do_request_fw(ctx, filename, &fw->ucode); + err = b43_do_request_fw(ctx, filename, &fw->ucode, true); if (err) goto err_load; @@ -2235,7 +2263,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) else goto err_no_pcm; fw->pcm_request_failed = false; - err = b43_do_request_fw(ctx, filename, &fw->pcm); + err = b43_do_request_fw(ctx, filename, &fw->pcm, false); if (err == -ENOENT) { /* We did not find a PCM file? Not fatal, but * core rev <= 10 must do without hwcrypto then. */ @@ -2296,7 +2324,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) default: goto err_no_initvals; } - err = b43_do_request_fw(ctx, filename, &fw->initvals); + err = b43_do_request_fw(ctx, filename, &fw->initvals, false); if (err) goto err_load; @@ -2355,7 +2383,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) default: goto err_no_initvals; } - err = b43_do_request_fw(ctx, filename, &fw->initvals_band); + err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false); if (err) goto err_load; diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 8c684cd33529..abac25ee958d 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -137,9 +137,8 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on); struct b43_request_fw_context; -int b43_do_request_fw(struct b43_request_fw_context *ctx, - const char *name, - struct b43_firmware_file *fw); +int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, + struct b43_firmware_file *fw, bool async); void b43_do_release_fw(struct b43_firmware_file *fw); #endif /* B43_MAIN_H_ */ -- GitLab From d6e362f53991a42b64b5fac902274b328d817e47 Mon Sep 17 00:00:00 2001 From: Dzianis Kahanovich Date: Mon, 3 Dec 2012 16:06:26 +0300 Subject: [PATCH 1431/1799] USB: option: add Nexpring NP10T terminal id commit ad86e58661b38b279b7519d4e49c7a19dc1654bb upstream. Hyundai Petatel Inc. Nexpring NP10T terminal (EV-DO rev.A USB modem) ID Signed-off-by: Denis Kaganovich Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 0c3d29034816..136580dd9d2d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -441,6 +441,10 @@ static void option_instat_callback(struct urb *urb); #define CELLIENT_VENDOR_ID 0x2692 #define CELLIENT_PRODUCT_MEN200 0x9005 +/* Hyundai Petatel Inc. products */ +#define PETATEL_VENDOR_ID 0x1ff4 +#define PETATEL_PRODUCT_NP10T 0x600e + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -1295,6 +1299,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, + { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- GitLab From b80a67da576ee645568ecc1305743662809090d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 19 Dec 2012 15:15:17 +0100 Subject: [PATCH 1432/1799] USB: option: blacklist network interface on ZTE MF880 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit fab38246f318edcd0dcb8fd3852a47cf8938878a upstream. The driver description files gives these names to the vendor specific functions on this modem: diag: VID_19D2&PID_0284&MI_00 nmea: VID_19D2&PID_0284&MI_01 at: VID_19D2&PID_0284&MI_02 mdm: VID_19D2&PID_0284&MI_03 net: VID_19D2&PID_0284&MI_04 Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 136580dd9d2d..17630e1cc6d4 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -927,7 +927,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, -- GitLab From 719d0cdd2c42bf0d272d285e89cb9ad4d2d01728 Mon Sep 17 00:00:00 2001 From: "Quentin.Li" Date: Wed, 26 Dec 2012 16:58:22 +0800 Subject: [PATCH 1433/1799] USB: option: Add new MEDIATEK PID support commit 94a85b633829b946eef53fc1825d526312fb856f upstream. In option.c, add some new MEDIATEK PIDs support for MEDIATEK new products. This is a MEDIATEK inc. release patch. Signed-off-by: Quentin.Li Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 17630e1cc6d4..b7d98c54dabc 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -429,9 +429,12 @@ static void option_instat_callback(struct urb *urb); #define MEDIATEK_VENDOR_ID 0x0e8d #define MEDIATEK_PRODUCT_DC_1COM 0x00a0 #define MEDIATEK_PRODUCT_DC_4COM 0x00a5 +#define MEDIATEK_PRODUCT_DC_4COM2 0x00a7 #define MEDIATEK_PRODUCT_DC_5COM 0x00a4 #define MEDIATEK_PRODUCT_7208_1COM 0x7101 #define MEDIATEK_PRODUCT_7208_2COM 0x7102 +#define MEDIATEK_PRODUCT_7103_2COM 0x7103 +#define MEDIATEK_PRODUCT_7106_2COM 0x7106 #define MEDIATEK_PRODUCT_FP_1COM 0x0003 #define MEDIATEK_PRODUCT_FP_2COM 0x0023 #define MEDIATEK_PRODUCT_FPDC_1COM 0x0043 @@ -1299,6 +1302,10 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7103_2COM, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7106_2COM, 0x02, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) }, { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, { } /* Terminating entry */ -- GitLab From 1aaa39456c16f3f290811312d2ac81c0bdfdd1d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 28 Dec 2012 17:29:52 +0100 Subject: [PATCH 1434/1799] USB: option: add Telekom Speedstick LTE II MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 5ec0085440ef8c2cf50002b34d5a504ee12aa2bf upstream. also known as Alcatel One Touch L100V LTE The driver description files gives these names to the vendor specific functions on this modem: Application1: VID_1BBB&PID_011E&MI_00 Application2: VID_1BBB&PID_011E&MI_01 Modem: VID_1BBB&PID_011E&MI_03 Ethernet: VID_1BBB&PID_011E&MI_04 Reported-by: Thomas Schäfer Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index b7d98c54dabc..ba23ad55f41a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -288,6 +288,7 @@ static void option_instat_callback(struct urb *urb); #define ALCATEL_VENDOR_ID 0x1bbb #define ALCATEL_PRODUCT_X060S_X200 0x0000 #define ALCATEL_PRODUCT_X220_X500D 0x0017 +#define ALCATEL_PRODUCT_L100V 0x011e #define PIRELLI_VENDOR_ID 0x1266 #define PIRELLI_PRODUCT_C100_1 0x1002 @@ -1198,6 +1199,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), -- GitLab From 91d816cd00e5de594a1ec62893edbd9b84c5c252 Mon Sep 17 00:00:00 2001 From: Tomasz Mloduchowski Date: Sun, 13 Jan 2013 23:32:53 +0100 Subject: [PATCH 1435/1799] usb: ftdi_sio: Crucible Technologies COMET Caller ID - pid added commit 8cf65dc386f3634a43312f436cc7a935476a40c4 upstream. Simple fix to add support for Crucible Technologies COMET Caller ID USB decoder - a device containing FTDI USB/Serial converter chip, handling 1200bps CallerID messages decoded from the phone line - adding correct USB PID is sufficient. Tested to apply cleanly and work flawlessly against 3.6.9, 3.7.0-rc8 and 3.8.0-rc3 on both amd64 and x86 arches. Signed-off-by: Tomasz Mloduchowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 25903f54c1d2..3fbf39d66a7a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -881,6 +881,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, + /* Crucible Devices */ + { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 049b6e715fa4..fa5d56038276 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1259,3 +1259,9 @@ * ATI command output: Cinterion MC55i */ #define FTDI_CINTERION_MC55I_PID 0xA951 + +/* + * Product: Comet Caller ID decoder + * Manufacturer: Crucible Technologies + */ +#define FTDI_CT_COMET_PID 0x8e08 -- GitLab From b756d75a459f351e43d1d71295d5f6b94ec811c3 Mon Sep 17 00:00:00 2001 From: Denis N Ladin Date: Wed, 26 Dec 2012 18:29:44 +0500 Subject: [PATCH 1436/1799] USB: cdc-acm: Add support for "PSC Scanning, Magellan 800i" commit 036915a7a402753c05b8d0529f5fd08805ab46d0 upstream. Adding support "PSC Scanning, Magellan 800i" in cdc-acm Very simple, but very necessary. Suitable for all versions of the kernel > 2.6 Signed-off-by: Denis N Ladin Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index b4e87cfa73a7..3a7a95084cc5 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1602,6 +1602,9 @@ static const struct usb_device_id acm_ids[] = { { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ .driver_info = NO_UNION_NORMAL, }, + { USB_DEVICE(0x05f9, 0x4002), /* PSC Scanning, Magellan 800i */ + .driver_info = NO_UNION_NORMAL, + }, { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ }, -- GitLab From 98bea5234411352182c84918640629fe05bf64b5 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 20 Nov 2012 13:23:15 +0100 Subject: [PATCH 1437/1799] usb: gadget: dummy: fix enumeration with g_multi commit 1d16638e3b9cc195bac18a8fcbca748f33c1bc24 upstream. If we do have endpoints named like "ep-a" then bEndpointAddress is counted internally by the gadget framework. If we do have endpoints named like "ep-1" then bEndpointAddress is assigned from the digit after "ep-". If we do have both, then it is likely that after we used up the "generic" endpoints we will use the digits and thus assign one bEndpointAddress to multiple endpoints. This theory can be proofed by using the completely enabled g_multi. Without this patch, the mass storage won't enumerate and times out because it shares endpoints with RNDIS. This patch also adds fills up the endpoints list so we have in total endpoints 1 to 15 in + out available while some of them are restricted to certain types like BULK or ISO. Without this change the nokia gadget won't load because the system does not provide enough (BULK) endpoints but it did before ep-a - ep-f were removed. Signed-off-by: Sebastian Andrzej Siewior Acked-by: Alan Stern Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/dummy_hcd.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 2d277a2bc335..9a7b436bd925 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -126,10 +126,7 @@ static const char ep0name[] = "ep0"; static const char *const ep_name[] = { ep0name, /* everyone has ep0 */ - /* act like a net2280: high speed, six configurable endpoints */ - "ep-a", "ep-b", "ep-c", "ep-d", "ep-e", "ep-f", - - /* or like pxa250: fifteen fixed function endpoints */ + /* act like a pxa250: fifteen fixed function endpoints */ "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int", "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int", "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso", @@ -137,6 +134,10 @@ static const char *const ep_name[] = { /* or like sa1100: two fixed function endpoints */ "ep1out-bulk", "ep2in-bulk", + + /* and now some generic EPs so we have enough in multi config */ + "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in", + "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out", }; #define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name) -- GitLab From 1353cac7123b29dc169e775a7f3cf20929d0ef72 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 14 Nov 2012 18:49:50 +0300 Subject: [PATCH 1438/1799] usb: musb: core: print new line in the driver banner again commit 2ac788f705e5118dd45204e7a5bc8d5bb6873835 upstream. Commit 5c8a86e10a7c164f44537fabdc169fd8b4e7a440 (usb: musb: drop unneeded musb_debug trickery) erroneously removed '\n' from the driver's banner. Concatenate all the banner substrings while adding it back... Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 66aaccf04490..a2b4008dc069 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2400,10 +2400,7 @@ static int __init musb_init(void) if (usb_disabled()) return 0; - pr_info("%s: version " MUSB_VERSION ", " - "?dma?" - ", " - "otg (peripheral+host)", + pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n", musb_driver_name); return platform_driver_register(&musb_driver); } -- GitLab From e5583b77083d74c988dfd8572cd8f7d246bf63ac Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Tue, 18 Dec 2012 20:30:47 +0100 Subject: [PATCH 1439/1799] drm/nouveau: fix blank LVDS screen regression on pre-nv50 cards commit 92441b2263866c27ef48137be5aa6c8c692652fc upstream. Commit 2a44e499 ("drm/nouveau/disp: introduce proper init/fini, separate from create/destroy") started to call display init routines on pre-nv50 hardware on module load. But LVDS init code sets driver state in a way which prevents modesetting code from operating properly. nv04_display_init calls nv04_dfp_restore, which sets encoder->last_dpms to NV_DPMS_CLEARED. drm_crtc_helper_set_mode nv04_dfp_prepare nv04_lvds_dpms(DRM_MODE_DPMS_OFF) nv04_lvds_dpms checks last_dpms mode (which is NV_DPMS_CLEARED) and wrongly assumes it's a "powersaving mode", the new one (DRM_MODE_DPMS_OFF) is too, so it skips calling some crucial lvds scripts. Reported-by: Chris Paulson-Ellis Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nv04_dfp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 473f30a4194a..71b62352315f 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -504,7 +504,7 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) static inline bool is_powersaving_dpms(int mode) { - return (mode != DRM_MODE_DPMS_ON); + return mode != DRM_MODE_DPMS_ON && mode != NV_DPMS_CLEARED; } static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) -- GitLab From 98e5587b9abe155e356d9eef3be6b1472c508c96 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 14 Nov 2012 15:58:52 -0800 Subject: [PATCH 1440/1799] USB: Handle auto-transition from hot to warm reset. commit 1c7439c61fa6516419c32a9824976334ea969d47 upstream. USB 3.0 hubs and roothubs will automatically transition a failed hot reset to a warm (BH) reset. In that case, the warm reset change bit will be set, and the link state change bit may also be set. Change hub_port_finish_reset to unconditionally clear those change bits for USB 3.0 hubs. If these bits are not cleared, we may lose port change events from the roothub. This commit should be backported to kernels as old as 3.2, that contain the commit 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine warm reset logic". Signed-off-by: Sarah Sharp Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 11344bcc1758..8dee90becf03 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2249,16 +2249,16 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1, clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_RESET); /* FIXME need disconnect() for NOTATTACHED device */ - if (warm) { + if (hub_is_superspeed(hub->hdev)) { clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_BH_PORT_RESET); clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_PORT_LINK_STATE); - } else { + } + if (!warm) usb_set_device_state(udev, *status ? USB_STATE_NOTATTACHED : USB_STATE_DEFAULT); - } break; } } -- GitLab From 36f037316ff169ca111917d6b1d2546d243a2f78 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 14 Nov 2012 16:10:49 -0800 Subject: [PATCH 1441/1799] USB: Ignore xHCI Reset Device status. commit 8b8132bc3d1cc3d4c0687e4d638a482fa920d98a upstream. When the USB core finishes reseting a USB device, the xHCI driver sends a Reset Device command to the host. The xHC then updates its internal representation of the USB device to the 'Default' device state. If the device was already in the Default state, the xHC will complete the command with an error status. If a device needs to be reset several times during enumeration, the second reset will always fail because of the xHCI Reset Device command. This can cause issues during enumeration. For example, usb_reset_and_verify_device calls into hub_port_init in a loop. Say that on the first call into hub_port_init, the device is successfully reset, but doesn't respond to several set address control transfers. Then the port will be disabled, but the udev will remain in tact. usb_reset_and_verify_device will call into hub_port_init again. On the second call into hub_port_init, the device will be reset, and the xHCI driver will issue a Reset Device command. This command will fail (because the device is already in the Default state), and usb_reset_and_verify_device will fail. The port will be disabled, and the device won't be able to enumerate. Fix this by ignoring the return value of the HCD reset_device callback. This commit should be backported to kernels as old as 3.2, that contain the commit 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine warm reset logic". Signed-off-by: Sarah Sharp Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 8dee90becf03..2a369d3fc3a8 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2234,14 +2234,11 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1, msleep(10 + 40); update_devnum(udev, 0); hcd = bus_to_hcd(udev->bus); - if (hcd->driver->reset_device) { - *status = hcd->driver->reset_device(hcd, udev); - if (*status < 0) { - dev_err(&udev->dev, "Cannot reset " - "HCD device state\n"); - break; - } - } + /* The xHC may think the device is already reset, + * so ignore the status. + */ + if (hcd->driver->reset_device) + hcd->driver->reset_device(hcd, udev); } /* FALL THROUGH */ case -ENOTCONN: -- GitLab From a723a6cf79aa2e283d5134adf2787b8a35e0b8f3 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 14 Nov 2012 16:42:32 -0800 Subject: [PATCH 1442/1799] USB: Allow USB 3.0 ports to be disabled. commit 41e7e056cdc662f704fa9262e5c6e213b4ab45dd upstream. If hot and warm reset fails, or a port remains in the Compliance Mode, the USB core needs to be able to disable a USB 3.0 port. Unlike USB 2.0 ports, once the port is placed into the Disabled link state, it will not report any new device connects. To get device connect notifications, we need to put the link into the Disabled state, and then the RxDetect state. The xHCI driver needs to atomically clear all change bits on USB 3.0 port disable, so that we get Port Status Change Events for future port changes. We could technically do this in the USB core instead of in the xHCI roothub code, since the port state machine can't advance out of the disabled state until we set the link state to RxDetect. However, external USB 3.0 hubs don't need this code. They are level-triggered, not edge-triggered like xHCI, so they will continue to send interrupt events when any change bit is set. Therefore it doesn't make sense to put this code in the USB core. This patch is part of a series to fix several reports of infinite loops on device enumeration failure. This includes John, when he boots with a USB 3.0 device (Roseweil eusb3 enclosure) attached to his NEC 0.96 host controller. The fix requires warm reset support, so it does not make sense to backport this patch to stable kernels without warm reset support. This patch should be backported to kernels as old as 3.2, contain the commit ID 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine warm reset logic" Signed-off-by: Sarah Sharp Acked-by: Alan Stern Reported-by: John Covici Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 63 +++++++++++++++++++++++++++++++++++-- drivers/usb/host/xhci-hub.c | 31 ++++++++++++++++-- 2 files changed, 90 insertions(+), 4 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 2a369d3fc3a8..0e330a1de06a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -644,6 +644,60 @@ static int hub_hub_status(struct usb_hub *hub, return ret; } +static int hub_set_port_link_state(struct usb_hub *hub, int port1, + unsigned int link_status) +{ + return set_port_feature(hub->hdev, + port1 | (link_status << 3), + USB_PORT_FEAT_LINK_STATE); +} + +/* + * If USB 3.0 ports are placed into the Disabled state, they will no longer + * detect any device connects or disconnects. This is generally not what the + * USB core wants, since it expects a disabled port to produce a port status + * change event when a new device connects. + * + * Instead, set the link state to Disabled, wait for the link to settle into + * that state, clear any change bits, and then put the port into the RxDetect + * state. + */ +static int hub_usb3_port_disable(struct usb_hub *hub, int port1) +{ + int ret; + int total_time; + u16 portchange, portstatus; + + if (!hub_is_superspeed(hub->hdev)) + return -EINVAL; + + ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED); + if (ret) { + dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", + port1, ret); + return ret; + } + + /* Wait for the link to enter the disabled state. */ + for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { + ret = hub_port_status(hub, port1, &portstatus, &portchange); + if (ret < 0) + return ret; + + if ((portstatus & USB_PORT_STAT_LINK_STATE) == + USB_SS_PORT_LS_SS_DISABLED) + break; + if (total_time >= HUB_DEBOUNCE_TIMEOUT) + break; + msleep(HUB_DEBOUNCE_STEP); + } + if (total_time >= HUB_DEBOUNCE_TIMEOUT) + dev_warn(hub->intfdev, "Could not disable port %d after %d ms\n", + port1, total_time); + + return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT); +} + static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) { struct usb_device *hdev = hub->hdev; @@ -652,8 +706,13 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) if (hdev->children[port1-1] && set_state) usb_set_device_state(hdev->children[port1-1], USB_STATE_NOTATTACHED); - if (!hub->error && !hub_is_superspeed(hub->hdev)) - ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); + if (!hub->error) { + if (hub_is_superspeed(hub->hdev)) + ret = hub_usb3_port_disable(hub, port1); + else + ret = clear_port_feature(hdev, port1, + USB_PORT_FEAT_ENABLE); + } if (ret) dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", port1, ret); diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index de07b7556d4d..0efc857ed1eb 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -753,12 +753,39 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, break; case USB_PORT_FEAT_LINK_STATE: temp = xhci_readl(xhci, port_array[wIndex]); + + /* Disable port */ + if (link_state == USB_SS_PORT_LS_SS_DISABLED) { + xhci_dbg(xhci, "Disable port %d\n", wIndex); + temp = xhci_port_state_to_neutral(temp); + /* + * Clear all change bits, so that we get a new + * connection event. + */ + temp |= PORT_CSC | PORT_PEC | PORT_WRC | + PORT_OCC | PORT_RC | PORT_PLC | + PORT_CEC; + xhci_writel(xhci, temp | PORT_PE, + port_array[wIndex]); + temp = xhci_readl(xhci, port_array[wIndex]); + break; + } + + /* Put link in RxDetect (enable port) */ + if (link_state == USB_SS_PORT_LS_RX_DETECT) { + xhci_dbg(xhci, "Enable port %d\n", wIndex); + xhci_set_link_state(xhci, port_array, wIndex, + link_state); + temp = xhci_readl(xhci, port_array[wIndex]); + break; + } + /* Software should not attempt to set - * port link state above '5' (Rx.Detect) and the port + * port link state above '3' (U3) and the port * must be enabled. */ if ((temp & PORT_PE) == 0 || - (link_state > USB_SS_PORT_LS_RX_DETECT)) { + (link_state > USB_SS_PORT_LS_U3)) { xhci_warn(xhci, "Cannot set link state.\n"); goto error; } -- GitLab From 7bcaf3b265ae4d197d265916268bceed044d289c Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 14 Nov 2012 17:16:52 -0800 Subject: [PATCH 1443/1799] USB: Increase reset timeout. commit 77c7f072c87fa951e9a74805febf26466f31170c upstream. John's NEC 0.96 xHCI host controller needs a longer timeout for a warm reset to complete. The logs show it takes 650ms to complete the warm reset, so extend the hub reset timeout to 800ms to be on the safe side. This commit should be backported to kernels as old as 3.2, that contain the commit 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine warm reset logic". Signed-off-by: Sarah Sharp Acked-by: Alan Stern Reported-by: John Covici Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0e330a1de06a..12d2b4f5778f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2168,7 +2168,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub) #define HUB_SHORT_RESET_TIME 10 #define HUB_BH_RESET_TIME 50 #define HUB_LONG_RESET_TIME 200 -#define HUB_RESET_TIMEOUT 500 +#define HUB_RESET_TIMEOUT 800 static int hub_port_reset(struct usb_hub *hub, int port1, struct usb_device *udev, unsigned int delay, bool warm); -- GitLab From 870826a75318bfee80967140ce3eb6b55e1e9759 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 15 Nov 2012 14:58:04 -0800 Subject: [PATCH 1444/1799] USB: Ignore port state until reset completes. commit 4f43447e62b37ee19c82a13f72f35b1ca60a74d3 upstream. The port reset code bails out early if the current connect status is cleared (device disconnected). If we're issuing a hot reset, it may also look at the link state before the reset is finished. Section 10.14.2.6 of the USB 3.0 spec says that when a port enters the Error state or Resetting state, the port connection bit retains the value from the previous state. Therefore we can't trust it until the reset finishes. Also, the xHCI spec section 4.19.1.2.5 says software shall ignore the link state while the port is resetting, as it can be in an unknown state. The port state during reset is also unknown for USB 2.0 hubs. The hub sends a reset signal by driving the bus into an SE0 state. This overwhelms the "connect" signal from the device, so the port can't tell whether anything is connected or not. Fix the port reset code to ignore the port link state and current connect bit until the reset finishes, and USB_PORT_STAT_RESET is cleared. Remove the check for USB_PORT_STAT_C_BH_RESET in the warm reset case, because it's redundant. When the warm reset finishes, the port reset bit will be cleared at the same time USB_PORT_STAT_C_BH_RESET is set. Remove the now-redundant check for a cleared USB_PORT_STAT_RESET bit in the code to deal with the finished reset. This patch should be backported to all stable kernels. Signed-off-by: Sarah Sharp Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 12d2b4f5778f..c444c901ec59 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2203,6 +2203,10 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, if (ret < 0) return ret; + /* The port state is unknown until the reset completes. */ + if ((portstatus & USB_PORT_STAT_RESET)) + goto delay; + /* * Some buggy devices require a warm reset to be issued even * when the port appears not to be connected. @@ -2248,11 +2252,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, if ((portchange & USB_PORT_STAT_C_CONNECTION)) return -ENOTCONN; - /* if we`ve finished resetting, then break out of - * the loop - */ - if (!(portstatus & USB_PORT_STAT_RESET) && - (portstatus & USB_PORT_STAT_ENABLE)) { + if ((portstatus & USB_PORT_STAT_ENABLE)) { if (hub_is_wusb(hub)) udev->speed = USB_SPEED_WIRELESS; else if (hub_is_superspeed(hub->hdev)) @@ -2266,10 +2266,10 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, return 0; } } else { - if (portchange & USB_PORT_STAT_C_BH_RESET) - return 0; + return 0; } +delay: /* switch to the long delay after two short delay failures */ if (delay_time >= 2 * HUB_SHORT_RESET_TIME) delay = HUB_LONG_RESET_TIME; -- GitLab From 9dbcaec830cd97f44a0b91b315844e0d7144746b Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 14 Nov 2012 17:58:04 -0800 Subject: [PATCH 1445/1799] USB: Handle warm reset failure on empty port. commit 65bdac5effd15d6af619b3b7218627ef4d84ed6a upstream. An empty port can transition to either Inactive or Compliance Mode if a newly connected USB 3.0 device fails to link train. In that case, we issue a warm reset. Some devices, such as John's Roseweil eusb3 enclosure, slip back into Compliance Mode after the warm reset. The current warm reset code does not check for device connect status on warm reset completion, and it incorrectly reports the warm reset succeeded. This causes the USB core to attempt to send a Set Address control transfer to a port in Compliance Mode, which will always fail. Make hub_port_wait_reset check the current connect status and link state after the warm reset completes. Return a failure status if the device is disconnected or the link state is Compliance Mode or SS.Inactive. Make hub_events disable the port if warm reset fails. This will disable the port, and then bring it back into the RxDetect state. Make the USB core ignore the connect change until the device reconnects. Note that this patch does NOT handle connected devices slipping into the Inactive state very well. This is a concern, because devices can go into the Inactive state on U1/U2 exit failure. However, the fix for that case is too large for stable, so it will be submitted in a separate patch. This patch should be backported to kernels as old as 3.2, contain the commit ID 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine warm reset logic" Signed-off-by: Sarah Sharp Acked-by: Alan Stern Reported-by: John Covici Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c444c901ec59..dbc4bf753746 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2266,6 +2266,11 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, return 0; } } else { + if (!(portstatus & USB_PORT_STAT_CONNECTION) || + hub_port_warm_reset_required(hub, + portstatus)) + return -ENOTCONN; + return 0; } @@ -3830,9 +3835,14 @@ static void hub_events(void) * SS.Inactive state. */ if (hub_port_warm_reset_required(hub, portstatus)) { + int status; + dev_dbg(hub_dev, "warm reset port %d\n", i); - hub_port_reset(hub, i, NULL, + status = hub_port_reset(hub, i, NULL, HUB_BH_RESET_TIME, true); + if (status < 0) + hub_port_disable(hub, i, 1); + connect_change = 0; } if (connect_change) -- GitLab From 4ceac47e41f4d587fa71a26dc87335d639a32520 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 27 Nov 2012 12:30:23 -0800 Subject: [PATCH 1446/1799] xhci: Avoid "dead ports", add roothub port polling. commit c52804a472649b2e5005342308739434cbd51119 upstream. The USB core hub thread (khubd) is designed with external USB hubs in mind. It expects that if a port status change bit is set, the hub will continue to send a notification through the hub status data transfer. Basically, it expects hub notifications to be level-triggered. The xHCI host controller is designed to be edge-triggered on the logical 'OR' of all the port status change bits. When all port status change bits are clear, and a new change bit is set, the xHC will generate a Port Status Change Event. If another change bit is set in the same port status register before the first bit is cleared, it will not send another event. This means that the hub code may lose port status changes because of race conditions between clearing change bits. The user sees this as a "dead port" that doesn't react to device connects. The fix is to turn on port polling whenever a new change bit is set. Once the USB core issues a hub status request that shows that no change bits are set in any USB ports, turn off port polling. We can't allow the USB core to poll the roothub for port events during host suspend because if the PCI host is in D3cold, the port registers will be all f's. Instead, stop the port polling timer, and unconditionally restart it when the host resumes. If there are no port change bits set after the resume, the first call to hub_status_data will disable polling. This patch should be backported to stable kernels with the first xHCI support, 2.6.31 and newer, that include the commit 0f2a79300a1471cf92ab43af165ea13555c8b0a5 "USB: xhci: Root hub support." There will be merge conflicts because the check for HC_STATE_SUSPENDED was moved into xhci_suspend in 3.8. Signed-off-by: Sarah Sharp Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 7 +++++++ drivers/usb/host/xhci-ring.c | 9 +++++++++ drivers/usb/host/xhci.c | 10 ++++++++++ 3 files changed, 26 insertions(+) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 0efc857ed1eb..8331893c75e3 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -940,6 +940,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) int max_ports; __le32 __iomem **port_array; struct xhci_bus_state *bus_state; + bool reset_change = false; max_ports = xhci_get_ports(hcd, &port_array); bus_state = &xhci->bus_state[hcd_index(hcd)]; @@ -971,6 +972,12 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) buf[(i + 1) / 8] |= 1 << (i + 1) % 8; status = 1; } + if ((temp & PORT_RC)) + reset_change = true; + } + if (!status && !reset_change) { + xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); } spin_unlock_irqrestore(&xhci->lock, flags); return status ? retval : 0; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index bf8bcc4dd788..01361f929f1d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1725,6 +1725,15 @@ static void handle_port_status(struct xhci_hcd *xhci, if (bogus_port_status) return; + /* + * xHCI port-status-change events occur when the "or" of all the + * status-change bits in the portsc register changes from 0 to 1. + * New status changes won't cause an event if any other change + * bits are still set. When an event occurs, switch over to + * polling to avoid losing status changes. + */ + xhci_dbg(xhci, "%s: starting port polling.\n", __func__); + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); spin_unlock(&xhci->lock); /* Pass this up to the core */ usb_hcd_poll_rh_status(hcd); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index b4063fc72b42..b04134aa3462 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -880,6 +880,11 @@ int xhci_suspend(struct xhci_hcd *xhci) struct usb_hcd *hcd = xhci_to_hcd(xhci); u32 command; + /* Don't poll the roothubs on bus suspend. */ + xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + del_timer_sync(&hcd->rh_timer); + spin_lock_irq(&xhci->lock); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); @@ -1064,6 +1069,11 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) if (xhci->quirks & XHCI_COMP_MODE_QUIRK) compliance_mode_recovery_timer_init(xhci); + /* Re-enable port polling. */ + xhci_dbg(xhci, "%s: starting port polling.\n", __func__); + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + usb_hcd_poll_rh_status(hcd); + return retval; } #endif /* CONFIG_PM */ -- GitLab From 7dd830b8315230e29f958fd0e039e9eecad28c5d Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 29 Nov 2012 15:05:57 +0100 Subject: [PATCH 1447/1799] USB: hub: handle claim of enabled remote wakeup after reset commit 07e72b95f5038cc82304b9a4a2eb7f9fc391ea68 upstream. Some touchscreens have buggy firmware which claims remote wakeup to be enabled after a reset. They nevertheless crash if the feature is cleared by the host. Add a check for reset resume before checking for an enabled remote wakeup feature. On compliant devices the feature must be cleared after a reset anyway. Signed-off-by: Oliver Neukum Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index dbc4bf753746..ef8f790d6172 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2609,7 +2609,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) static int finish_port_resume(struct usb_device *udev) { int status = 0; - u16 devstatus; + u16 devstatus = 0; /* caller owns the udev device lock */ dev_dbg(&udev->dev, "%s\n", @@ -2654,7 +2654,13 @@ static int finish_port_resume(struct usb_device *udev) if (status) { dev_dbg(&udev->dev, "gone after usb resume? status %d\n", status); - } else if (udev->actconfig) { + /* + * There are a few quirky devices which violate the standard + * by claiming to have remote wakeup enabled after a reset, + * which crash if the feature is cleared, hence check for + * udev->reset_resume + */ + } else if (udev->actconfig && !udev->reset_resume) { le16_to_cpus(&devstatus); if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { status = usb_control_msg(udev, -- GitLab From 74abeffd733e53f83e94fc0d90c0a105af7c58ae Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 17 Dec 2012 14:12:35 -0800 Subject: [PATCH 1448/1799] xhci: Handle HS bulk/ctrl endpoints that don't NAK. commit 55c1945edaac94c5338a3647bc2e85ff75d9cf36 upstream. A high speed control or bulk endpoint may have bInterval set to zero, which means it does not NAK. If bInterval is non-zero, it means the endpoint NAKs at a rate of 2^(bInterval - 1). The xHCI code to compute the NAK interval does not handle the special case of zero properly. The current code unconditionally subtracts one from bInterval and uses it as an exponent. This causes a very large bInterval to be used, and warning messages like these will be printed: usb 1-1: ep 0x1 - rounding interval to 32768 microframes, ep desc says 0 microframes This may cause the xHCI host hardware to reject the Configure Endpoint command, which means the HS device will be unusable under xHCI ports. This patch should be backported to kernels as old as 2.6.31, that contain commit dfa49c4ad120a784ef1ff0717168aa79f55a483a "USB: xhci - fix math in xhci_get_endpoint_interval()". Reported-by: Vincent Pelletier Suggested-by: Alan Stern Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 3e16f1c160a2..b42a6fb45b22 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1250,6 +1250,8 @@ static unsigned int xhci_microframes_to_exponent(struct usb_device *udev, static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, struct usb_host_endpoint *ep) { + if (ep->desc.bInterval == 0) + return 0; return xhci_microframes_to_exponent(udev, ep, ep->desc.bInterval, 0, 15); } -- GitLab From 8b564a8e7334a2ce7a691ec7fe21195475ae999f Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Wed, 7 Nov 2012 00:38:06 -0600 Subject: [PATCH 1449/1799] GFS2: Test bufdata with buffer locked and gfs2_log_lock held commit 96e5d1d3adf56f1c7eeb07258f6a1a0a7ae9c489 upstream. In gfs2_trans_add_bh(), gfs2 was testing if a there was a bd attached to the buffer without having the gfs2_log_lock held. It was then assuming it would stay attached for the rest of the function. However, without either the log lock being held of the buffer locked, __gfs2_ail_flush() could detach bd at any time. This patch moves the locking before the test. If there isn't a bd already attached, gfs2 can safely allocate one and attach it before locking. There is no way that the newly allocated bd could be on the ail list, and thus no way for __gfs2_ail_flush() to detach it. Signed-off-by: Benjamin Marzinski Signed-off-by: Steven Whitehouse [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- fs/gfs2/lops.c | 18 ++++-------------- fs/gfs2/trans.c | 8 ++++++++ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 6b1efb594d90..a392e32af480 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -258,16 +258,14 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) struct gfs2_meta_header *mh; struct gfs2_trans *tr; - lock_buffer(bd->bd_bh); - gfs2_log_lock(sdp); if (!list_empty(&bd->bd_list_tr)) - goto out; + return; tr = current->journal_info; tr->tr_touched = 1; tr->tr_num_buf++; list_add(&bd->bd_list_tr, &tr->tr_list_buf); if (!list_empty(&le->le_list)) - goto out; + return; set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); gfs2_meta_check(sdp, bd->bd_bh); @@ -278,9 +276,6 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) sdp->sd_log_num_buf++; list_add(&le->le_list, &sdp->sd_log_le_buf); tr->tr_num_buf_new++; -out: - gfs2_log_unlock(sdp); - unlock_buffer(bd->bd_bh); } static void buf_lo_before_commit(struct gfs2_sbd *sdp) @@ -611,11 +606,9 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) struct address_space *mapping = bd->bd_bh->b_page->mapping; struct gfs2_inode *ip = GFS2_I(mapping->host); - lock_buffer(bd->bd_bh); - gfs2_log_lock(sdp); if (tr) { if (!list_empty(&bd->bd_list_tr)) - goto out; + return; tr->tr_touched = 1; if (gfs2_is_jdata(ip)) { tr->tr_num_buf++; @@ -623,7 +616,7 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) } } if (!list_empty(&le->le_list)) - goto out; + return; set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); @@ -635,9 +628,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) } else { list_add_tail(&le->le_list, &sdp->sd_log_le_ordered); } -out: - gfs2_log_unlock(sdp); - unlock_buffer(bd->bd_bh); } static void gfs2_check_magic(struct buffer_head *bh) diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index 86ac75d99d31..6ab2a77e7726 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c @@ -145,14 +145,22 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta) struct gfs2_sbd *sdp = gl->gl_sbd; struct gfs2_bufdata *bd; + lock_buffer(bh); + gfs2_log_lock(sdp); bd = bh->b_private; if (bd) gfs2_assert(sdp, bd->bd_gl == gl); else { + gfs2_log_unlock(sdp); + unlock_buffer(bh); gfs2_attach_bufdata(gl, bh, meta); bd = bh->b_private; + lock_buffer(bh); + gfs2_log_lock(sdp); } lops_add(sdp, &bd->bd_le); + gfs2_log_unlock(sdp); + unlock_buffer(bh); } void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) -- GitLab From eb52d3018cd126254c64241e64936a6cfc0a82eb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 8 Dec 2012 12:58:33 +0100 Subject: [PATCH 1450/1799] drm/i915: disable cpt phase pointer fdi rx workaround commit 539526b4137bc0e7a8806c38c8522f226814a0e6 upstream. We've originally added this in commit 291427f5fdadec6e4be2924172e83588880e1539 Author: Jesse Barnes Date: Fri Jul 29 12:42:37 2011 -0700 drm/i915: apply phase pointer override on SNB+ too and then copy-pasted it over to ivb/ppt. The w/a was originally added for ilk/ibx in commit 5b2adf897146edeac6a1e438fb67b5a53dbbdf34 Author: Jesse Barnes Date: Thu Oct 7 16:01:15 2010 -0700 drm/i915: add Ironlake clock gating workaround for FDI link training and fixed up a bit in commit 6f06ce184c765fd8d50669a8d12fdd566c920859 Author: Jesse Barnes Date: Tue Jan 4 15:09:38 2011 -0800 drm/i915: set phase sync pointer override enable before setting phase sync pointer It turns out that this w/a isn't actually required on cpt/ppt and positively harmful on ivb/ppt when using fdi B/C links - it results in a black screen occasionally, with seemingfully everything working as it should. The only failure indication I've found in the hw is that eventually (but not right after the modeset completes) a pipe underrun is signalled. Big thanks to Arthur Runyan for all the ideas for registers to check and changes to test, otherwise I couldn't ever have tracked this down! Reviewed-by: Jesse Barnes Cc: "Runyan, Arthur J" Signed-off-by: Daniel Vetter Signed-off-by: CAI Qian Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 31 ---------------------------- 1 file changed, 31 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index fd150a98a626..ec6d1e0c82b4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2424,18 +2424,6 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) FDI_FE_ERRC_ENABLE); } -static void cpt_phase_pointer_enable(struct drm_device *dev, int pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u32 flags = I915_READ(SOUTH_CHICKEN1); - - flags |= FDI_PHASE_SYNC_OVR(pipe); - I915_WRITE(SOUTH_CHICKEN1, flags); /* once to unlock... */ - flags |= FDI_PHASE_SYNC_EN(pipe); - I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to enable */ - POSTING_READ(SOUTH_CHICKEN1); -} - /* The FDI link training functions for ILK/Ibexpeak. */ static void ironlake_fdi_link_train(struct drm_crtc *crtc) { @@ -2586,9 +2574,6 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) POSTING_READ(reg); udelay(150); - if (HAS_PCH_CPT(dev)) - cpt_phase_pointer_enable(dev, pipe); - for (i = 0; i < 4; i++) { reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); @@ -2707,9 +2692,6 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) POSTING_READ(reg); udelay(150); - if (HAS_PCH_CPT(dev)) - cpt_phase_pointer_enable(dev, pipe); - for (i = 0; i < 4; i++) { reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); @@ -2819,17 +2801,6 @@ static void ironlake_fdi_pll_enable(struct drm_crtc *crtc) } } -static void cpt_phase_pointer_disable(struct drm_device *dev, int pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u32 flags = I915_READ(SOUTH_CHICKEN1); - - flags &= ~(FDI_PHASE_SYNC_EN(pipe)); - I915_WRITE(SOUTH_CHICKEN1, flags); /* once to disable... */ - flags &= ~(FDI_PHASE_SYNC_OVR(pipe)); - I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to lock */ - POSTING_READ(SOUTH_CHICKEN1); -} static void ironlake_fdi_disable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -2859,8 +2830,6 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc) I915_WRITE(FDI_RX_CHICKEN(pipe), I915_READ(FDI_RX_CHICKEN(pipe) & ~FDI_RX_PHASE_SYNC_POINTER_EN)); - } else if (HAS_PCH_CPT(dev)) { - cpt_phase_pointer_disable(dev, pipe); } /* still set train pattern 1 */ -- GitLab From 7d609c8d07b74c0a5ef7b903a9ae918d73a9a039 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 6 Oct 2012 03:56:35 +0200 Subject: [PATCH 1451/1799] KVM: PPC: 44x: fix DCR read/write commit e43a028752fed049e4bd94ef895542f96d79fa74 upstream. When remembering the direction of a DCR transaction, we should write to the same variable that we interpret on later when doing vcpu_run again. Signed-off-by: Alexander Graf Signed-off-by: CAI Qian Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kvm/44x_emulate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c index 549bb2c9a47a..ded8a1a04264 100644 --- a/arch/powerpc/kvm/44x_emulate.c +++ b/arch/powerpc/kvm/44x_emulate.c @@ -79,6 +79,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, run->dcr.dcrn = dcrn; run->dcr.data = 0; run->dcr.is_write = 0; + vcpu->arch.dcr_is_write = 0; vcpu->arch.io_gpr = rt; vcpu->arch.dcr_needed = 1; kvmppc_account_exit(vcpu, DCR_EXITS); @@ -100,6 +101,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, run->dcr.dcrn = dcrn; run->dcr.data = kvmppc_get_gpr(vcpu, rs); run->dcr.is_write = 1; + vcpu->arch.dcr_is_write = 1; vcpu->arch.dcr_needed = 1; kvmppc_account_exit(vcpu, DCR_EXITS); emulated = EMULATE_DO_DCR; -- GitLab From fd5f25462460a68f73ff8f90ac08535b01830d9a Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Wed, 23 May 2012 16:26:54 -0400 Subject: [PATCH 1452/1799] drm/edid/quirks: ViewSonic VA2026w commit bc42aabc6a01b92b0f961d65671564e0e1cd7592 upstream. Entirely new class of fail for this one. The detailed timings are for normal CVT but the monitor really wanted CVT-R. Bugzilla: http://bugzilla.redhat/com/516471 Signed-off-by: Adam Jackson Signed-off-by: Dave Airlie Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_edid.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 6e38325d04a6..9d9835a4fee1 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -66,6 +66,8 @@ #define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5) /* use +hsync +vsync for detailed mode */ #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) +/* Force reduced-blanking timings for detailed modes */ +#define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) struct detailed_mode_closure { struct drm_connector *connector; @@ -120,6 +122,9 @@ static struct edid_quirk { /* Samsung SyncMaster 22[5-6]BW */ { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 }, { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 }, + + /* ViewSonic VA2026w */ + { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING }, }; /*** DDC fetch and block validation ***/ @@ -852,12 +857,19 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, "Wrong Hsync/Vsync pulse width\n"); return NULL; } + + if (quirks & EDID_QUIRK_FORCE_REDUCED_BLANKING) { + mode = drm_cvt_mode(dev, hactive, vactive, 60, true, false, false); + if (!mode) + return NULL; + + goto set_size; + } + mode = drm_mode_create(dev); if (!mode) return NULL; - mode->type = DRM_MODE_TYPE_DRIVER; - if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH) timing->pixel_clock = cpu_to_le16(1088); @@ -881,8 +893,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, drm_mode_do_interlace_quirk(mode, pt); - drm_mode_set_name(mode); - if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) { pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE; } @@ -892,6 +902,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; +set_size: mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; @@ -905,6 +916,9 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, mode->height_mm = edid->height_cm * 10; } + mode->type = DRM_MODE_TYPE_DRIVER; + drm_mode_set_name(mode); + return mode; } -- GitLab From 0ab9c5b5d2ffed9550ca2aae49ef39bfc61d2d0b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 17 Apr 2012 19:35:53 +0100 Subject: [PATCH 1453/1799] drm/i915: Unpin the flip target if we fail to queue the flip commit 83d4092b0381e5dd6f312b2ec57121dcf0fcbade upstream. Signed-off-by: Chris Wilson Cc: Jesse Barnes Signed-off-by: Daniel Vetter Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 50 +++++++++++++++++++--------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ec6d1e0c82b4..c19bc62bc4ef 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7313,14 +7313,14 @@ static int intel_gen2_queue_flip(struct drm_device *dev, ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); if (ret) - goto out; + goto err; /* Offset into the new buffer for cases of shared fbs between CRTCs */ offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; ret = BEGIN_LP_RING(6); if (ret) - goto out; + goto err_unpin; /* Can't queue multiple flips, so wait for the previous * one to finish before executing the next. @@ -7337,7 +7337,11 @@ static int intel_gen2_queue_flip(struct drm_device *dev, OUT_RING(obj->gtt_offset + offset); OUT_RING(0); /* aux display base address, unused */ ADVANCE_LP_RING(); -out: + return 0; + +err_unpin: + intel_unpin_fb_obj(obj); +err: return ret; } @@ -7354,14 +7358,14 @@ static int intel_gen3_queue_flip(struct drm_device *dev, ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); if (ret) - goto out; + goto err; /* Offset into the new buffer for cases of shared fbs between CRTCs */ offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; ret = BEGIN_LP_RING(6); if (ret) - goto out; + goto err_unpin; if (intel_crtc->plane) flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; @@ -7376,7 +7380,11 @@ static int intel_gen3_queue_flip(struct drm_device *dev, OUT_RING(MI_NOOP); ADVANCE_LP_RING(); -out: + return 0; + +err_unpin: + intel_unpin_fb_obj(obj); +err: return ret; } @@ -7392,11 +7400,11 @@ static int intel_gen4_queue_flip(struct drm_device *dev, ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); if (ret) - goto out; + goto err; ret = BEGIN_LP_RING(4); if (ret) - goto out; + goto err_unpin; /* i965+ uses the linear or tiled offsets from the * Display Registers (which do not change across a page-flip) @@ -7415,7 +7423,11 @@ static int intel_gen4_queue_flip(struct drm_device *dev, pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; OUT_RING(pf | pipesrc); ADVANCE_LP_RING(); -out: + return 0; + +err_unpin: + intel_unpin_fb_obj(obj); +err: return ret; } @@ -7431,11 +7443,11 @@ static int intel_gen6_queue_flip(struct drm_device *dev, ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); if (ret) - goto out; + goto err; ret = BEGIN_LP_RING(4); if (ret) - goto out; + goto err_unpin; OUT_RING(MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); @@ -7452,7 +7464,11 @@ static int intel_gen6_queue_flip(struct drm_device *dev, pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; OUT_RING(pf | pipesrc); ADVANCE_LP_RING(); -out: + return 0; + +err_unpin: + intel_unpin_fb_obj(obj); +err: return ret; } @@ -7474,18 +7490,22 @@ static int intel_gen7_queue_flip(struct drm_device *dev, ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) - goto out; + goto err; ret = intel_ring_begin(ring, 4); if (ret) - goto out; + goto err_unpin; intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19)); intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); intel_ring_emit(ring, (obj->gtt_offset)); intel_ring_emit(ring, (MI_NOOP)); intel_ring_advance(ring); -out: + return 0; + +err_unpin: + intel_unpin_fb_obj(obj); +err: return ret; } -- GitLab From 6148d57ee89d8ad89cd28a6f5803330c8601dfa6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 23 May 2012 14:02:00 +0200 Subject: [PATCH 1454/1799] drm/i915: fix up ivb plane 3 pageflips commit cb05d8dedefa3066bf5d74ef88c6ca6cf4bd1c87 upstream. Or at least plug another gapping hole. Apparrently hw desingers only moved the bit field, but did not bother ot re-enumerate the planes when adding support for a 3rd pipe. Discovered by i-g-t/flip_test. This may or may not fix the reference bugzilla, because that one smells like we have still larger fish to fry. v2: Fixup the impossible case to catch programming errors, noticed by Chris Wilson. References: https://bugs.freedesktop.org/show_bug.cgi?id=50069 Acked-by: Chris Wilson Tested-by: Eugeni Dodonov Eugeni Dodonov Signed-Off-by: Daniel Vetter Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 8 ++++++++ drivers/gpu/drm/i915/intel_display.c | 19 ++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index cd1a85a68809..eaf380602232 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -197,6 +197,14 @@ #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) +/* IVB has funny definitions for which plane to flip. */ +#define MI_DISPLAY_FLIP_IVB_PLANE_A (0 << 19) +#define MI_DISPLAY_FLIP_IVB_PLANE_B (1 << 19) +#define MI_DISPLAY_FLIP_IVB_SPRITE_A (2 << 19) +#define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) +#define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) +#define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) + #define MI_SET_CONTEXT MI_INSTR(0x18, 0) #define MI_MM_SPACE_GTT (1<<8) #define MI_MM_SPACE_PHYSICAL (0<<8) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c19bc62bc4ef..216504a6fb46 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7486,17 +7486,34 @@ static int intel_gen7_queue_flip(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; + uint32_t plane_bit = 0; int ret; ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) goto err; + switch(intel_crtc->plane) { + case PLANE_A: + plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_A; + break; + case PLANE_B: + plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_B; + break; + case PLANE_C: + plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_C; + break; + default: + WARN_ONCE(1, "unknown plane in flip command\n"); + ret = -ENODEV; + goto err; + } + ret = intel_ring_begin(ring, 4); if (ret) goto err_unpin; - intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19)); + intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); intel_ring_emit(ring, (obj->gtt_offset)); intel_ring_emit(ring, (MI_NOOP)); -- GitLab From e99e7f74856e4aaf57753b2698d590966fa4022a Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 22 Mar 2012 14:38:43 -0700 Subject: [PATCH 1455/1799] drm/i915: move NEEDS_FORCE_WAKE to i915_drv.c commit b7d84096d3c45f4e397e913da4ce24ec9a32022e upstream. It's only used by the main read/write functions, so we can keep it with them. Signed-off-by: Jesse Barnes Acked-by: Ben Widawsky Signed-off-by: Daniel Vetter Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_drv.c | 6 ++++++ drivers/gpu/drm/i915/i915_drv.h | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ae8a64f9f845..01cc14e653c4 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -993,6 +993,12 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL and additional rights"); +/* We give fast paths for the really cool registers */ +#define NEEDS_FORCE_WAKE(dev_priv, reg) \ + (((dev_priv)->info->gen >= 6) && \ + ((reg) < 0x40000) && \ + ((reg) != FORCEWAKE)) + #define __i915_read(x, y) \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ u##x val = 0; \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5fabc6c31fec..a8edd5379e74 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1450,12 +1450,6 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv); void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv); -/* We give fast paths for the really cool registers */ -#define NEEDS_FORCE_WAKE(dev_priv, reg) \ - (((dev_priv)->info->gen >= 6) && \ - ((reg) < 0x40000) && \ - ((reg) != FORCEWAKE)) - #define __i915_read(x, y) \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg); -- GitLab From 2406e63c32cf6bf83f7f188ba0cb96bfa94dc6ec Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 4 Jun 2012 11:18:15 +0200 Subject: [PATCH 1456/1799] drm/i915: hold forcewake around ring hw init commit b7884eb45ec98c0d34c7f49005ae9d4b4b4e38f6 upstream. Empirical evidence suggests that we need to: On at least one ivb machine when running the hangman i-g-t test, the rings don't properly initialize properly - the RING_START registers seems to be stuck at all zeros. Holding forcewake around this register init sequences makes chip reset reliable again. Note that this is not the first such issue: commit f01db988ef6f6c70a6cc36ee71e4a98a68901229 Author: Sean Paul Date: Fri Mar 16 12:43:22 2012 -0400 drm/i915: Add wait_for in init_ring_common added delay loops to make RING_START and RING_CTL initialization reliable on the blt ring at boot-up. So I guess it won't hurt if we do this unconditionally for all force_wake needing gpus. To avoid copy&pasting of the HAS_FORCE_WAKE check I've added a new intel_info bit for that. v2: Fixup missing commas in static struct and properly handling the error case in init_ring_common, both noticed by Jani Nikula. Reported-and-tested-by: Yang Guang Reviewed-by: Eugeni Dodonov Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=50522 Signed-Off-by: Daniel Vetter [bwh: Backported to 3.2: - drop changes to Haswell device information - NEEDS_FORCE_WAKE didn't refer to Valley View anyway] Signed-off-by: Ben Hutchings [jcristau: further context adjustments for 3.4] Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_drv.c | 6 +++++- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/intel_ringbuffer.c | 16 +++++++++++++--- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 01cc14e653c4..89f3d4aed664 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -224,6 +224,7 @@ static const struct intel_device_info intel_sandybridge_d_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_force_wake = 1, }; static const struct intel_device_info intel_sandybridge_m_info = { @@ -233,6 +234,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_force_wake = 1, }; static const struct intel_device_info intel_ivybridge_d_info = { @@ -241,6 +243,7 @@ static const struct intel_device_info intel_ivybridge_d_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_force_wake = 1, }; static const struct intel_device_info intel_ivybridge_m_info = { @@ -250,6 +253,7 @@ static const struct intel_device_info intel_ivybridge_m_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_force_wake = 1, }; static const struct pci_device_id pciidlist[] = { /* aka */ @@ -995,7 +999,7 @@ MODULE_LICENSE("GPL and additional rights"); /* We give fast paths for the really cool registers */ #define NEEDS_FORCE_WAKE(dev_priv, reg) \ - (((dev_priv)->info->gen >= 6) && \ + ((HAS_FORCE_WAKE((dev_priv)->dev)) && \ ((reg) < 0x40000) && \ ((reg) != FORCEWAKE)) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a8edd5379e74..e86f6fd3ed5b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -255,6 +255,7 @@ struct intel_device_info { u8 is_broadwater:1; u8 is_crestline:1; u8 is_ivybridge:1; + u8 has_force_wake:1; u8 has_fbc:1; u8 has_pipe_cxsr:1; u8 has_hotplug:1; @@ -1051,6 +1052,8 @@ struct drm_i915_file_private { #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) +#define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake) + #include "i915_trace.h" /** diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 302d3d54fb41..60db39df7a0e 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -249,10 +249,15 @@ u32 intel_ring_get_active_head(struct intel_ring_buffer *ring) static int init_ring_common(struct intel_ring_buffer *ring) { - drm_i915_private_t *dev_priv = ring->dev->dev_private; + struct drm_device *dev = ring->dev; + drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj = ring->obj; + int ret = 0; u32 head; + if (HAS_FORCE_WAKE(dev)) + gen6_gt_force_wake_get(dev_priv); + /* Stop the ring if it's running. */ I915_WRITE_CTL(ring, 0); I915_WRITE_HEAD(ring, 0); @@ -300,7 +305,8 @@ static int init_ring_common(struct intel_ring_buffer *ring) I915_READ_HEAD(ring), I915_READ_TAIL(ring), I915_READ_START(ring)); - return -EIO; + ret = -EIO; + goto out; } if (!drm_core_check_feature(ring->dev, DRIVER_MODESET)) @@ -312,7 +318,11 @@ static int init_ring_common(struct intel_ring_buffer *ring) ring->last_retired_head = -1; } - return 0; +out: + if (HAS_FORCE_WAKE(dev)) + gen6_gt_force_wake_put(dev_priv); + + return ret; } static int -- GitLab From feef244d1742de63b5a7292883276ee6e11a06c5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Mar 2012 13:07:05 +0100 Subject: [PATCH 1457/1799] drm/i915: Check VBIOS value for determining LVDS dual channel mode, too commit b03543857fd75876b96e10d4320b775e95041bb7 upstream. Currently i915 driver checks [PCH_]LVDS register bits to decide whether to set up the dual-link or the single-link mode. This relies implicitly on that BIOS initializes the register properly at boot. However, BIOS doesn't initialize it always. When the machine is booted with the closed lid, BIOS skips the LVDS reg initialization. This ends up in blank output on a machine with a dual-link LVDS when you open the lid after the boot. This patch adds a workaround for that problem by checking the initial LVDS register value in VBT. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=37742 Tested-By: Paulo Zanoni Reviewed-by: Rodrigo Vivi Reviewed-by: Adam Jackson Signed-off-by: Takashi Iwai Signed-off-by: Daniel Vetter Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_bios.c | 36 ++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_display.c | 30 ++++++++++++++++++----- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e86f6fd3ed5b..45c5cf83fae2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -406,6 +406,8 @@ typedef struct drm_i915_private { unsigned int lvds_use_ssc:1; unsigned int display_clock_mode:1; int lvds_ssc_freq; + unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */ + unsigned int lvds_val; /* used for checking LVDS channel mode */ struct { int rate; int lanes; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 3fe05245d3fc..a2c9e56c0c1a 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -174,6 +174,28 @@ get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data, return (struct lvds_dvo_timing *)(entry + dvo_timing_offset); } +/* get lvds_fp_timing entry + * this function may return NULL if the corresponding entry is invalid + */ +static const struct lvds_fp_timing * +get_lvds_fp_timing(const struct bdb_header *bdb, + const struct bdb_lvds_lfp_data *data, + const struct bdb_lvds_lfp_data_ptrs *ptrs, + int index) +{ + size_t data_ofs = (const u8 *)data - (const u8 *)bdb; + u16 data_size = ((const u16 *)data)[-1]; /* stored in header */ + size_t ofs; + + if (index >= ARRAY_SIZE(ptrs->ptr)) + return NULL; + ofs = ptrs->ptr[index].fp_timing_offset; + if (ofs < data_ofs || + ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size) + return NULL; + return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs); +} + /* Try to find integrated panel data */ static void parse_lfp_panel_data(struct drm_i915_private *dev_priv, @@ -183,6 +205,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, const struct bdb_lvds_lfp_data *lvds_lfp_data; const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; const struct lvds_dvo_timing *panel_dvo_timing; + const struct lvds_fp_timing *fp_timing; struct drm_display_mode *panel_fixed_mode; int i, downclock; @@ -244,6 +267,19 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, "Normal Clock %dKHz, downclock %dKHz\n", panel_fixed_mode->clock, 10*downclock); } + + fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data, + lvds_lfp_data_ptrs, + lvds_options->panel_type); + if (fp_timing) { + /* check the resolution, just to be sure */ + if (fp_timing->x_res == panel_fixed_mode->hdisplay && + fp_timing->y_res == panel_fixed_mode->vdisplay) { + dev_priv->bios_lvds_val = fp_timing->lvds_reg_val; + DRM_DEBUG_KMS("VBT initial LVDS value %x\n", + dev_priv->bios_lvds_val); + } + } } /* Try to find sdvo panel data */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 216504a6fb46..7cd342b01805 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -360,6 +360,27 @@ static const intel_limit_t intel_limits_ironlake_display_port = { .find_pll = intel_find_pll_ironlake_dp, }; +static bool is_dual_link_lvds(struct drm_i915_private *dev_priv, + unsigned int reg) +{ + unsigned int val; + + if (dev_priv->lvds_val) + val = dev_priv->lvds_val; + else { + /* BIOS should set the proper LVDS register value at boot, but + * in reality, it doesn't set the value when the lid is closed; + * we need to check "the value to be set" in VBT when LVDS + * register is uninitialized. + */ + val = I915_READ(reg); + if (!(val & ~LVDS_DETECTED)) + val = dev_priv->bios_lvds_val; + dev_priv->lvds_val = val; + } + return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP; +} + static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc, int refclk) { @@ -368,8 +389,7 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc, const intel_limit_t *limit; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) { + if (is_dual_link_lvds(dev_priv, PCH_LVDS)) { /* LVDS dual channel */ if (refclk == 100000) limit = &intel_limits_ironlake_dual_lvds_100m; @@ -397,8 +417,7 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) const intel_limit_t *limit; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) + if (is_dual_link_lvds(dev_priv, LVDS)) /* LVDS with dual channel */ limit = &intel_limits_g4x_dual_channel_lvds; else @@ -536,8 +555,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, * reliably set up different single/dual channel state, if we * even can. */ - if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) + if (is_dual_link_lvds(dev_priv, LVDS)) clock.p2 = limit->p2.p2_fast; else clock.p2 = limit->p2.p2_slow; -- GitLab From 392dcfdce12ee18d511c74132704c8749b149141 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Fri, 16 Mar 2012 12:43:22 -0400 Subject: [PATCH 1458/1799] drm/i915: Add wait_for in init_ring_common commit f01db988ef6f6c70a6cc36ee71e4a98a68901229 upstream. I have seen a number of "blt ring initialization failed" messages where the ctl or start registers are not the correct value. Upon further inspection, if the code just waited a little bit, it would read the correct value. Adding the wait_for to these reads should eliminate the issue. Signed-off-by: Sean Paul Reviewed-by: Ben Widawsky Signed-off-by: Daniel Vetter Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_ringbuffer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 60db39df7a0e..c17325ce3799 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -295,9 +295,9 @@ static int init_ring_common(struct intel_ring_buffer *ring) | RING_VALID); /* If the head is still not zero, the ring is dead */ - if ((I915_READ_CTL(ring) & RING_VALID) == 0 || - I915_READ_START(ring) != obj->gtt_offset || - (I915_READ_HEAD(ring) & HEAD_ADDR) != 0) { + if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 && + I915_READ_START(ring) == obj->gtt_offset && + (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) { DRM_ERROR("%s initialization failed " "ctl %08x head %08x tail %08x start %08x\n", ring->name, -- GitLab From b834417b9134b533c79a12ff134da40b982d6b2f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 17 Apr 2012 10:05:38 +0100 Subject: [PATCH 1459/1799] drm/i915: Wait for all pending operations to the fb before disabling the pipe commit 0f91128d88bbb8b0a8e7bb93df2c40680871d45a upstream. During modeset we have to disable the pipe to reconfigure its timings and maybe its size. Userspace may have queued up command buffers that depend upon the pipe running in a certain configuration and so the commands may become confused across the modeset. At the moment, we use a less than satisfactory kick-scanline-waits should the GPU hang during the modeset. It should be more reliable to wait for the pending operations to complete first, even though we still have a window for userspace to submit a broken command buffer during the modeset. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7cd342b01805..9a29fd67c3a1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2897,16 +2897,14 @@ static void intel_clear_scanline_wait(struct drm_device *dev) static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) { - struct drm_i915_gem_object *obj; - struct drm_i915_private *dev_priv; + struct drm_device *dev = crtc->dev; if (crtc->fb == NULL) return; - obj = to_intel_framebuffer(crtc->fb)->obj; - dev_priv = crtc->dev->dev_private; - wait_event(dev_priv->pending_flip_queue, - atomic_read(&obj->pending_flip) == 0); + mutex_lock(&dev->struct_mutex); + intel_finish_fb(crtc->fb); + mutex_unlock(&dev->struct_mutex); } static bool intel_crtc_driving_pch(struct drm_crtc *crtc) @@ -3372,23 +3370,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc) struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; struct drm_device *dev = crtc->dev; - /* Flush any pending WAITs before we disable the pipe. Note that - * we need to drop the struct_mutex in order to acquire it again - * during the lowlevel dpms routines around a couple of the - * operations. It does not look trivial nor desirable to move - * that locking higher. So instead we leave a window for the - * submission of further commands on the fb before we can actually - * disable it. This race with userspace exists anyway, and we can - * only rely on the pipe being disabled by userspace after it - * receives the hotplug notification and has flushed any pending - * batches. - */ - if (crtc->fb) { - mutex_lock(&dev->struct_mutex); - intel_finish_fb(crtc->fb); - mutex_unlock(&dev->struct_mutex); - } - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); -- GitLab From 1478f45496fca13f42fb7f940908b5cd3bee105c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 13 Apr 2012 15:51:51 +0200 Subject: [PATCH 1460/1799] drm/i915: don't pwrite tiled objects through the gtt commit c07496fa61f4c5cb2addd1c57f6b22fcaeea2eeb upstream. ... we will botch up the bit17 swizzling. Furthermore tiled pwrite is a (now) unused slowpath, so no one really cares. This fixes the last swizzling issues I have with i-g-t on my bit17 swizzling i915G. No regression, it's been broken since the dawn of gem, but it's nice for regression tracking when really _all_ i-g-t tests work. Actually this is not true, Chris Wilson noticed while reviewing this patch that the commit commit d9e86c0ee60f323e890484628f351bf50fa9a15d Author: Chris Wilson Date: Wed Nov 10 16:40:20 2010 +0000 drm/i915: Pipelined fencing [infrastructure] contained a functional change that broke things. Reviewed-by: Chris Wilson Signed-Off-by: Daniel Vetter [jcristau: adjust context for 3.4] Signed-off-by: Julien Cristau 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 0d1e4b7b4b99..723544557037 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -928,6 +928,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, } if (obj->gtt_space && + obj->tiling_mode == I915_TILING_NONE && obj->base.write_domain != I915_GEM_DOMAIN_CPU) { ret = i915_gem_object_pin(obj, 0, true); if (ret) -- GitLab From 3eafd581892bca5588762bb30d797c74f0441fac Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 17 Jul 2012 14:02:43 -0400 Subject: [PATCH 1461/1799] drm/radeon: fix up pll selection on DCE5/6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 26fe45a0a76f165425f332a5aaa298f149f9db22 upstream. Selecting ATOM_PPLL_INVALID should be equivalent as the DCPLL or PPLL0 are already programmed for the DISPCLK, but the preferred method is to always specify the PLL selected. SetPixelClock will check the parameters and skip the programming if the PLL is already set up. Signed-off-by: Alex Deucher Reviewed-by: Christian König Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_crtc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 19f4082c6181..ca2548b26500 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1533,7 +1533,11 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) * crtc virtual pixel clock. */ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { - if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk) + if (ASIC_IS_DCE5(rdev)) + return ATOM_DCPLL; + else if (ASIC_IS_DCE6(rdev)) + return ATOM_PPLL0; + else if (rdev->clock.dp_extclk) return ATOM_PPLL_INVALID; } } -- GitLab From 64d3c4a1eaca2134821407f7e4c3de9bf3d6aba9 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 28 May 2012 16:43:00 -0300 Subject: [PATCH 1462/1799] drm/i915: add some barriers when changing DIPs commit 9d9740f099f2eaf309c4c9cbc0d732507140db28 upstream. On IVB and older, we basically have two registers: the control and the data register. We write a few consecutitve times to the control register, and we need these writes to arrive exactly in the specified order. Also, when we're changing the data register, we need to guarantee that anything written to the control register already arrived (since changing the control register can change where the data register points to). Also, we need to make sure all the writes to the data register happen exactly in the specified order, and we also *can't* read the data register during this process, since reading and/or writing it will change the place it points to. So invoke the "better safe than sorry" rule and just be careful and put barriers everywhere :) On HSW we still have a control register that we write many times, but we have many data registers. Demanded-by: Chris Wilson Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter [bwh: Backported to 3.2: - There are only two write_infoframe functions to be modified - The other VIDEO_DIP_CTL writes are in entirely different functions] Signed-off-by: Ben Hutchings Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_hdmi.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index fb44e9d116e4..c60100d48ceb 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -138,14 +138,17 @@ static void i9xx_write_infoframe(struct drm_encoder *encoder, I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | val | port | flags); + mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(VIDEO_DIP_DATA, *data); data++; } + mmiowb(); flags |= intel_infoframe_flags(frame); I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | val | port | flags); + POSTING_READ(VIDEO_DIP_CTL); } static void ironlake_write_infoframe(struct drm_encoder *encoder, @@ -168,14 +171,17 @@ static void ironlake_write_infoframe(struct drm_encoder *encoder, I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags); + mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } + mmiowb(); flags |= intel_infoframe_flags(frame); I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags); + POSTING_READ(reg); } static void intel_set_infoframe(struct drm_encoder *encoder, struct dip_infoframe *frame) @@ -549,10 +555,13 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) if (!HAS_PCH_SPLIT(dev)) { intel_hdmi->write_infoframe = i9xx_write_infoframe; I915_WRITE(VIDEO_DIP_CTL, 0); + POSTING_READ(VIDEO_DIP_CTL); } else { intel_hdmi->write_infoframe = ironlake_write_infoframe; - for_each_pipe(i) + for_each_pipe(i) { I915_WRITE(TVIDEO_DIP_CTL(i), 0); + POSTING_READ(TVIDEO_DIP_CTL(i)); + } } drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); -- GitLab From df2a959c0e03e58f4efebbc49b6065014e3798e4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 11 May 2012 18:01:33 +0100 Subject: [PATCH 1463/1799] drm/i915: SDVO hotplug have different interrupt status bits for i915/i965/g4x commit 084b612ecf8e59973576b2f644e6949609c79375 upstream. Note that gen3 is the only platform where we've got the bit definitions right, hence the workaround of disabling sdvo hotplug support on i945g/gm is not due to misdiagnosis of broken hotplug irq handling ... Signed-off-by: Chris Wilson [danvet: add some blurb about sdvo hotplug fail on i945g/gm I've wondered about while reviewing.] Signed-off-by: Daniel Vetter [bwh: Backported to 3.2: - Adjust context - Handle all three cases in i915_driver_irq_postinstall() as there are not separate functions for gen3 and gen4+ - Carry on using IS_SDVOB() in intel_sdvo_init()] Signed-off-by: Ben Hutchings Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_irq.c | 20 ++++++++++++++++---- drivers/gpu/drm/i915/i915_reg.h | 10 ++++++++-- drivers/gpu/drm/i915/intel_sdvo.c | 17 +++++++++++++---- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 26c67a788770..54fcbc15007a 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2051,10 +2051,22 @@ static int i915_driver_irq_postinstall(struct drm_device *dev) hotplug_en |= HDMIC_HOTPLUG_INT_EN; if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) hotplug_en |= HDMID_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) - hotplug_en |= SDVOC_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) - hotplug_en |= SDVOB_HOTPLUG_INT_EN; + if (IS_G4X(dev)) { + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_G4X) + hotplug_en |= SDVOC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_G4X) + hotplug_en |= SDVOB_HOTPLUG_INT_EN; + } else if (IS_GEN4(dev)) { + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I965) + hotplug_en |= SDVOC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I965) + hotplug_en |= SDVOB_HOTPLUG_INT_EN; + } else { + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915) + hotplug_en |= SDVOC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915) + hotplug_en |= SDVOB_HOTPLUG_INT_EN; + } if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { hotplug_en |= CRT_HOTPLUG_INT_EN; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index eaf380602232..06c0fc3dcd63 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1491,14 +1491,20 @@ #define DPC_HOTPLUG_INT_STATUS (1 << 28) #define HDMID_HOTPLUG_INT_STATUS (1 << 27) #define DPD_HOTPLUG_INT_STATUS (1 << 27) +/* CRT/TV common between gen3+ */ #define CRT_HOTPLUG_INT_STATUS (1 << 11) #define TV_HOTPLUG_INT_STATUS (1 << 10) #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) #define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) #define CRT_HOTPLUG_MONITOR_MONO (2 << 8) #define CRT_HOTPLUG_MONITOR_NONE (0 << 8) -#define SDVOC_HOTPLUG_INT_STATUS (1 << 7) -#define SDVOB_HOTPLUG_INT_STATUS (1 << 6) +/* SDVO is different across gen3/4 */ +#define SDVOC_HOTPLUG_INT_STATUS_G4X (1 << 3) +#define SDVOB_HOTPLUG_INT_STATUS_G4X (1 << 2) +#define SDVOC_HOTPLUG_INT_STATUS_I965 (3 << 4) +#define SDVOB_HOTPLUG_INT_STATUS_I965 (3 << 2) +#define SDVOC_HOTPLUG_INT_STATUS_I915 (1 << 7) +#define SDVOB_HOTPLUG_INT_STATUS_I915 (1 << 6) /* SDVO port control */ #define SDVOB 0x61140 diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index b96e8c835c83..53cbcc3dced5 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2528,6 +2528,7 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *intel_encoder; struct intel_sdvo *intel_sdvo; + u32 hotplug_mask; int i; intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); @@ -2558,10 +2559,18 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) } } - if (IS_SDVOB(sdvo_reg)) - dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; - else - dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; + hotplug_mask = 0; + if (IS_G4X(dev)) { + hotplug_mask = IS_SDVOB(sdvo_reg) ? + SDVOB_HOTPLUG_INT_STATUS_G4X : SDVOC_HOTPLUG_INT_STATUS_G4X; + } else if (IS_GEN4(dev)) { + hotplug_mask = IS_SDVOB(sdvo_reg) ? + SDVOB_HOTPLUG_INT_STATUS_I965 : SDVOC_HOTPLUG_INT_STATUS_I965; + } else { + hotplug_mask = IS_SDVOB(sdvo_reg) ? + SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915; + } + dev_priv->hotplug_supported_mask |= hotplug_mask; drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); -- GitLab From 90877b10fb58e3ffa5add2a040d0f10d8ac67535 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 6 Aug 2012 17:06:03 -0400 Subject: [PATCH 1464/1799] drm/radeon: fix ordering in pll picking on dce4+ commit ecd67955fd4c8e66e4df312098989d5fa7da624c upstream. No functional change, but re-order the cases so they evaluate properly due to the way the DCE macros work. Noticed by kallisti5 on IRC. Signed-off-by: Alex Deucher Signed-off-by: Julien Cristau 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 ca2548b26500..15594a30ebd4 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1533,12 +1533,12 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) * crtc virtual pixel clock. */ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { - if (ASIC_IS_DCE5(rdev)) - return ATOM_DCPLL; + if (rdev->clock.dp_extclk) + return ATOM_PPLL_INVALID; else if (ASIC_IS_DCE6(rdev)) return ATOM_PPLL0; - else if (rdev->clock.dp_extclk) - return ATOM_PPLL_INVALID; + else if (ASIC_IS_DCE5(rdev)) + return ATOM_DCPLL; } } } -- GitLab From d1879e35935a07a67420fab66a02ae3b4148960f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Aug 2012 14:08:42 +0300 Subject: [PATCH 1465/1799] drm/i915: only enable sdvo hotplug irq if needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit fcbc50da7753b210b4442ca9abc4efbd4e481f6e upstream. Avoid constant wakeups caused by noisy irq lines when we don't even care about the irq. This should be particularly useful for i945g/gm where the hotplug has been disabled: commit 768b107e4b3be0acf6f58e914afe4f337c00932b Author: Daniel Vetter Date: Fri May 4 11:29:56 2012 +0200 drm/i915: disable sdvo hotplug on i945g/gm v2: While at it, remove the bogus hotplug_active read, and do not mask hotplug_active[0] before checking whether the irq is needed, per discussion with Daniel on IRC. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=38442 Tested-by: Dominik Köppl Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_sdvo.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 53cbcc3dced5..1b6b1570f4c2 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2570,7 +2570,6 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) hotplug_mask = IS_SDVOB(sdvo_reg) ? SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915; } - dev_priv->hotplug_supported_mask |= hotplug_mask; drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); @@ -2578,14 +2577,6 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) goto err; - /* Set up hotplug command - note paranoia about contents of reply. - * We assume that the hardware is in a sane state, and only touch - * the bits we think we understand. - */ - intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, - &intel_sdvo->hotplug_active, 2); - intel_sdvo->hotplug_active[0] &= ~0x3; - if (intel_sdvo_output_setup(intel_sdvo, intel_sdvo->caps.output_flags) != true) { DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n", @@ -2593,6 +2584,12 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) goto err; } + /* Only enable the hotplug irq if we need it, to work around noisy + * hotplug lines. + */ + if (intel_sdvo->hotplug_active[0]) + dev_priv->hotplug_supported_mask |= hotplug_mask; + intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg); /* Set the input timing to the screen. Assume always input 0. */ -- GitLab From 755a4897be165bc3b705ee6f83bda2253528b196 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 15 Sep 2012 09:41:57 +0100 Subject: [PATCH 1466/1799] drm/i915: Reduce a pin-leak BUG into a WARN commit 7e81a42e341a4f15d76624b7c02ffb21b085b56f upstream. Pin-leaks persist and we get the perennial bug reports of machine lockups to the BUG_ON(pin_count==MAX). If we instead loudly report that the object cannot be pinned at that time it should prevent the driver from locking up, and hopefully restore a semblance of working whilst still leaving us a OOPS to debug. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_gem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 723544557037..a230a93935bd 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3318,7 +3318,8 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, struct drm_i915_private *dev_priv = dev->dev_private; int ret; - BUG_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT); + if (WARN_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)) + return -EBUSY; WARN_ON(i915_verify_lists(dev)); if (obj->gtt_space != NULL) { -- GitLab From 0907a85413bbf79fcdb40c1d984d805f5840cbf9 Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Mon, 18 Jun 2012 19:03:38 -0300 Subject: [PATCH 1467/1799] drm/i915: prevent possible pin leak on error path commit ab3951eb74e7c33a2f5b7b64d72e82f1eea61571 upstream. We should not hit this under any sane conditions, but still, this does not looks right. Reported-by: Herton Ronaldo Krzesinski CC: Chris Wilson CC: Daniel Vetter Reviewed-by: Chris Wlison Signed-off-by: Eugeni Dodonov Signed-off-by: Daniel Vetter Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9a29fd67c3a1..db780cbad997 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7505,7 +7505,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, default: WARN_ONCE(1, "unknown plane in flip command\n"); ret = -ENODEV; - goto err; + goto err_unpin; } ret = intel_ring_begin(ring, 4); -- GitLab From 77f0c3b4713f398e28461c7bfd5fe69126a6edf7 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 3 Oct 2012 19:34:24 -0700 Subject: [PATCH 1468/1799] drm/i915: Fix GT_MODE default value commit f8f2ac9a76b0f80a6763ca316116a7bab8486997 upstream. I can't even find how I figured this might be needed anymore. But sure enough, the value I'm reading back on platforms doesn't match what the docs recommends. It seemed to fix Chris' GT1 in limited testing as well. Tested-by: Chris Wilson Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter [bwh: Backported to 3.2: open-code _MASKED_BIT_{ENABLE,DISABLE}] Signed-off-by: Ben Hutchings Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_display.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 06c0fc3dcd63..27a296a1415e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -445,6 +445,9 @@ # define VS_TIMER_DISPATCH (1 << 6) # define MI_FLUSH_ENABLE (1 << 12) +#define GEN6_GT_MODE 0x20d0 +#define GEN6_GT_MODE_HI (1 << 9) + #define GFX_MODE 0x02520 #define GFX_MODE_GEN7 0x0229c #define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index db780cbad997..db2163f2e328 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8620,6 +8620,11 @@ static void gen6_init_clock_gating(struct drm_device *dev) DISPPLANE_TRICKLE_FEED_DISABLE); intel_flush_display_plane(dev_priv, pipe); } + + /* The default value should be 0x200 according to docs, but the two + * platforms I checked have a 0 for this. (Maybe BIOS overrides?) */ + I915_WRITE(GEN6_GT_MODE, 0xffff << 16); + I915_WRITE(GEN6_GT_MODE, GEN6_GT_MODE_HI << 16 | GEN6_GT_MODE_HI); } static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv) -- GitLab From 1d35b4e271f56cad111b7150a1de57954e441765 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 2 Oct 2012 17:54:35 +0200 Subject: [PATCH 1469/1799] drm/i915: call drm_handle_vblank before finish_page_flip commit 74d44445afb9f50126eba052adeb89827cee88f3 upstream. ... since finish_page_flip needs the vblank timestamp generated in drm_handle_vblank. Somehow all the gmch platforms get it right, but all the pch platform irq handlers get is wrong. Hooray for copy& pasting! Currently this gets papered over by a gross hack in finish_page_flip. A second patch will remove that. Note that without this, the new timestamp sanity checks in flip_test occasionally get tripped up, hence the cc: stable tag. Reviewed-by: mario.kleiner@tuebingen.mpg.de Tested-by: Imre Deak Signed-off-by: Daniel Vetter [bwh: Backported to 3.2: no loop over pipes in ivybridge_irq_handler(), so make a similar change to that in ironlake_irq_handler()] Signed-off-by: Ben Hutchings Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_irq.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 54fcbc15007a..8bca2d2d804d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -530,6 +530,12 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) if (de_iir & DE_GSE_IVB) intel_opregion_gse_intr(dev); + if (de_iir & DE_PIPEA_VBLANK_IVB) + drm_handle_vblank(dev, 0); + + if (de_iir & DE_PIPEB_VBLANK_IVB) + drm_handle_vblank(dev, 1); + if (de_iir & DE_PLANEA_FLIP_DONE_IVB) { intel_prepare_page_flip(dev, 0); intel_finish_page_flip_plane(dev, 0); @@ -540,12 +546,6 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) intel_finish_page_flip_plane(dev, 1); } - if (de_iir & DE_PIPEA_VBLANK_IVB) - drm_handle_vblank(dev, 0); - - if (de_iir & DE_PIPEB_VBLANK_IVB) - drm_handle_vblank(dev, 1); - /* check event from PCH */ if (de_iir & DE_PCH_EVENT_IVB) { if (pch_iir & SDE_HOTPLUG_MASK_CPT) @@ -622,6 +622,12 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) if (de_iir & DE_GSE) intel_opregion_gse_intr(dev); + if (de_iir & DE_PIPEA_VBLANK) + drm_handle_vblank(dev, 0); + + if (de_iir & DE_PIPEB_VBLANK) + drm_handle_vblank(dev, 1); + if (de_iir & DE_PLANEA_FLIP_DONE) { intel_prepare_page_flip(dev, 0); intel_finish_page_flip_plane(dev, 0); @@ -632,12 +638,6 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) intel_finish_page_flip_plane(dev, 1); } - if (de_iir & DE_PIPEA_VBLANK) - drm_handle_vblank(dev, 0); - - if (de_iir & DE_PIPEB_VBLANK) - drm_handle_vblank(dev, 1); - /* check event from PCH */ if (de_iir & DE_PCH_EVENT) { if (pch_iir & hotplug_mask) -- GitLab From 7d17dc4851ad423a848e716354c9499c537fcb5b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 27 Sep 2012 21:25:58 +0100 Subject: [PATCH 1470/1799] drm/i915: Flush the pending flips on the CRTC before modification commit 5bb61643f6a70d48de9cfe91ad0fee0d618b6816 upstream. This was meant to be the purpose of the intel_crtc_wait_for_pending_flips() function which is called whilst preparing the CRTC for a modeset or before disabling. However, as Ville Syrjala pointed out, we set the pending flip notification on the old framebuffer that is no longer attached to the CRTC by the time we come to flush the pending operations. Instead, we can simply wait on the pending unpin work to be finished on this CRTC, knowning that the hardware has therefore finished modifying the registers, before proceeding with our direct access. Fixes i-g-t/flip_test on non-pch platforms. pch platforms simply schedule the flip immediately when the pipe is disabled, leading to other funny issues. Signed-off-by: Chris Wilson [danvet: Added i-g-t note and cc: stable] Signed-off-by: Daniel Vetter Signed-off-by: Julien Cristau Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index db2163f2e328..8e95c9432869 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2895,13 +2895,34 @@ static void intel_clear_scanline_wait(struct drm_device *dev) I915_WRITE_CTL(ring, tmp); } +static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long flags; + bool pending; + + if (atomic_read(&dev_priv->mm.wedged)) + return false; + + spin_lock_irqsave(&dev->event_lock, flags); + pending = to_intel_crtc(crtc)->unpin_work != NULL; + spin_unlock_irqrestore(&dev->event_lock, flags); + + return pending; +} + static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; if (crtc->fb == NULL) return; + wait_event(dev_priv->pending_flip_queue, + !intel_crtc_has_pending_flip(crtc)); + mutex_lock(&dev->struct_mutex); intel_finish_fb(crtc->fb); mutex_unlock(&dev->struct_mutex); @@ -7258,9 +7279,8 @@ static void do_intel_finish_page_flip(struct drm_device *dev, atomic_clear_mask(1 << intel_crtc->plane, &obj->pending_flip.counter); - if (atomic_read(&obj->pending_flip) == 0) - wake_up(&dev_priv->pending_flip_queue); + wake_up(&dev_priv->pending_flip_queue); schedule_work(&work->work); trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj); -- GitLab From 627e242990064e050cf09436c46d66ccf0f8a6b9 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 7 Jan 2013 10:27:13 +0100 Subject: [PATCH 1471/1799] Revert "drm/i915: no lvds quirk for Zotac ZDBOX SD ID12/ID13" commit 48e858340dae43189a4e55647f6eac736766f828 upstream. This reverts commit 9756fe38d10b2bf90c81dc4d2f17d5632e135364. The bogus lvds output is actually a lvds->hdmi bridge, which we don't really support. But unconditionally disabling it breaks some existing setups. Reported-by: John Tapsell References: http://permalink.gmane.org/gmane.comp.freedesktop.xorg.drivers.intel/17237 Signed-off-by: Daniel Vetter Cc: Luis Henriques Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_lvds.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 802fec20ff82..a8b28c493a85 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -777,14 +777,6 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "MS-7469"), }, }, - { - .callback = intel_no_lvds_dmi_callback, - .ident = "ZOTAC ZBOXSD-ID12/ID13", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"), - DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), - }, - }, { .callback = intel_no_lvds_dmi_callback, .ident = "Gigabyte GA-D525TUD", -- GitLab From a2d928ffc91d237f178d769943bc785f1a7f7435 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 30 Jul 2012 16:21:17 -0700 Subject: [PATCH 1472/1799] ceph: close old con before reopening on mds reconnect When we detect a mds session reset, close the old ceph_connection before reopening it. This ensures we clean up the old socket properly and keep the ceph_connection state correct. Signed-off-by: Sage Weil Reviewed-by: Alex Elder Reviewed-by: Yehuda Sadeh (cherry picked from commit a53aab645c82f0146e35684b34692c69b5118121) Signed-off-by: Greg Kroah-Hartman --- fs/ceph/mds_client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 7f1682da29a7..95708dd092f1 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2528,6 +2528,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, session->s_state = CEPH_MDS_SESSION_RECONNECTING; session->s_seq = 0; + ceph_con_close(&session->s_con); ceph_con_open(&session->s_con, CEPH_ENTITY_TYPE_MDS, mds, ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); -- GitLab From 95268c46ace4492b924abf6e82c6974c152bee29 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 21 Nov 2011 18:14:25 -0800 Subject: [PATCH 1473/1799] rbd: return errors for mapped but deleted snapshot When a snapshot is deleted, the OSD will return ENOENT when reading from it. This is normally interpreted as a hole by rbd, which will return zeroes. To minimize the time in which this can happen, stop requests early when we are notified that our snapshot no longer exists. [elder@inktank.com: updated __rbd_init_snaps_header() logic] Signed-off-by: Josh Durgin Reviewed-by: Alex Elder (cherry picked from commit e88a36ec961b8c1899c59c5e4ae35a318c0209d3) Signed-off-by: Greg Kroah-Hartman Conflicts: drivers/block/rbd.c --- drivers/block/rbd.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 7b331366a8a4..4f7ed7fa549e 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -174,9 +174,13 @@ struct rbd_device { /* protects updating the header */ struct rw_semaphore header_rwsem; + /* name of the snapshot this device reads from */ char snap_name[RBD_MAX_SNAP_NAME_LEN]; + /* id of the snapshot this device reads from */ u64 snap_id; /* current snapshot id */ - int read_only; + /* whether the snap_id this device reads from still exists */ + bool snap_exists; + int read_only; struct list_head node; @@ -590,6 +594,7 @@ static int rbd_header_set_snap(struct rbd_device *dev, u64 *size) else snapc->seq = 0; dev->snap_id = CEPH_NOSNAP; + dev->snap_exists = false; dev->read_only = 0; if (size) *size = header->image_size; @@ -598,6 +603,7 @@ static int rbd_header_set_snap(struct rbd_device *dev, u64 *size) if (ret < 0) goto done; dev->snap_id = snapc->seq; + dev->snap_exists = true; dev->read_only = 1; } @@ -1466,6 +1472,21 @@ static void rbd_rq_fn(struct request_queue *q) spin_unlock_irq(q->queue_lock); + if (rbd_dev->snap_id != CEPH_NOSNAP) { + bool snap_exists; + + down_read(&rbd_dev->header_rwsem); + snap_exists = rbd_dev->snap_exists; + up_read(&rbd_dev->header_rwsem); + + if (!snap_exists) { + dout("request for non-existent snapshot"); + spin_lock_irq(q->queue_lock); + __blk_end_request_all(rq, -ENXIO); + continue; + } + } + dout("%s 0x%x bytes at 0x%llx\n", do_write ? "write" : "read", size, blk_rq_pos(rq) * SECTOR_SIZE); @@ -2069,7 +2090,14 @@ static int __rbd_init_snaps_header(struct rbd_device *rbd_dev) cur_id = rbd_dev->header.snapc->snaps[i - 1]; if (!i || old_snap->id < cur_id) { - /* old_snap->id was skipped, thus was removed */ + /* + * old_snap->id was skipped, thus was + * removed. If this rbd_dev is mapped to + * the removed snapshot, record that it no + * longer exists, to prevent further I/O. + */ + if (rbd_dev->snap_id == old_snap->id) + rbd_dev->snap_exists = false; __rbd_remove_snap_dev(rbd_dev, old_snap); continue; } -- GitLab From 7272b7d3db9160716acce4ae387cf98fd24ff820 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 21 Nov 2011 17:13:54 -0800 Subject: [PATCH 1474/1799] rbd: only reset capacity when pointing to head Snapshots cannot be resized, and the new capacity of head should not be reflected by the snapshot. Signed-off-by: Josh Durgin Reviewed-by: Alex Elder (cherry picked from commit 474ef7ce832d471148f63a9d07f67fc5564834f1) Signed-off-by: Greg Kroah-Hartman --- drivers/block/rbd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 4f7ed7fa549e..52a045b11d4e 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1721,7 +1721,12 @@ static int __rbd_update_snaps(struct rbd_device *rbd_dev) return ret; /* resized? */ - set_capacity(rbd_dev->disk, h.image_size / SECTOR_SIZE); + if (rbd_dev->snap_id == CEPH_NOSNAP) { + sector_t size = (sector_t) h.image_size / SECTOR_SIZE; + + dout("setting size to %llu sectors", (unsigned long long) size); + set_capacity(rbd_dev->disk, size); + } down_write(&rbd_dev->header_rwsem); -- GitLab From 929333aa674e6c1b3026a3b3c8f27907e9a7de5b Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 5 Dec 2011 10:35:04 -0800 Subject: [PATCH 1475/1799] rbd: expose the correct size of the device in sysfs If an image was mapped to a snapshot, the size of the head version would be shown. Protect capacity with header_rwsem, since it may change. Signed-off-by: Josh Durgin Reviewed-by: Alex Elder (cherry picked from commit a51aa0c042fa39946dd017d5f91a073300a71577) Signed-off-by: Greg Kroah-Hartman --- drivers/block/rbd.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 52a045b11d4e..0ac989cf240e 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1720,6 +1720,8 @@ static int __rbd_update_snaps(struct rbd_device *rbd_dev) if (ret < 0) return ret; + down_write(&rbd_dev->header_rwsem); + /* resized? */ if (rbd_dev->snap_id == CEPH_NOSNAP) { sector_t size = (sector_t) h.image_size / SECTOR_SIZE; @@ -1728,8 +1730,6 @@ static int __rbd_update_snaps(struct rbd_device *rbd_dev) set_capacity(rbd_dev->disk, size); } - down_write(&rbd_dev->header_rwsem); - snap_seq = rbd_dev->header.snapc->seq; if (rbd_dev->header.total_snaps && rbd_dev->header.snapc->snaps[0] == snap_seq) @@ -1844,8 +1844,13 @@ static ssize_t rbd_size_show(struct device *dev, struct device_attribute *attr, char *buf) { struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); + sector_t size; + + down_read(&rbd_dev->header_rwsem); + size = get_capacity(rbd_dev->disk); + up_read(&rbd_dev->header_rwsem); - return sprintf(buf, "%llu\n", (unsigned long long)rbd_dev->header.image_size); + return sprintf(buf, "%llu\n", (unsigned long long) size * SECTOR_SIZE); } static ssize_t rbd_major_show(struct device *dev, -- GitLab From 894910deddfe36e66079bea42ae9d728b3f4b5cc Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 5 Dec 2011 10:41:28 -0800 Subject: [PATCH 1476/1799] rbd: set image size when header is updated The image may have been resized. Signed-off-by: Josh Durgin Reviewed-by: Alex Elder (cherry picked from commit 93a24e084d67ba2fcb9a4c289135825b623ec864) Signed-off-by: Greg Kroah-Hartman --- drivers/block/rbd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 0ac989cf240e..1dcfd0920871 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1741,6 +1741,7 @@ static int __rbd_update_snaps(struct rbd_device *rbd_dev) kfree(rbd_dev->header.snap_names); kfree(rbd_dev->header.snap_sizes); + rbd_dev->header.image_size = h.image_size; rbd_dev->header.total_snaps = h.total_snaps; rbd_dev->header.snapc = h.snapc; rbd_dev->header.snap_names = h.snap_names; -- GitLab From fc5eb627a897ac41581692abf60ffea874df2e55 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 5 Dec 2011 14:03:05 -0800 Subject: [PATCH 1477/1799] rbd: use reference counting for the snap context This prevents a race between requests with a given snap context and header updates that free it. The osd client was already expecting the snap context to be reference counted, since it get()s it in ceph_osdc_build_request and put()s it when the request completes. Also remove the second down_read()/up_read() on header_rwsem in rbd_do_request, which wasn't actually preventing this race or protecting any other data. Signed-off-by: Josh Durgin Reviewed-by: Alex Elder (cherry picked from commit d1d25646543134d756a02ffe4e02073faa761f2c) Signed-off-by: Greg Kroah-Hartman --- drivers/block/rbd.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 1dcfd0920871..dc26c2e48d83 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -615,7 +615,7 @@ static int rbd_header_set_snap(struct rbd_device *dev, u64 *size) static void rbd_header_free(struct rbd_image_header *header) { - kfree(header->snapc); + ceph_put_snap_context(header->snapc); kfree(header->snap_names); kfree(header->snap_sizes); } @@ -893,13 +893,10 @@ static int rbd_do_request(struct request *rq, dout("rbd_do_request obj=%s ofs=%lld len=%lld\n", obj, len, ofs); - down_read(&dev->header_rwsem); - osdc = &dev->rbd_client->client->osdc; req = ceph_osdc_alloc_request(osdc, flags, snapc, ops, false, GFP_NOIO, pages, bio); if (!req) { - up_read(&dev->header_rwsem); ret = -ENOMEM; goto done_pages; } @@ -934,7 +931,6 @@ static int rbd_do_request(struct request *rq, snapc, &mtime, req->r_oid, req->r_oid_len); - up_read(&dev->header_rwsem); if (linger_req) { ceph_osdc_set_request_linger(osdc, req); @@ -1446,6 +1442,7 @@ static void rbd_rq_fn(struct request_queue *q) u64 ofs; int num_segs, cur_seg = 0; struct rbd_req_coll *coll; + struct ceph_snap_context *snapc; /* peek at request from block layer */ if (!rq) @@ -1472,21 +1469,20 @@ static void rbd_rq_fn(struct request_queue *q) spin_unlock_irq(q->queue_lock); - if (rbd_dev->snap_id != CEPH_NOSNAP) { - bool snap_exists; + down_read(&rbd_dev->header_rwsem); - down_read(&rbd_dev->header_rwsem); - snap_exists = rbd_dev->snap_exists; + if (rbd_dev->snap_id != CEPH_NOSNAP && !rbd_dev->snap_exists) { up_read(&rbd_dev->header_rwsem); - - if (!snap_exists) { - dout("request for non-existent snapshot"); - spin_lock_irq(q->queue_lock); - __blk_end_request_all(rq, -ENXIO); - continue; - } + dout("request for non-existent snapshot"); + spin_lock_irq(q->queue_lock); + __blk_end_request_all(rq, -ENXIO); + continue; } + snapc = ceph_get_snap_context(rbd_dev->header.snapc); + + up_read(&rbd_dev->header_rwsem); + dout("%s 0x%x bytes at 0x%llx\n", do_write ? "write" : "read", size, blk_rq_pos(rq) * SECTOR_SIZE); @@ -1496,6 +1492,7 @@ static void rbd_rq_fn(struct request_queue *q) if (!coll) { spin_lock_irq(q->queue_lock); __blk_end_request_all(rq, -ENOMEM); + ceph_put_snap_context(snapc); continue; } @@ -1519,7 +1516,7 @@ static void rbd_rq_fn(struct request_queue *q) /* init OSD command: write or read */ if (do_write) rbd_req_write(rq, rbd_dev, - rbd_dev->header.snapc, + snapc, ofs, op_size, bio, coll, cur_seg); @@ -1542,6 +1539,8 @@ static void rbd_rq_fn(struct request_queue *q) if (bp) bio_pair_release(bp); spin_lock_irq(q->queue_lock); + + ceph_put_snap_context(snapc); } } @@ -1737,7 +1736,7 @@ static int __rbd_update_snaps(struct rbd_device *rbd_dev) if head moves */ follow_seq = 1; - kfree(rbd_dev->header.snapc); + ceph_put_snap_context(rbd_dev->header.snapc); kfree(rbd_dev->header.snap_names); kfree(rbd_dev->header.snap_sizes); -- GitLab From ca9a5e33a97a965378a2a0387fd8acf3a0144950 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 5 Dec 2011 18:10:44 -0800 Subject: [PATCH 1478/1799] rbd: send header version when notifying Previously the original header version was sent. Now, we update it when the header changes. Signed-off-by: Josh Durgin Reviewed-by: Alex Elder (cherry picked from commit a71b891bc7d77a070e723c8c53d1dd73cf931555) Signed-off-by: Greg Kroah-Hartman --- drivers/block/rbd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index dc26c2e48d83..52e295defb98 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1195,7 +1195,7 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev, if (ret < 0) return ret; - ops[0].watch.ver = cpu_to_le64(dev->header.obj_version); + ops[0].watch.ver = cpu_to_le64(ver); ops[0].watch.cookie = notify_id; ops[0].watch.flag = 0; @@ -1215,6 +1215,7 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev, static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) { struct rbd_device *dev = (struct rbd_device *)data; + u64 hver; int rc; if (!dev) @@ -1224,12 +1225,13 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) notify_id, (int)opcode); mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); rc = __rbd_update_snaps(dev); + hver = dev->header.obj_version; mutex_unlock(&ctl_mutex); if (rc) pr_warning(RBD_DRV_NAME "%d got notification but failed to " " update snaps: %d\n", dev->major, rc); - rbd_req_sync_notify_ack(dev, ver, notify_id, dev->obj_md_name); + rbd_req_sync_notify_ack(dev, hver, notify_id, dev->obj_md_name); } /* @@ -1740,6 +1742,7 @@ static int __rbd_update_snaps(struct rbd_device *rbd_dev) kfree(rbd_dev->header.snap_names); kfree(rbd_dev->header.snap_sizes); + rbd_dev->header.obj_version = h.obj_version; rbd_dev->header.image_size = h.image_size; rbd_dev->header.total_snaps = h.total_snaps; rbd_dev->header.snapc = h.snapc; -- GitLab From 2c130889f540f0bc6bc866d436b2ec3a23ea8f2b Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 21 Aug 2012 15:55:25 -0700 Subject: [PATCH 1479/1799] ceph: tolerate (and warn on) extraneous dentry from mds If the MDS gives us a dentry and we weren't prepared to handle it, WARN_ON_ONCE instead of crashing. Reported-by: Yan, Zheng Signed-off-by: Sage Weil Reviewed-by: Alex Elder (cherry picked from commit 6c5e50fa614fea5325a2973be06f7ec6f1055316) Signed-off-by: Greg Kroah-Hartman --- fs/ceph/inode.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 9fff9f3b17e4..4b5762ef7c2b 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -992,11 +992,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, if (rinfo->head->is_dentry) { struct inode *dir = req->r_locked_dir; - err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, - session, req->r_request_started, -1, - &req->r_caps_reservation); - if (err < 0) - return err; + if (dir) { + err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, + session, req->r_request_started, -1, + &req->r_caps_reservation); + if (err < 0) + return err; + } else { + WARN_ON_ONCE(1); + } } /* @@ -1004,6 +1008,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, * will have trouble splicing in the virtual snapdir later */ if (rinfo->head->is_dentry && !req->r_aborted && + req->r_locked_dir && (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name, fsc->mount_options->snapdir_name, req->r_dentry->d_name.len))) { -- GitLab From a871375b5548cbcd28c9b97040da7f6470a96a72 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 10 Aug 2012 13:12:07 -0700 Subject: [PATCH 1480/1799] rbd: drop dev reference on error in rbd_open() If a read-only rbd device is opened for writing in rbd_open(), it returns without dropping the just-acquired device reference. Fix this by moving the read-only check before getting the reference. Signed-off-by: Alex Elder Reviewed-by: Yehuda Sadeh Reviewed-by: Josh Durgin (cherry picked from commit 340c7a2b2c9a2da640af28a8c196356484ac8b50) Signed-off-by: Greg Kroah-Hartman --- drivers/block/rbd.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 52e295defb98..c05a4ab47e5a 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -250,13 +250,12 @@ static int rbd_open(struct block_device *bdev, fmode_t mode) { struct rbd_device *rbd_dev = bdev->bd_disk->private_data; - rbd_get_dev(rbd_dev); - - set_device_ro(bdev, rbd_dev->read_only); - if ((mode & FMODE_WRITE) && rbd_dev->read_only) return -EROFS; + rbd_get_dev(rbd_dev); + set_device_ro(bdev, rbd_dev->read_only); + return 0; } -- GitLab From b4659d8e7001600f06080f2b3f1922d0f4d96478 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 24 Sep 2012 21:01:02 -0700 Subject: [PATCH 1481/1799] ceph: propagate layout error on osd request creation If we are creating an osd request and get an invalid layout, return an EINVAL to the caller. We switch up the return to have an error code instead of NULL implying -ENOMEM. Signed-off-by: Sage Weil Reviewed-by: Alex Elder (cherry picked from commit 6816282dab3a72efe8c0d182c1bc2960d87f4322) Signed-off-by: Greg Kroah-Hartman --- fs/ceph/addr.c | 8 ++++---- fs/ceph/file.c | 4 ++-- net/ceph/osd_client.c | 15 +++++++++------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 32ee086c259b..e009fde39cf6 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -308,8 +308,8 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max) NULL, 0, ci->i_truncate_seq, ci->i_truncate_size, NULL, false, 1, 0); - if (!req) - return -ENOMEM; + if (IS_ERR(req)) + return PTR_ERR(req); /* build page vector */ nr_pages = len >> PAGE_CACHE_SHIFT; @@ -831,8 +831,8 @@ static int ceph_writepages_start(struct address_space *mapping, ci->i_truncate_size, &inode->i_mtime, true, 1, 0); - if (!req) { - rc = -ENOMEM; + if (IS_ERR(req)) { + rc = PTR_ERR(req); unlock_page(page); break; } diff --git a/fs/ceph/file.c b/fs/ceph/file.c index ed72428d9c75..9ce3a4bd4d1c 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -529,8 +529,8 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data, do_sync, ci->i_truncate_seq, ci->i_truncate_size, &mtime, false, 2, page_align); - if (!req) - return -ENOMEM; + if (IS_ERR(req)) + return PTR_ERR(req); if (file->f_flags & O_DIRECT) { pages = ceph_get_direct_page_vector(data, num_pages, false); diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index a79dbae3ea90..37a9f1e61241 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -461,6 +461,7 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, { struct ceph_osd_req_op ops[3]; struct ceph_osd_request *req; + int r; ops[0].op = opcode; ops[0].extent.truncate_seq = truncate_seq; @@ -479,10 +480,12 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, use_mempool, GFP_NOFS, NULL, NULL); if (!req) - return NULL; + return ERR_PTR(-ENOMEM); /* calculate max write size */ - calc_layout(osdc, vino, layout, off, plen, req, ops); + r = calc_layout(osdc, vino, layout, off, plen, req, ops); + if (r < 0) + return ERR_PTR(r); req->r_file_layout = *layout; /* keep a copy */ /* in case it differs from natural (file) alignment that @@ -1925,8 +1928,8 @@ int ceph_osdc_readpages(struct ceph_osd_client *osdc, CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ, NULL, 0, truncate_seq, truncate_size, NULL, false, 1, page_align); - if (!req) - return -ENOMEM; + if (IS_ERR(req)) + return PTR_ERR(req); /* it may be a short read due to an object boundary */ req->r_pages = pages; @@ -1968,8 +1971,8 @@ int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino, snapc, do_sync, truncate_seq, truncate_size, mtime, nofail, 1, page_align); - if (!req) - return -ENOMEM; + if (IS_ERR(req)) + return PTR_ERR(req); /* it may be a short write due to an object boundary */ req->r_pages = pages; -- GitLab From 1c0bd4af222ba3a54bf3ba489127323079d0816d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 7 Dec 2012 19:50:07 -0600 Subject: [PATCH 1482/1799] libceph: socket can close in any connection state A connection's socket can close for any reason, independent of the state of the connection (and without irrespective of the connection mutex). As a result, the connectino can be in pretty much any state at the time its socket is closed. Handle those other cases at the top of con_work(). Pull this whole block of code into a separate function to reduce the clutter. Signed-off-by: Alex Elder Reviewed-by: Sage Weil (cherry picked from commit 7bb21d68c535ad8be38e14a715632ae398b37ac1) Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 47 ++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index aa71a67450af..429f3bcb56a3 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2258,6 +2258,35 @@ static void queue_con(struct ceph_connection *con) } } +static bool con_sock_closed(struct ceph_connection *con) +{ + if (!test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) + return false; + +#define CASE(x) \ + case CON_STATE_ ## x: \ + con->error_msg = "socket closed (con state " #x ")"; \ + break; + + switch (con->state) { + CASE(CLOSED); + CASE(PREOPEN); + CASE(CONNECTING); + CASE(NEGOTIATING); + CASE(OPEN); + CASE(STANDBY); + default: + pr_warning("%s con %p unrecognized state %lu\n", + __func__, con, con->state); + con->error_msg = "unrecognized con state"; + BUG(); + break; + } +#undef CASE + + return true; +} + /* * Do some work on a connection. Drop a connection ref when we're done. */ @@ -2269,24 +2298,8 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: - if (test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) { - switch (con->state) { - case CON_STATE_CONNECTING: - con->error_msg = "connection failed"; - break; - case CON_STATE_NEGOTIATING: - con->error_msg = "negotiation failed"; - break; - case CON_STATE_OPEN: - con->error_msg = "socket closed"; - break; - default: - dout("unrecognized con state %d\n", (int)con->state); - con->error_msg = "unrecognized con state"; - BUG(); - } + if (con_sock_closed(con)) goto fault; - } if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) { dout("con_work %p backing off\n", con); -- GitLab From 6ea5c964ecc4037d4ae56694982be253bd821685 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 14 Dec 2012 16:47:41 -0600 Subject: [PATCH 1483/1799] libceph: report connection fault with warning When a connection's socket disconnects, or if there's a protocol error of some kind on the connection, a fault is signaled and the connection is reset (closed and reopened, basically). We currently get an error message on the log whenever this occurs. A ceph connection will attempt to reestablish a socket connection repeatedly if a fault occurs. This means that these error messages will get repeatedly added to the log, which is undesirable. Change the error message to be a warning, so they don't get logged by default. Signed-off-by: Alex Elder Reviewed-by: Sage Weil (cherry picked from commit 28362986f8743124b3a0fda20a8ed3e80309cce1) Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 429f3bcb56a3..0ff14e88586f 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2365,7 +2365,7 @@ static void con_work(struct work_struct *work) static void ceph_fault(struct ceph_connection *con) __releases(con->mutex) { - pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), + pr_warning("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg); dout("fault %p state %lu to peer %s\n", con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); -- GitLab From 281c5d9e31a2411055bc750d81dd38d11131648e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 6 Dec 2012 07:22:04 -0600 Subject: [PATCH 1484/1799] libceph: init osd->o_node in create_osd() The red-black node node in the ceph osd structure is not initialized in create_osd(). Because this node can be the subject of a RB_EMPTY_NODE() call later on, we should ensure the node is initialized properly for that. Add a call to RB_CLEAR_NODE() initialize it. Signed-off-by: Alex Elder Reviewed-by: Sage Weil (cherry picked from commit f407731d12214e7686819018f3a1e9d7b6f83a02) Signed-off-by: Greg Kroah-Hartman --- net/ceph/osd_client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 37a9f1e61241..0b3fbdd7100a 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -645,6 +645,7 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum) atomic_set(&osd->o_ref, 1); osd->o_osdc = osdc; osd->o_osd = onum; + RB_CLEAR_NODE(&osd->o_node); INIT_LIST_HEAD(&osd->o_requests); INIT_LIST_HEAD(&osd->o_linger_requests); INIT_LIST_HEAD(&osd->o_osd_lru); -- GitLab From 76fb865bcfeba57652edf054fd36aeed38ba5ceb Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Dec 2012 12:23:48 -0600 Subject: [PATCH 1485/1799] libceph: init event->node in ceph_osdc_create_event() The red-black node node in the ceph osd event structure is not initialized in create_osdc_create_event(). Because this node can be the subject of a RB_EMPTY_NODE() call later on, we should ensure the node is initialized properly for that. Signed-off-by: Alex Elder Reviewed-by: Sage Weil (cherry picked from commit 3ee5234df68d253c415ba4f2db72ad250d9c21a9) Signed-off-by: Greg Kroah-Hartman --- net/ceph/osd_client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 0b3fbdd7100a..6af3d2af31c8 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -1598,6 +1598,7 @@ int ceph_osdc_create_event(struct ceph_osd_client *osdc, event->data = data; event->osdc = osdc; INIT_LIST_HEAD(&event->osd_node); + RB_CLEAR_NODE(&event->node); kref_init(&event->kref); /* one ref for us */ kref_get(&event->kref); /* one ref for the caller */ init_completion(&event->completion); -- GitLab From 1d2522a000b6f6a0c836d586bbb39bacaae9b390 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Dec 2012 12:23:48 -0600 Subject: [PATCH 1486/1799] libceph: don't use rb_init_node() in ceph_osdc_alloc_request() The red-black node in the ceph osd request structure is initialized in ceph_osdc_alloc_request() using rbd_init_node(). We do need to initialize this, because in __unregister_request() we call RB_EMPTY_NODE(), which expects the node it's checking to have been initialized. But rb_init_node() is apparently overkill, and may in fact be on its way out. So use RB_CLEAR_NODE() instead. For a little more background, see this commit: 4c199a93 rbtree: empty nodes have no color" Signed-off-by: Alex Elder Reviewed-by: Sage Weil (cherry picked from commit a978fa20fb657548561dddbfb605fe43654f0825) Signed-off-by: Greg Kroah-Hartman --- net/ceph/osd_client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 6af3d2af31c8..2c3951628872 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -221,6 +221,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, kref_init(&req->r_kref); init_completion(&req->r_completion); init_completion(&req->r_safe_completion); + RB_CLEAR_NODE(&req->r_node); INIT_LIST_HEAD(&req->r_unsafe_item); INIT_LIST_HEAD(&req->r_linger_item); INIT_LIST_HEAD(&req->r_linger_osd); -- GitLab From 0d3b9fff8bc11bc7d745c6b34c098b1c548fec65 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 6 Dec 2012 07:22:04 -0600 Subject: [PATCH 1487/1799] libceph: register request before unregister linger In kick_requests(), we need to register the request before we unregister the linger request. Otherwise the unregister will reset the request's osd pointer to NULL. Signed-off-by: Alex Elder Reviewed-by: Sage Weil (cherry picked from commit c89ce05e0c5a01a256100ac6a6019f276bdd1ca6) Signed-off-by: Greg Kroah-Hartman --- net/ceph/osd_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 2c3951628872..93845f23d3f7 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -1364,8 +1364,8 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) dout("kicking lingering %p tid %llu osd%d\n", req, req->r_tid, req->r_osd ? req->r_osd->o_osd : -1); - __unregister_linger_request(osdc, req); __register_request(osdc, req); + __unregister_linger_request(osdc, req); } mutex_unlock(&osdc->request_mutex); -- GitLab From a9ded438f7c08525df2ce19e8aeb112efd3090c9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Dec 2012 15:52:36 -0600 Subject: [PATCH 1488/1799] libceph: move linger requests sooner in kick_requests() The kick_requests() function is called by ceph_osdc_handle_map() when an osd map change has been indicated. Its purpose is to re-queue any request whose target osd is different from what it was when it was originally sent. It is structured as two loops, one for incomplete but registered requests, and a second for handling completed linger requests. As a special case, in the first loop if a request marked to linger has not yet completed, it is moved from the request list to the linger list. This is as a quick and dirty way to have the second loop handle sending the request along with all the other linger requests. Because of the way it's done now, however, this quick and dirty solution can result in these incomplete linger requests never getting re-sent as desired. The problem lies in the fact that the second loop only arranges for a linger request to be sent if it appears its target osd has changed. This is the proper handling for *completed* linger requests (it avoids issuing the same linger request twice to the same osd). But although the linger requests added to the list in the first loop may have been sent, they have not yet completed, so they need to be re-sent regardless of whether their target osd has changed. The first required fix is we need to avoid calling __map_request() on any incomplete linger request. Otherwise the subsequent __map_request() call in the second loop will find the target osd has not changed and will therefore not re-send the request. Second, we need to be sure that a sent but incomplete linger request gets re-sent. If the target osd is the same with the new osd map as it was when the request was originally sent, this won't happen. This can be fixed through careful handling when we move these requests from the request list to the linger list, by unregistering the request *before* it is registered as a linger request. This works because a side-effect of unregistering the request is to make the request's r_osd pointer be NULL, and *that* will ensure the second loop actually re-sends the linger request. Processing of such a request is done at that point, so continue with the next one once it's been moved. Signed-off-by: Alex Elder Reviewed-by: Sage Weil (cherry picked from commit ab60b16d3c31b9bd9fd5b39f97dc42c52a50b67d) Signed-off-by: Greg Kroah-Hartman --- net/ceph/osd_client.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 93845f23d3f7..c42ef9f78550 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -1320,6 +1320,24 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) for (p = rb_first(&osdc->requests); p; ) { req = rb_entry(p, struct ceph_osd_request, r_node); p = rb_next(p); + + /* + * For linger requests that have not yet been + * registered, move them to the linger list; they'll + * be sent to the osd in the loop below. Unregister + * the request before re-registering it as a linger + * request to ensure the __map_request() below + * will decide it needs to be sent. + */ + if (req->r_linger && list_empty(&req->r_linger_item)) { + dout("%p tid %llu restart on osd%d\n", + req, req->r_tid, + req->r_osd ? req->r_osd->o_osd : -1); + __unregister_request(osdc, req); + __register_linger_request(osdc, req); + continue; + } + err = __map_request(osdc, req, force_resend); if (err < 0) continue; /* error */ @@ -1334,17 +1352,6 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) req->r_flags |= CEPH_OSD_FLAG_RETRY; } } - if (req->r_linger && list_empty(&req->r_linger_item)) { - /* - * register as a linger so that we will - * re-submit below and get a new tid - */ - dout("%p tid %llu restart on osd%d\n", - req, req->r_tid, - req->r_osd ? req->r_osd->o_osd : -1); - __register_linger_request(osdc, req); - __unregister_request(osdc, req); - } } list_for_each_entry_safe(req, nreq, &osdc->req_linger, @@ -1352,6 +1359,7 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) dout("linger req=%p req->r_osd=%p\n", req, req->r_osd); err = __map_request(osdc, req, force_resend); + dout("__map_request returned %d\n", err); if (err == 0) continue; /* no change and no osd was specified */ if (err < 0) -- GitLab From 1cc023b2653ad66b58970460165d0859943f41e7 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 26 Dec 2012 14:31:40 -0600 Subject: [PATCH 1489/1799] libceph: always reset osds when kicking When ceph_osdc_handle_map() is called to process a new osd map, kick_requests() is called to ensure all affected requests are updated if necessary to reflect changes in the osd map. This happens in two cases: whenever an incremental map update is processed; and when a full map update (or the last one if there is more than one) gets processed. In the former case, the kick_requests() call is followed immediately by a call to reset_changed_osds() to ensure any connections to osds affected by the map change are reset. But for full map updates this isn't done. Both cases should be doing this osd reset. Rather than duplicating the reset_changed_osds() call, move it into the end of kick_requests(). Signed-off-by: Alex Elder Reviewed-by: Sage Weil (cherry picked from commit e6d50f67a6b1a6252a616e6e629473b5c4277218) Signed-off-by: Greg Kroah-Hartman --- net/ceph/osd_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index c42ef9f78550..e03202bdc270 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -1306,7 +1306,7 @@ static void reset_changed_osds(struct ceph_osd_client *osdc) * Requeue requests whose mapping to an OSD has changed. If requests map to * no osd, request a new map. * - * Caller should hold map_sem for read and request_mutex. + * Caller should hold map_sem for read. */ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) { @@ -1381,6 +1381,7 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) dout("%d requests for down osds, need new map\n", needmap); ceph_monc_request_next_osdmap(&osdc->client->monc); } + reset_changed_osds(osdc); } @@ -1437,7 +1438,6 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) osdc->osdmap = newmap; } kick_requests(osdc, 0); - reset_changed_osds(osdc); } else { dout("ignoring incremental map %u len %d\n", epoch, maplen); -- GitLab From 5bd9eb5a0891df0a806f265db504661fd558529c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 26 Dec 2012 10:43:57 -0600 Subject: [PATCH 1490/1799] libceph: WARN, don't BUG on unexpected connection states A number of assertions in the ceph messenger are implemented with BUG_ON(), killing the system if connection's state doesn't match what's expected. At this point our state model is (evidently) not well understood enough for these assertions to trigger a BUG(). Convert all BUG_ON(con->state...) calls to be WARN_ON(con->state...) so we learn about these issues without killing the machine. We now recognize that a connection fault can occur due to a socket closure at any time, regardless of the state of the connection. So there is really nothing we can assert about the state of the connection at that point so eliminate that assertion. Reported-by: Ugis Tested-by: Ugis Signed-off-by: Alex Elder Reviewed-by: Sage Weil (cherry picked from commit 122070a2ffc91f87fe8e8493eb0ac61986c5557c) Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 0ff14e88586f..5ff743ee8068 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -561,7 +561,7 @@ void ceph_con_open(struct ceph_connection *con, mutex_lock(&con->mutex); dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); - BUG_ON(con->state != CON_STATE_CLOSED); + WARN_ON(con->state != CON_STATE_CLOSED); con->state = CON_STATE_PREOPEN; con->peer_name.type = (__u8) entity_type; @@ -1505,7 +1505,7 @@ static int process_banner(struct ceph_connection *con) static void fail_protocol(struct ceph_connection *con) { reset_connection(con); - BUG_ON(con->state != CON_STATE_NEGOTIATING); + WARN_ON(con->state != CON_STATE_NEGOTIATING); con->state = CON_STATE_CLOSED; } @@ -1631,7 +1631,7 @@ static int process_connect(struct ceph_connection *con) return -1; } - BUG_ON(con->state != CON_STATE_NEGOTIATING); + WARN_ON(con->state != CON_STATE_NEGOTIATING); con->state = CON_STATE_OPEN; con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); @@ -2128,7 +2128,6 @@ static int try_read(struct ceph_connection *con) if (ret < 0) goto out; - BUG_ON(con->state != CON_STATE_CONNECTING); con->state = CON_STATE_NEGOTIATING; /* @@ -2156,7 +2155,7 @@ static int try_read(struct ceph_connection *con) goto more; } - BUG_ON(con->state != CON_STATE_OPEN); + WARN_ON(con->state != CON_STATE_OPEN); if (con->in_base_pos < 0) { /* @@ -2370,7 +2369,7 @@ static void ceph_fault(struct ceph_connection *con) dout("fault %p state %lu to peer %s\n", con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); - BUG_ON(con->state != CON_STATE_CONNECTING && + WARN_ON(con->state != CON_STATE_CONNECTING && con->state != CON_STATE_NEGOTIATING && con->state != CON_STATE_OPEN); -- GitLab From 7f5b160daddeaa55e441aca16010fab8299dfe9e Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 27 Dec 2012 20:27:04 -0600 Subject: [PATCH 1491/1799] libceph: fix protocol feature mismatch failure path We should not set con->state to CLOSED here; that happens in ceph_fault() in the caller, where it first asserts that the state is not yet CLOSED. Avoids a BUG when the features don't match. Since the fail_protocol() has become a trivial wrapper, replace calls to it with direct calls to reset_connection(). Signed-off-by: Sage Weil Reviewed-by: Alex Elder (cherry picked from commit 0fa6ebc600bc8e830551aee47a0e929e818a1868) Signed-off-by: Greg Kroah-Hartman --- net/ceph/messenger.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 5ff743ee8068..ba1037ceb496 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -506,6 +506,7 @@ static void reset_connection(struct ceph_connection *con) { /* reset connection, out_queue, msg_ and connect_seq */ /* discard existing out_queue and msg_seq */ + dout("reset_connection %p\n", con); ceph_msg_remove_list(&con->out_queue); ceph_msg_remove_list(&con->out_sent); @@ -1502,13 +1503,6 @@ static int process_banner(struct ceph_connection *con) return 0; } -static void fail_protocol(struct ceph_connection *con) -{ - reset_connection(con); - WARN_ON(con->state != CON_STATE_NEGOTIATING); - con->state = CON_STATE_CLOSED; -} - static int process_connect(struct ceph_connection *con) { u64 sup_feat = con->msgr->supported_features; @@ -1526,7 +1520,7 @@ static int process_connect(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr), sup_feat, server_feat, server_feat & ~sup_feat); con->error_msg = "missing required protocol features"; - fail_protocol(con); + reset_connection(con); return -1; case CEPH_MSGR_TAG_BADPROTOVER: @@ -1537,7 +1531,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->out_connect.protocol_version), le32_to_cpu(con->in_reply.protocol_version)); con->error_msg = "protocol version mismatch"; - fail_protocol(con); + reset_connection(con); return -1; case CEPH_MSGR_TAG_BADAUTHORIZER: @@ -1627,7 +1621,7 @@ static int process_connect(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr), req_feat, server_feat, req_feat & ~server_feat); con->error_msg = "missing required protocol features"; - fail_protocol(con); + reset_connection(con); return -1; } -- GitLab From 9aaab33ec9b7b9cb745fc47dfe20b991ff468d72 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 29 Oct 2012 11:01:42 -0700 Subject: [PATCH 1492/1799] libceph: fix osdmap decode error paths Ensure that we set the err value correctly so that we do not pass a 0 value to ERR_PTR and confuse the calling code. (In particular, osd_client.c handle_map() will BUG(!newmap)). Signed-off-by: Sage Weil Reviewed-by: Alex Elder (cherry picked from commit 0ed7285e0001b960c888e5455ae982025210ed3d) Signed-off-by: Greg Kroah-Hartman --- net/ceph/osdmap.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 430076ee938e..7fbe21030f54 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -613,10 +613,12 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) ceph_decode_32_safe(p, end, max, bad); while (max--) { ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad); + err = -ENOMEM; pi = kzalloc(sizeof(*pi), GFP_NOFS); if (!pi) goto bad; pi->id = ceph_decode_32(p); + err = -EINVAL; ev = ceph_decode_8(p); /* encoding version */ if (ev > CEPH_PG_POOL_VERSION) { pr_warning("got unknown v %d > %d of ceph_pg_pool\n", @@ -632,8 +634,13 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) __insert_pg_pool(&map->pg_pools, pi); } - if (version >= 5 && __decode_pool_names(p, end, map) < 0) - goto bad; + if (version >= 5) { + err = __decode_pool_names(p, end, map); + if (err < 0) { + dout("fail to decode pool names"); + goto bad; + } + } ceph_decode_32_safe(p, end, map->pool_max, bad); @@ -713,7 +720,7 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) return map; bad: - dout("osdmap_decode fail\n"); + dout("osdmap_decode fail err %d\n", err); ceph_osdmap_destroy(map); return ERR_PTR(err); } @@ -807,6 +814,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, if (ev > CEPH_PG_POOL_VERSION) { pr_warning("got unknown v %d > %d of ceph_pg_pool\n", ev, CEPH_PG_POOL_VERSION); + err = -EINVAL; goto bad; } pi = __lookup_pg_pool(&map->pg_pools, pool); @@ -823,8 +831,11 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, if (err < 0) goto bad; } - if (version >= 5 && __decode_pool_names(p, end, map) < 0) - goto bad; + if (version >= 5) { + err = __decode_pool_names(p, end, map); + if (err < 0) + goto bad; + } /* old_pool */ ceph_decode_32_safe(p, end, len, bad); @@ -900,15 +911,13 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, (void) __remove_pg_mapping(&map->pg_temp, pgid); /* insert */ - if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) { - err = -EINVAL; + err = -EINVAL; + if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) goto bad; - } + err = -ENOMEM; pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); - if (!pg) { - err = -ENOMEM; + if (!pg) goto bad; - } pg->pgid = pgid; pg->len = pglen; for (j = 0; j < pglen; j++) -- GitLab From 3aa540b869b9bd734ec60246ae1dfe35ab3530e0 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 7 Dec 2012 09:57:58 -0600 Subject: [PATCH 1493/1799] libceph: avoid using freed osd in __kick_osd_requests() If an osd has no requests and no linger requests, __reset_osd() will just remove it with a call to __remove_osd(). That drops a reference to the osd, and therefore the osd may have been free by the time __reset_osd() returns. That function offers no indication this may have occurred, and as a result the osd will continue to be used even when it's no longer valid. Change__reset_osd() so it returns an error (ENODEV) when it deletes the osd being reset. And change __kick_osd_requests() so it returns immediately (before referencing osd again) if __reset_osd() returns *any* error. Signed-off-by: Alex Elder Reviewed-by: Sage Weil (cherry picked from commit 685a7555ca69030739ddb57a47f0ea8ea80196a4) Signed-off-by: Greg Kroah-Hartman --- net/ceph/osd_client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index e03202bdc270..a5735f7c3667 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -579,7 +579,7 @@ static void __kick_osd_requests(struct ceph_osd_client *osdc, dout("__kick_osd_requests osd%d\n", osd->o_osd); err = __reset_osd(osdc, osd); - if (err == -EAGAIN) + if (err) return; list_for_each_entry(req, &osd->o_requests, r_osd_item) { @@ -750,6 +750,7 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) if (list_empty(&osd->o_requests) && list_empty(&osd->o_linger_requests)) { __remove_osd(osdc, osd); + ret = -ENODEV; } else if (memcmp(&osdc->osdmap->osd_addr[osd->o_osd], &osd->o_con.peer_addr, sizeof(osd->o_con.peer_addr)) == 0 && -- GitLab From e4a4a559d2ba0d50059a85967b4c4c707863a65b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 10 Aug 2012 13:12:10 -0700 Subject: [PATCH 1494/1799] rbd: kill create_snap sysfs entry Josh proposed the following change, and I don't think I could explain it any better than he did: From: Josh Durgin Date: Tue, 24 Jul 2012 14:22:11 -0700 To: ceph-devel Message-ID: <500F1203.9050605@inktank.com> From: Josh Durgin Right now the kernel still has one piece of rbd management duplicated from the rbd command line tool: snapshot creation. There's nothing special about snapshot creation that makes it advantageous to do from the kernel, so I'd like to remove the create_snap sysfs interface. That is, /sys/bus/rbd/devices//create_snap would be removed. Does anyone rely on the sysfs interface for creating rbd snapshots? If so, how hard would it be to replace with: rbd snap create pool/image@snap Is there any benefit to the sysfs interface that I'm missing? Josh This patch implements this proposal, removing the code that implements the "snap_create" sysfs interface for rbd images. As a result, quite a lot of other supporting code goes away. [elder@inktank.com: commented out rbd_req_sync_exec() to avoid warning] Suggested-by: Josh Durgin Signed-off-by: Alex Elder Reviewed-by: Josh Durgin (based on commit 02cdb02ceab1f3dd9ac2bc899fc51f0e0e744782) --- Documentation/ABI/testing/sysfs-bus-rbd | 6 - drivers/block/rbd.c | 165 +----------------------- 2 files changed, 2 insertions(+), 169 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-rbd b/Documentation/ABI/testing/sysfs-bus-rbd index dbedafb095e2..eb781c624a78 100644 --- a/Documentation/ABI/testing/sysfs-bus-rbd +++ b/Documentation/ABI/testing/sysfs-bus-rbd @@ -51,12 +51,6 @@ current_snap The current snapshot for which the device is mapped. -create_snap - - Create a snapshot: - - $ echo > /sys/bus/rbd/devices//snap_create - snap_* A directory per each snapshot diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index c05a4ab47e5a..cce3e5f8a031 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -201,10 +201,6 @@ static DEFINE_SPINLOCK(rbd_client_list_lock); static int __rbd_init_snaps_header(struct rbd_device *rbd_dev); static void rbd_dev_release(struct device *dev); -static ssize_t rbd_snap_add(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count); static void __rbd_remove_snap_dev(struct rbd_device *rbd_dev, struct rbd_snap *snap); @@ -1307,71 +1303,7 @@ static int rbd_req_sync_unwatch(struct rbd_device *dev, return ret; } -struct rbd_notify_info { - struct rbd_device *dev; -}; - -static void rbd_notify_cb(u64 ver, u64 notify_id, u8 opcode, void *data) -{ - struct rbd_device *dev = (struct rbd_device *)data; - if (!dev) - return; - - dout("rbd_notify_cb %s notify_id=%lld opcode=%d\n", dev->obj_md_name, - notify_id, (int)opcode); -} - -/* - * Request sync osd notify - */ -static int rbd_req_sync_notify(struct rbd_device *dev, - const char *obj) -{ - struct ceph_osd_req_op *ops; - struct ceph_osd_client *osdc = &dev->rbd_client->client->osdc; - struct ceph_osd_event *event; - struct rbd_notify_info info; - int payload_len = sizeof(u32) + sizeof(u32); - int ret; - - ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY, payload_len); - if (ret < 0) - return ret; - - info.dev = dev; - - ret = ceph_osdc_create_event(osdc, rbd_notify_cb, 1, - (void *)&info, &event); - if (ret < 0) - goto fail; - - ops[0].watch.ver = 1; - ops[0].watch.flag = 1; - ops[0].watch.cookie = event->cookie; - ops[0].watch.prot_ver = RADOS_NOTIFY_VER; - ops[0].watch.timeout = 12; - - ret = rbd_req_sync_op(dev, NULL, - CEPH_NOSNAP, - 0, - CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, - ops, - 1, obj, 0, 0, NULL, NULL, NULL); - if (ret < 0) - goto fail_event; - - ret = ceph_osdc_wait_event(event, CEPH_OSD_TIMEOUT_DEFAULT); - dout("ceph_osdc_wait_event returned %d\n", ret); - rbd_destroy_ops(ops); - return 0; - -fail_event: - ceph_osdc_cancel_event(event); -fail: - rbd_destroy_ops(ops); - return ret; -} - +#if 0 /* * Request sync osd read */ @@ -1411,6 +1343,7 @@ static int rbd_req_sync_exec(struct rbd_device *dev, dout("cls_exec returned %d\n", ret); return ret; } +#endif static struct rbd_req_coll *rbd_alloc_coll(int num_reqs) { @@ -1645,57 +1578,6 @@ static int rbd_read_header(struct rbd_device *rbd_dev, return rc; } -/* - * create a snapshot - */ -static int rbd_header_add_snap(struct rbd_device *dev, - const char *snap_name, - gfp_t gfp_flags) -{ - int name_len = strlen(snap_name); - u64 new_snapid; - int ret; - void *data, *p, *e; - u64 ver; - struct ceph_mon_client *monc; - - /* we should create a snapshot only if we're pointing at the head */ - if (dev->snap_id != CEPH_NOSNAP) - return -EINVAL; - - monc = &dev->rbd_client->client->monc; - ret = ceph_monc_create_snapid(monc, dev->poolid, &new_snapid); - dout("created snapid=%lld\n", new_snapid); - if (ret < 0) - return ret; - - data = kmalloc(name_len + 16, gfp_flags); - if (!data) - return -ENOMEM; - - p = data; - e = data + name_len + 16; - - ceph_encode_string_safe(&p, e, snap_name, name_len, bad); - ceph_encode_64_safe(&p, e, new_snapid, bad); - - ret = rbd_req_sync_exec(dev, dev->obj_md_name, "rbd", "snap_add", - data, p - data, &ver); - - kfree(data); - - if (ret < 0) - return ret; - - down_write(&dev->header_rwsem); - dev->header.snapc->seq = new_snapid; - up_write(&dev->header_rwsem); - - return 0; -bad: - return -ERANGE; -} - static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev) { struct rbd_snap *snap; @@ -1923,7 +1805,6 @@ static DEVICE_ATTR(pool, S_IRUGO, rbd_pool_show, NULL); static DEVICE_ATTR(name, S_IRUGO, rbd_name_show, NULL); static DEVICE_ATTR(refresh, S_IWUSR, NULL, rbd_image_refresh); static DEVICE_ATTR(current_snap, S_IRUGO, rbd_snap_show, NULL); -static DEVICE_ATTR(create_snap, S_IWUSR, NULL, rbd_snap_add); static struct attribute *rbd_attrs[] = { &dev_attr_size.attr, @@ -1933,7 +1814,6 @@ static struct attribute *rbd_attrs[] = { &dev_attr_name.attr, &dev_attr_current_snap.attr, &dev_attr_refresh.attr, - &dev_attr_create_snap.attr, NULL }; @@ -2563,47 +2443,6 @@ static ssize_t rbd_remove(struct bus_type *bus, return ret; } -static ssize_t rbd_snap_add(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); - int ret; - char *name = kmalloc(count + 1, GFP_KERNEL); - if (!name) - return -ENOMEM; - - snprintf(name, count, "%s", buf); - - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - - ret = rbd_header_add_snap(rbd_dev, - name, GFP_KERNEL); - if (ret < 0) - goto err_unlock; - - ret = __rbd_update_snaps(rbd_dev); - if (ret < 0) - goto err_unlock; - - /* shouldn't hold ctl_mutex when notifying.. notify might - trigger a watch callback that would need to get that mutex */ - mutex_unlock(&ctl_mutex); - - /* make a best effort, don't error if failed */ - rbd_req_sync_notify(rbd_dev, rbd_dev->obj_md_name); - - ret = count; - kfree(name); - return ret; - -err_unlock: - mutex_unlock(&ctl_mutex); - kfree(name); - return ret; -} - /* * create control files in sysfs * /sys/bus/rbd/... -- GitLab From 5833a9132795681510a7dbd952696960763dc736 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 10 Aug 2012 13:12:07 -0700 Subject: [PATCH 1495/1799] rbd: add read_only rbd map option Add the ability to map an rbd image read-only, by specifying either "read_only" or "ro" as an option on the rbd "command line." Also allow the inverse to be explicitly specified using "read_write" or "rw". Signed-off-by: Alex Elder Reviewed-by: Yehuda Sadeh (based on commit cc0538b62c839c2df7b9f8378bb37e3b35faa608) --- drivers/block/rbd.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index cce3e5f8a031..78996d0e1499 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -71,7 +71,8 @@ #define DEV_NAME_LEN 32 #define MAX_INT_FORMAT_WIDTH ((5 * sizeof (int)) / 2 + 1) -#define RBD_NOTIFY_TIMEOUT_DEFAULT 10 +#define RBD_NOTIFY_TIMEOUT_DEFAULT 10 +#define RBD_READ_ONLY_DEFAULT false /* * block device image metadata (in-memory version) @@ -95,6 +96,7 @@ struct rbd_image_header { struct rbd_options { int notify_timeout; + bool read_only; }; /* @@ -180,7 +182,7 @@ struct rbd_device { u64 snap_id; /* current snapshot id */ /* whether the snap_id this device reads from still exists */ bool snap_exists; - int read_only; + bool read_only; struct list_head node; @@ -346,12 +348,21 @@ enum { /* int args above */ Opt_last_string, /* string args above */ + Opt_read_only, + Opt_read_write, + /* Boolean args above */ + Opt_last_bool, }; static match_table_t rbdopt_tokens = { {Opt_notify_timeout, "notify_timeout=%d"}, /* int args above */ /* string args above */ + {Opt_read_only, "read_only"}, + {Opt_read_only, "ro"}, /* Alternate spelling */ + {Opt_read_write, "read_write"}, + {Opt_read_write, "rw"}, /* Alternate spelling */ + /* Boolean args above */ {-1, NULL} }; @@ -376,6 +387,8 @@ static int parse_rbd_opts_token(char *c, void *private) } else if (token > Opt_last_int && token < Opt_last_string) { dout("got string token %d val %s\n", token, argstr[0].from); + } else if (token > Opt_last_string && token < Opt_last_bool) { + dout("got Boolean token %d\n", token); } else { dout("got token %d\n", token); } @@ -384,6 +397,12 @@ static int parse_rbd_opts_token(char *c, void *private) case Opt_notify_timeout: rbdopt->notify_timeout = intval; break; + case Opt_read_only: + rbdopt->read_only = true; + break; + case Opt_read_write: + rbdopt->read_only = false; + break; default: BUG_ON(token); } @@ -407,6 +426,7 @@ static struct rbd_client *rbd_get_client(const char *mon_addr, return ERR_PTR(-ENOMEM); rbd_opts->notify_timeout = RBD_NOTIFY_TIMEOUT_DEFAULT; + rbd_opts->read_only = RBD_READ_ONLY_DEFAULT; opt = ceph_parse_options(options, mon_addr, mon_addr + mon_addr_len, @@ -590,7 +610,7 @@ static int rbd_header_set_snap(struct rbd_device *dev, u64 *size) snapc->seq = 0; dev->snap_id = CEPH_NOSNAP; dev->snap_exists = false; - dev->read_only = 0; + dev->read_only = dev->rbd_client->rbd_opts->read_only; if (size) *size = header->image_size; } else { @@ -599,7 +619,7 @@ static int rbd_header_set_snap(struct rbd_device *dev, u64 *size) goto done; dev->snap_id = snapc->seq; dev->snap_exists = true; - dev->read_only = 1; + dev->read_only = true; /* No choice for snapshots */ } ret = 0; -- GitLab From 87c7f759d1546a27d46d8cc2778ffecaa5f542c6 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 10 Aug 2012 13:12:07 -0700 Subject: [PATCH 1496/1799] rbd: kill notify_timeout option The "notify_timeout" rbd device option is never used, so get rid of it. Signed-off-by: Alex Elder Reviewed-by: Yehuda Sadeh (cherry picked from commit 84d34dcc116e117a41c6fc8be13430529fc2d9e7) Signed-off-by: Greg Kroah-Hartman --- drivers/block/rbd.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 78996d0e1499..cf3ce697c0b6 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -71,7 +71,6 @@ #define DEV_NAME_LEN 32 #define MAX_INT_FORMAT_WIDTH ((5 * sizeof (int)) / 2 + 1) -#define RBD_NOTIFY_TIMEOUT_DEFAULT 10 #define RBD_READ_ONLY_DEFAULT false /* @@ -95,7 +94,6 @@ struct rbd_image_header { }; struct rbd_options { - int notify_timeout; bool read_only; }; @@ -343,7 +341,6 @@ static struct rbd_client *__rbd_client_find(struct ceph_options *opt) * mount options */ enum { - Opt_notify_timeout, Opt_last_int, /* int args above */ Opt_last_string, @@ -355,7 +352,6 @@ enum { }; static match_table_t rbdopt_tokens = { - {Opt_notify_timeout, "notify_timeout=%d"}, /* int args above */ /* string args above */ {Opt_read_only, "read_only"}, @@ -394,9 +390,6 @@ static int parse_rbd_opts_token(char *c, void *private) } switch (token) { - case Opt_notify_timeout: - rbdopt->notify_timeout = intval; - break; case Opt_read_only: rbdopt->read_only = true; break; @@ -425,7 +418,6 @@ static struct rbd_client *rbd_get_client(const char *mon_addr, if (!rbd_opts) return ERR_PTR(-ENOMEM); - rbd_opts->notify_timeout = RBD_NOTIFY_TIMEOUT_DEFAULT; rbd_opts->read_only = RBD_READ_ONLY_DEFAULT; opt = ceph_parse_options(options, mon_addr, -- GitLab From 31c46473d6a31ac1948c189624b472f26a6365e9 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 28 Nov 2012 12:28:24 -0800 Subject: [PATCH 1497/1799] libceph: remove 'osdtimeout' option This would reset a connection with any OSD that had an outstanding request that was taking more than N seconds. The idea was that if the OSD was buggy, the client could compensate by resending the request. In reality, this only served to hide server bugs, and we haven't actually seen such a bug in quite a while. Moreover, the userspace client code never did this. More importantly, often the request is taking a long time because the OSD is trying to recover, or overloaded, and killing the connection and retrying would only make the situation worse by giving the OSD more work to do. Signed-off-by: Sage Weil Reviewed-by: Alex Elder (cherry picked from commit 83aff95eb9d60aff5497e9f44a2ae906b86d8e88) Signed-off-by: Greg Kroah-Hartman --- fs/ceph/super.c | 2 -- include/linux/ceph/libceph.h | 2 -- net/ceph/ceph_common.c | 3 +-- net/ceph/osd_client.c | 47 +++--------------------------------- 4 files changed, 5 insertions(+), 49 deletions(-) diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 1e67dd7305a4..f36391815461 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -387,8 +387,6 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root) seq_printf(m, ",mount_timeout=%d", opt->mount_timeout); if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT) seq_printf(m, ",osd_idle_ttl=%d", opt->osd_idle_ttl); - if (opt->osd_timeout != CEPH_OSD_TIMEOUT_DEFAULT) - seq_printf(m, ",osdtimeout=%d", opt->osd_timeout); if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT) seq_printf(m, ",osdkeepalivetimeout=%d", opt->osd_keepalive_timeout); diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h index 98ec36ae8a3b..893420b78d0a 100644 --- a/include/linux/ceph/libceph.h +++ b/include/linux/ceph/libceph.h @@ -49,7 +49,6 @@ struct ceph_options { struct ceph_entity_addr my_addr; int mount_timeout; int osd_idle_ttl; - int osd_timeout; int osd_keepalive_timeout; /* @@ -69,7 +68,6 @@ struct ceph_options { * defaults */ #define CEPH_MOUNT_TIMEOUT_DEFAULT 60 -#define CEPH_OSD_TIMEOUT_DEFAULT 60 /* seconds */ #define CEPH_OSD_KEEPALIVE_DEFAULT 5 #define CEPH_OSD_IDLE_TTL_DEFAULT 60 diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 8e74e8c5a774..b11448f052f4 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -304,7 +304,6 @@ ceph_parse_options(char *options, const char *dev_name, /* start with defaults */ opt->flags = CEPH_OPT_DEFAULT; - opt->osd_timeout = CEPH_OSD_TIMEOUT_DEFAULT; opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT; opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */ opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT; /* seconds */ @@ -390,7 +389,7 @@ ceph_parse_options(char *options, const char *dev_name, /* misc */ case Opt_osdtimeout: - opt->osd_timeout = intval; + pr_warning("ignoring deprecated osdtimeout option\n"); break; case Opt_osdkeepalivetimeout: opt->osd_keepalive_timeout = intval; diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index a5735f7c3667..254f530b98ff 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -606,14 +606,6 @@ static void __kick_osd_requests(struct ceph_osd_client *osdc, } } -static void kick_osd_requests(struct ceph_osd_client *osdc, - struct ceph_osd *kickosd) -{ - mutex_lock(&osdc->request_mutex); - __kick_osd_requests(osdc, kickosd); - mutex_unlock(&osdc->request_mutex); -} - /* * If the osd connection drops, we need to resubmit all requests. */ @@ -627,7 +619,9 @@ static void osd_reset(struct ceph_connection *con) dout("osd_reset osd%d\n", osd->o_osd); osdc = osd->o_osdc; down_read(&osdc->map_sem); - kick_osd_requests(osdc, osd); + mutex_lock(&osdc->request_mutex); + __kick_osd_requests(osdc, osd); + mutex_unlock(&osdc->request_mutex); send_queued(osdc); up_read(&osdc->map_sem); } @@ -1091,12 +1085,10 @@ static void handle_timeout(struct work_struct *work) { struct ceph_osd_client *osdc = container_of(work, struct ceph_osd_client, timeout_work.work); - struct ceph_osd_request *req, *last_req = NULL; + struct ceph_osd_request *req; struct ceph_osd *osd; - unsigned long timeout = osdc->client->options->osd_timeout * HZ; unsigned long keepalive = osdc->client->options->osd_keepalive_timeout * HZ; - unsigned long last_stamp = 0; struct list_head slow_osds; dout("timeout\n"); down_read(&osdc->map_sem); @@ -1105,37 +1097,6 @@ static void handle_timeout(struct work_struct *work) mutex_lock(&osdc->request_mutex); - /* - * reset osds that appear to be _really_ unresponsive. this - * is a failsafe measure.. we really shouldn't be getting to - * this point if the system is working properly. the monitors - * should mark the osd as failed and we should find out about - * it from an updated osd map. - */ - while (timeout && !list_empty(&osdc->req_lru)) { - req = list_entry(osdc->req_lru.next, struct ceph_osd_request, - r_req_lru_item); - - /* hasn't been long enough since we sent it? */ - if (time_before(jiffies, req->r_stamp + timeout)) - break; - - /* hasn't been long enough since it was acked? */ - if (req->r_request->ack_stamp == 0 || - time_before(jiffies, req->r_request->ack_stamp + timeout)) - break; - - BUG_ON(req == last_req && req->r_stamp == last_stamp); - last_req = req; - last_stamp = req->r_stamp; - - osd = req->r_osd; - BUG_ON(!osd); - pr_warning(" tid %llu timed out on osd%d, will reset osd\n", - req->r_tid, osd->o_osd); - __kick_osd_requests(osdc, osd); - } - /* * ping osds that are a bit slow. this ensures that if there * is a break in the TCP connection we will notice, and reopen -- GitLab From 02585b8bdc988de82b45088a3f2092af2e6b2816 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 29 Nov 2012 08:37:03 -0600 Subject: [PATCH 1498/1799] ceph: don't reference req after put In __unregister_request(), there is a call to list_del_init() referencing a request that was the subject of a call to ceph_osdc_put_request() on the previous line. This is not safe, because the request structure could have been freed by the time we reach the list_del_init(). Fix this by reversing the order of these lines. Signed-off-by: Alex Elder Reviewed-off-by: Sage Weil (cherry picked from commit 7d5f24812bd182a2471cb69c1c2baf0648332e1f) Signed-off-by: Greg Kroah-Hartman --- net/ceph/osd_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 254f530b98ff..925649c522f2 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -871,9 +871,9 @@ static void __unregister_request(struct ceph_osd_client *osdc, req->r_osd = NULL; } + list_del_init(&req->r_req_lru_item); ceph_osdc_put_request(req); - list_del_init(&req->r_req_lru_item); if (osdc->num_requests == 0) { dout(" no requests, canceling timeout\n"); __cancel_osd_timeout(osdc); -- GitLab From 50cda8f4439d715e080ced70d1e6d9ec07f95e6c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 6 Dec 2012 09:37:23 -0600 Subject: [PATCH 1499/1799] rbd: remove linger unconditionally In __unregister_linger_request(), the request is being removed from the osd client's req_linger list only when the request has a non-null osd pointer. It should be done whether or not the request currently has an osd. This is most likely a non-issue because I believe the request will always have an osd when this function is called. Signed-off-by: Alex Elder Reviewed-by: Sage Weil (cherry picked from commit 61c74035626beb25a39b0273ccf7d75510bc36a1) Signed-off-by: Greg Kroah-Hartman --- net/ceph/osd_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 925649c522f2..b16dfa25e750 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -905,8 +905,8 @@ static void __unregister_linger_request(struct ceph_osd_client *osdc, struct ceph_osd_request *req) { dout("__unregister_linger_request %p\n", req); + list_del_init(&req->r_linger_item); if (req->r_osd) { - list_del_init(&req->r_linger_item); list_del_init(&req->r_linger_osd); if (list_empty(&req->r_osd->o_requests) && -- GitLab From f2ac87daff2e4a8c9fb8119a8e4badaac684a284 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 24 Sep 2012 21:02:47 -0700 Subject: [PATCH 1500/1799] rbd: BUG on invalid layout This shouldn't actually be possible because the layout struct is constructed from the RBD header and validated then. [elder@inktank.com: converted BUG() call to equivalent rbd_assert()] Signed-off-by: Sage Weil Reviewed-by: Alex Elder (based on commit 6cae3717cddaf8e5e96e304733dca66e40d56f89) --- drivers/block/rbd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index cf3ce697c0b6..f1375d98f6e7 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -930,8 +930,9 @@ static int rbd_do_request(struct request *rq, layout->fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER); layout->fl_pg_preferred = cpu_to_le32(-1); layout->fl_pg_pool = cpu_to_le32(dev->poolid); - ceph_calc_raw_layout(osdc, layout, snapid, ofs, &len, &bno, - req, ops); + ret = ceph_calc_raw_layout(osdc, layout, snapid, ofs, &len, &bno, + req, ops); + BUG_ON(ret != 0); ceph_osdc_build_request(req, ofs, &len, ops, -- GitLab From 1e411c66732294f5fb983323dafa7559796481f5 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 10 Oct 2012 21:19:13 -0700 Subject: [PATCH 1501/1799] rbd: fix bug in rbd_dev_id_put() In rbd_dev_id_put(), there's a loop that's intended to determine the maximum device id in use. But it isn't doing that at all, the effect of how it's written is to simply use the just-put id number, which ignores whole purpose of this function. Fix the bug. Signed-off-by: Alex Elder Reviewed-by: Josh Durgin (cherry picked from commit b213e0b1a62637b2a9395a34349b13d73ca2b90a) Signed-off-by: Greg Kroah-Hartman --- drivers/block/rbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index f1375d98f6e7..d9ebe6844da6 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -2150,8 +2150,8 @@ static void rbd_id_put(struct rbd_device *rbd_dev) struct rbd_device *rbd_dev; rbd_dev = list_entry(tmp, struct rbd_device, node); - if (rbd_id > max_id) - max_id = rbd_id; + if (rbd_dev->id > max_id) + max_id = rbd_dev->id; } spin_unlock(&rbd_dev_list_lock); -- GitLab From 3317122449a2ce5c0bba77e1f05b1df2ff716447 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 16 Nov 2012 09:29:16 -0600 Subject: [PATCH 1502/1799] rbd: do not allow remove of mounted-on image There is no check in rbd_remove() to see if anybody holds open the image being removed. That's not cool. Add a simple open count that goes up and down with opens and closes (releases) of the device, and don't allow an rbd image to be removed if the count is non-zero. Protect the updates of the open count value with ctl_mutex to ensure the underlying rbd device doesn't get removed while concurrently being opened. Signed-off-by: Alex Elder Reviewed-by: Sage Weil (based on commit 42382b709bd1d143b9f0fa93e0a3a1f2f4210707) --- drivers/block/rbd.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index d9ebe6844da6..cba3d0278b86 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -189,6 +189,7 @@ struct rbd_device { /* sysfs related */ struct device dev; + unsigned long open_count; }; static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */ @@ -249,8 +250,11 @@ static int rbd_open(struct block_device *bdev, fmode_t mode) if ((mode & FMODE_WRITE) && rbd_dev->read_only) return -EROFS; + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); rbd_get_dev(rbd_dev); set_device_ro(bdev, rbd_dev->read_only); + rbd_dev->open_count++; + mutex_unlock(&ctl_mutex); return 0; } @@ -259,7 +263,11 @@ static int rbd_release(struct gendisk *disk, fmode_t mode) { struct rbd_device *rbd_dev = disk->private_data; + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + BUG_ON(!rbd_dev->open_count); + rbd_dev->open_count--; rbd_put_dev(rbd_dev); + mutex_unlock(&ctl_mutex); return 0; } @@ -2448,6 +2456,11 @@ static ssize_t rbd_remove(struct bus_type *bus, goto done; } + if (rbd_dev->open_count) { + ret = -EBUSY; + goto done; + } + __rbd_remove_all_snaps(rbd_dev); rbd_bus_del_dev(rbd_dev); -- GitLab From 7ae7b557aaaf1d50f04706b775341957f12bab10 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 19 Nov 2012 10:49:04 +0800 Subject: [PATCH 1503/1799] ceph: Don't update i_max_size when handling non-auth cap The cap from non-auth mds doesn't have a meaningful max_size value. Signed-off-by: Yan, Zheng Signed-off-by: Sage Weil (cherry picked from commit 5e62ad30157d0da04cf40c6d1a2f4bc840948b9c) Signed-off-by: Greg Kroah-Hartman --- fs/ceph/caps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 620daad201db..d7149c0dda1b 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -2388,7 +2388,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, &atime); /* max size increase? */ - if (max_size != ci->i_max_size) { + if (ci->i_auth_cap == cap && max_size != ci->i_max_size) { dout("max_size %lld -> %llu\n", ci->i_max_size, max_size); ci->i_max_size = max_size; if (max_size >= ci->i_wanted_max_size) { -- GitLab From 42d519d12ef2d43a83b86cd2931c539045d07059 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 19 Nov 2012 10:49:06 +0800 Subject: [PATCH 1504/1799] ceph: Fix infinite loop in __wake_requests __wake_requests() will enter infinite loop if we use it to wake requests in the session->s_waiting list. __wake_requests() deletes requests from the list and __do_request() adds requests back to the list. Signed-off-by: Yan, Zheng Signed-off-by: Sage Weil (cherry picked from commit ed75ec2cd19b47efcd292b6e23f58e56f4c5bc34) Signed-off-by: Greg Kroah-Hartman --- fs/ceph/mds_client.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 95708dd092f1..3fd08ad5c478 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -1886,9 +1886,14 @@ static int __do_request(struct ceph_mds_client *mdsc, static void __wake_requests(struct ceph_mds_client *mdsc, struct list_head *head) { - struct ceph_mds_request *req, *nreq; + struct ceph_mds_request *req; + LIST_HEAD(tmp_list); + + list_splice_init(head, &tmp_list); - list_for_each_entry_safe(req, nreq, head, r_wait) { + while (!list_empty(&tmp_list)) { + req = list_entry(tmp_list.next, + struct ceph_mds_request, r_wait); list_del_init(&req->r_wait); __do_request(mdsc, req); } -- GitLab From ba647fd5c7ffc1a6433c8c90eedadf76a3df82fa Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 19 Nov 2012 10:49:07 +0800 Subject: [PATCH 1505/1799] ceph: Don't add dirty inode to dirty list if caps is in migration Add dirty inode to cap_dirty_migrating list instead, this can avoid ceph_flush_dirty_caps() entering infinite loop. Signed-off-by: Yan, Zheng Signed-off-by: Sage Weil (cherry picked from commit 0685235ffd9dbdb9ccbda587f8a3c83ad1d5a921) Signed-off-by: Greg Kroah-Hartman --- fs/ceph/caps.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index d7149c0dda1b..e4eb282da109 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -1349,11 +1349,15 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) if (!ci->i_head_snapc) ci->i_head_snapc = ceph_get_snap_context( ci->i_snap_realm->cached_context); - dout(" inode %p now dirty snapc %p\n", &ci->vfs_inode, - ci->i_head_snapc); + dout(" inode %p now dirty snapc %p auth cap %p\n", + &ci->vfs_inode, ci->i_head_snapc, ci->i_auth_cap); BUG_ON(!list_empty(&ci->i_dirty_item)); spin_lock(&mdsc->cap_dirty_lock); - list_add(&ci->i_dirty_item, &mdsc->cap_dirty); + if (ci->i_auth_cap) + list_add(&ci->i_dirty_item, &mdsc->cap_dirty); + else + list_add(&ci->i_dirty_item, + &mdsc->cap_dirty_migrating); spin_unlock(&mdsc->cap_dirty_lock); if (ci->i_flushing_caps == 0) { ihold(inode); -- GitLab From fbc8158351e8d34c499b61c422f3614dad6dc910 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 19 Nov 2012 10:49:08 +0800 Subject: [PATCH 1506/1799] ceph: Fix __ceph_do_pending_vmtruncate we should set i_truncate_pending to 0 after page cache is truncated to i_truncate_size Signed-off-by: Yan, Zheng Signed-off-by: Sage Weil (cherry picked from commit a85f50b6ef93fbbb2ae932ce9b2376509d172796) Signed-off-by: Greg Kroah-Hartman --- fs/ceph/inode.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 4b5762ef7c2b..81613bced19f 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1466,7 +1466,7 @@ void __ceph_do_pending_vmtruncate(struct inode *inode) { struct ceph_inode_info *ci = ceph_inode(inode); u64 to; - int wrbuffer_refs, wake = 0; + int wrbuffer_refs, finish = 0; retry: spin_lock(&ci->i_ceph_lock); @@ -1498,15 +1498,18 @@ void __ceph_do_pending_vmtruncate(struct inode *inode) truncate_inode_pages(inode->i_mapping, to); spin_lock(&ci->i_ceph_lock); - ci->i_truncate_pending--; - if (ci->i_truncate_pending == 0) - wake = 1; + if (to == ci->i_truncate_size) { + ci->i_truncate_pending = 0; + finish = 1; + } spin_unlock(&ci->i_ceph_lock); + if (!finish) + goto retry; if (wrbuffer_refs == 0) ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); - if (wake) - wake_up_all(&ci->i_cap_wq); + + wake_up_all(&ci->i_cap_wq); } -- GitLab From 57d93df8f18dbe66c0e2e1089ed2c120a9b980af Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 19 Nov 2012 10:49:09 +0800 Subject: [PATCH 1507/1799] ceph: call handle_cap_grant() for cap import message If client sends cap message that requests new max size during exporting caps, the exporting MDS will drop the message quietly. So the client may wait for the reply that updates the max size forever. call handle_cap_grant() for cap import message can avoid this issue. Signed-off-by: Yan, Zheng Signed-off-by: Sage Weil (cherry picked from commit 0e5e1774a92e6fe9c511585de8f078b4c4c68dbb) Signed-off-by: Greg Kroah-Hartman --- fs/ceph/caps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index e4eb282da109..e7d40776f58f 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -2749,6 +2749,7 @@ static void handle_cap_import(struct ceph_mds_client *mdsc, /* make sure we re-request max_size, if necessary */ spin_lock(&ci->i_ceph_lock); + ci->i_wanted_max_size = 0; /* reset */ ci->i_requested_max_size = 0; spin_unlock(&ci->i_ceph_lock); } @@ -2844,8 +2845,6 @@ void ceph_handle_caps(struct ceph_mds_session *session, case CEPH_CAP_OP_IMPORT: handle_cap_import(mdsc, inode, h, session, snaptrace, snaptrace_len); - ceph_check_caps(ceph_inode(inode), 0, session); - goto done_unlocked; } /* the rest require a cap */ @@ -2862,6 +2861,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, switch (op) { case CEPH_CAP_OP_REVOKE: case CEPH_CAP_OP_GRANT: + case CEPH_CAP_OP_IMPORT: handle_cap_grant(inode, h, session, cap, msg->middle); goto done_unlocked; -- GitLab From 359c4ea7baf79484cc3561f0040f9d5e367155fe Mon Sep 17 00:00:00 2001 From: David Zafman Date: Mon, 3 Dec 2012 19:14:05 -0800 Subject: [PATCH 1508/1799] libceph: Unlock unprocessed pages in start_read() error path Function start_read() can get an error before processing all pages. It must not only release the remaining pages, but unlock them too. This fixes http://tracker.newdream.net/issues/3370 Signed-off-by: David Zafman Reviewed-by: Alex Elder (cherry picked from commit 8884d53dd63b1d9315b343564fcbe1ede004a99e) Signed-off-by: Greg Kroah-Hartman --- fs/ceph/addr.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index e009fde39cf6..bb01881cb1f2 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -267,6 +267,14 @@ static void finish_read(struct ceph_osd_request *req, struct ceph_msg *msg) kfree(req->r_pages); } +static void ceph_unlock_page_vector(struct page **pages, int num_pages) +{ + int i; + + for (i = 0; i < num_pages; i++) + unlock_page(pages[i]); +} + /* * start an async read(ahead) operation. return nr_pages we submitted * a read for on success, or negative error code. @@ -347,6 +355,7 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max) return nr_pages; out_pages: + ceph_unlock_page_vector(pages, nr_pages); ceph_release_page_vector(pages, nr_pages); out: ceph_osdc_put_request(req); -- GitLab From c390e5a48ae714a6da89f16a8239e1751a285376 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Mar 2012 17:14:58 +0100 Subject: [PATCH 1509/1799] staging: comedi: don't hijack hardware device private data commit c43435d7722134ed1fda58ce1025f41029bd58ad upstream. comedi_auto_config() associates a Comedi minor device number with an auto-configured hardware device and comedi_auto_unconfig() disassociates it. Currently, these use the hardware device's private data pointer to point to some allocated storage holding the minor device number. This is a bit of a waste of the hardware device's private data pointer, preventing it from being used for something more useful by the low-level comedi device drivers. For example, it would make more sense if comedi_usb_auto_config() was passed a pointer to the struct usb_interface instead of the struct usb_device, but this cannot be done currently because the low-level comedi drivers already use the private data pointer in the struct usb_interface for something more useful. This patch stops the comedi core hijacking the hardware device's private data pointer. Instead, comedi_auto_config() stores a pointer to the hardware device's struct device in the struct comedi_device_file_info associated with the minor device number, and comedi_auto_unconfig() calls new function comedi_find_board_minor() to recover the minor device number associated with the hardware device. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 18 +++++++++++++++ drivers/staging/comedi/comedidev.h | 1 + drivers/staging/comedi/drivers.c | 34 ++++++++-------------------- drivers/staging/comedi/internal.h | 1 + 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 3fd9772d7a7d..b67c1070df76 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -2210,6 +2210,7 @@ int comedi_alloc_board_minor(struct device *hardware_device) kfree(info); return -ENOMEM; } + info->hardware_device = hardware_device; comedi_device_init(info->device); spin_lock_irqsave(&comedi_file_info_table_lock, flags); for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) { @@ -2298,6 +2299,23 @@ void comedi_free_board_minor(unsigned minor) } } +int comedi_find_board_minor(struct device *hardware_device) +{ + int minor; + struct comedi_device_file_info *info; + + for (minor = 0; minor < COMEDI_NUM_BOARD_MINORS; minor++) { + spin_lock(&comedi_file_info_table_lock); + info = comedi_file_info_table[minor]; + if (info && info->hardware_device == hardware_device) { + spin_unlock(&comedi_file_info_table_lock); + return minor; + } + spin_unlock(&comedi_file_info_table_lock); + } + return -ENODEV; +} + int comedi_alloc_subdevice_minor(struct comedi_device *dev, struct comedi_subdevice *s) { diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 7a0d4bcbc355..00d3c65589bd 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -234,6 +234,7 @@ struct comedi_device_file_info { struct comedi_device *device; struct comedi_subdevice *read_subdevice; struct comedi_subdevice *write_subdevice; + struct device *hardware_device; }; #ifdef CONFIG_COMEDI_DEBUG diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index bf185e2807d1..0fc1b9939d97 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -822,25 +822,14 @@ static int comedi_auto_config(struct device *hardware_device, int minor; struct comedi_device_file_info *dev_file_info; int retval; - unsigned *private_data = NULL; - if (!comedi_autoconfig) { - dev_set_drvdata(hardware_device, NULL); + if (!comedi_autoconfig) return 0; - } minor = comedi_alloc_board_minor(hardware_device); if (minor < 0) return minor; - private_data = kmalloc(sizeof(unsigned), GFP_KERNEL); - if (private_data == NULL) { - retval = -ENOMEM; - goto cleanup; - } - *private_data = minor; - dev_set_drvdata(hardware_device, private_data); - dev_file_info = comedi_get_device_file_info(minor); memset(&it, 0, sizeof(it)); @@ -853,25 +842,22 @@ static int comedi_auto_config(struct device *hardware_device, retval = comedi_device_attach(dev_file_info->device, &it); mutex_unlock(&dev_file_info->device->mutex); -cleanup: - if (retval < 0) { - kfree(private_data); + if (retval < 0) comedi_free_board_minor(minor); - } return retval; } static void comedi_auto_unconfig(struct device *hardware_device) { - unsigned *minor = (unsigned *)dev_get_drvdata(hardware_device); - if (minor == NULL) - return; - - BUG_ON(*minor >= COMEDI_NUM_BOARD_MINORS); + int minor; - comedi_free_board_minor(*minor); - dev_set_drvdata(hardware_device, NULL); - kfree(minor); + if (hardware_device == NULL) + return; + minor = comedi_find_board_minor(hardware_device); + if (minor < 0) + return; + BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); + comedi_free_board_minor(minor); } int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name) diff --git a/drivers/staging/comedi/internal.h b/drivers/staging/comedi/internal.h index 434ce3433368..4208fb4cf0ff 100644 --- a/drivers/staging/comedi/internal.h +++ b/drivers/staging/comedi/internal.h @@ -7,6 +7,7 @@ int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); int comedi_alloc_board_minor(struct device *hardware_device); void comedi_free_board_minor(unsigned minor); +int comedi_find_board_minor(struct device *hardware_device); void comedi_reset_async_buf(struct comedi_async *async); int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size); -- GitLab From ede3e03c6d28bc3aca30206995fec585031698af Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 3 Jan 2013 12:15:26 +0000 Subject: [PATCH 1510/1799] staging: comedi: Kconfig: COMEDI_NI_AT_A2150 should select COMEDI_FC commit 34ffb33e09132401872fe79e95c30824ce194d23 upstream. The 'ni_at_a2150' module links to `cfc_write_to_buffer` in the 'comedi_fc' module, so selecting 'COMEDI_NI_AT_A2150' in the kernel config needs to also select 'COMEDI_FC'. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 12c691d90900..f11cfc870129 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -424,6 +424,7 @@ config COMEDI_ADQ12B config COMEDI_NI_AT_A2150 tristate "NI AT-A2150 ISA card support" + select COMEDI_FC depends on COMEDI_NI_COMMON depends on VIRT_TO_BUS default N -- GitLab From 828b18866ce0907fdb67afe143d5d851deb9fec6 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 7 Nov 2012 10:31:30 -0500 Subject: [PATCH 1511/1799] USB: fix endpoint-disabling for failed config changes commit 36caff5d795429c572443894e8789c2150dd796b upstream. This patch (as1631) fixes a bug that shows up when a config change fails for a device under an xHCI controller. The controller needs to be told to disable the endpoints that have been enabled for the new config. The existing code does this, but before storing the information about which endpoints were enabled! As a result, any second attempt to install the new config is doomed to fail because xhci-hcd will refuse to enable an endpoint that is already enabled. The patch optimistically initializes the new endpoints' device structures before asking the device to switch to the new config. If the request fails then the endpoint information is already stored, so we can use usb_hcd_alloc_bandwidth() to disable the endpoints with no trouble. The rest of the error path is slightly more complex now; we have to disable the new interfaces and call put_device() rather than simply deallocating them. Signed-off-by: Alan Stern Reported-and-tested-by: Matthias Schniedermeyer CC: Sarah Sharp Signed-off-by: Greg Kroah-Hartman [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 53 ++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index ef116a55afa4..ab11ca3c79a5 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1770,28 +1770,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration) goto free_interfaces; } - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_CONFIGURATION, 0, configuration, 0, - NULL, 0, USB_CTRL_SET_TIMEOUT); - if (ret < 0) { - /* All the old state is gone, so what else can we do? - * The device is probably useless now anyway. - */ - cp = NULL; - } - - dev->actconfig = cp; - if (!cp) { - usb_set_device_state(dev, USB_STATE_ADDRESS); - usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); - mutex_unlock(hcd->bandwidth_mutex); - usb_autosuspend_device(dev); - goto free_interfaces; - } - mutex_unlock(hcd->bandwidth_mutex); - usb_set_device_state(dev, USB_STATE_CONFIGURED); - - /* Initialize the new interface structures and the + /* + * Initialize the new interface structures and the * hc/hcd/usbcore interface/endpoint state. */ for (i = 0; i < nintf; ++i) { @@ -1835,6 +1815,35 @@ int usb_set_configuration(struct usb_device *dev, int configuration) } kfree(new_interfaces); + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_CONFIGURATION, 0, configuration, 0, + NULL, 0, USB_CTRL_SET_TIMEOUT); + if (ret < 0 && cp) { + /* + * All the old state is gone, so what else can we do? + * The device is probably useless now anyway. + */ + usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); + for (i = 0; i < nintf; ++i) { + usb_disable_interface(dev, cp->interface[i], true); + put_device(&cp->interface[i]->dev); + cp->interface[i] = NULL; + } + cp = NULL; + } + + dev->actconfig = cp; + mutex_unlock(hcd->bandwidth_mutex); + + if (!cp) { + usb_set_device_state(dev, USB_STATE_ADDRESS); + + /* Leave LPM disabled while the device is unconfigured. */ + usb_autosuspend_device(dev); + return ret; + } + usb_set_device_state(dev, USB_STATE_CONFIGURED); + if (cp->string == NULL && !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) cp->string = usb_cache_string(dev, cp->desc.iConfiguration); -- GitLab From 6723972ab0cedb96477d47fb197091b487921322 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 17 Jan 2013 08:51:56 -0800 Subject: [PATCH 1512/1799] Linux 3.4.26 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0913881e4568..2d84a1d4d261 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 25 +SUBLEVEL = 26 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 8630dda5a013d1b39280ec9bda2ee9b7e99b68c1 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Fri, 16 Nov 2012 10:46:20 +0100 Subject: [PATCH 1513/1799] sh: Fix FDPIC binary loader commit 4a71997a3279a339e7336ea5d0cd27282e2dea44 upstream. Ensure that the aux table is properly initialized, even when optional features are missing. Without this, the FDPIC loader did not work. This was meant to be included in commit d5ab780305bb6d60a7b5a74f18cf84eb6ad153b1. Signed-off-by: Thomas Schwinge Signed-off-by: Paul Mundt Signed-off-by: Greg Kroah-Hartman --- arch/sh/include/asm/elf.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/include/asm/elf.h b/arch/sh/include/asm/elf.h index f38112be67d2..978b7fd6d474 100644 --- a/arch/sh/include/asm/elf.h +++ b/arch/sh/include/asm/elf.h @@ -202,9 +202,9 @@ extern void __kernel_vsyscall; if (vdso_enabled) \ NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE); \ else \ - NEW_AUX_ENT(AT_IGNORE, 0); + NEW_AUX_ENT(AT_IGNORE, 0) #else -#define VSYSCALL_AUX_ENT +#define VSYSCALL_AUX_ENT NEW_AUX_ENT(AT_IGNORE, 0) #endif /* CONFIG_VSYSCALL */ #ifdef CONFIG_SH_FPU -- GitLab From e86f92f7eaeb01b071d2ca2a473c1efff6e9db68 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 21 Dec 2012 10:58:14 -0800 Subject: [PATCH 1514/1799] tcm_fc: Do not indicate retry capability to initiators commit f2eeba214bcd0215b7f558cab6420e5fd153042b upstream. When generating a PRLI response to an initiator, clear the FCP_SPPF_RETRY bit in the response. Signed-off-by: Mark Rustad Reviewed-by: Bhanu Prakash Gollapudi Acked by Robert Love Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/tcm_fc/tfc_sess.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index a426c4020be0..34d7b251986a 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -397,10 +397,10 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, /* * OR in our service parameters with other provider (initiator), if any. - * TBD XXX - indicate RETRY capability? */ fill: fcp_parm = ntohl(spp->spp_params); + fcp_parm &= ~FCP_SPPF_RETRY; spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); return FC_SPP_RESP_ACK; } -- GitLab From 4b77fd473bf78ec6ddd7c6f4d1f03582a4ec34b9 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 21 Dec 2012 10:58:19 -0800 Subject: [PATCH 1515/1799] tcm_fc: Do not report target role when target is not defined commit edec8dfefa1f372b2dd8197da555352e76a10c03 upstream. Clear the target role when no target is provided for the node performing a PRLI. Signed-off-by: Mark Rustad Reviewed-by: Bhanu Prakash Gollapudi Acked by Robert Love Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/tcm_fc/tfc_sess.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 34d7b251986a..9249998a837a 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -356,11 +356,11 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, tport = ft_tport_create(rdata->local_port); if (!tport) - return 0; /* not a target for this local port */ + goto not_target; /* not a target for this local port */ acl = ft_acl_get(tport->tpg, rdata); if (!acl) - return 0; + goto not_target; /* no target for this remote */ if (!rspp) goto fill; @@ -403,6 +403,12 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, fcp_parm &= ~FCP_SPPF_RETRY; spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); return FC_SPP_RESP_ACK; + +not_target: + fcp_parm = ntohl(spp->spp_params); + fcp_parm &= ~FCP_SPPF_TARG_FCN; + spp->spp_params = htonl(fcp_parm); + return 0; } /** -- GitLab From aa16959322c2c096ac050d8a970e1cf2d2b1cc35 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 2 Jan 2013 12:47:59 -0800 Subject: [PATCH 1516/1799] target: Release se_cmd when LUN lookup fails for TMR commit 5a3b6fc0092c5f8dee7820064ee54d2631d48573 upstream. When transport_lookup_tmr_lun() fails and we return a task management response from target_complete_tmr_failure(), we need to call transport_cmd_check_stop_to_fabric() to release the last ref to the cmd after calling se_tfo->queue_tm_rsp(), or else we will never remove the failed TMR from the session command list (and we'll end up waiting forever when trying to tear down the session). (nab: Fix minor compile breakage) Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_transport.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 69f3f7d53a04..f52e5a0041b4 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1748,6 +1748,8 @@ static void target_complete_tmr_failure(struct work_struct *work) se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; se_cmd->se_tfo->queue_tm_rsp(se_cmd); + + transport_cmd_check_stop_to_fabric(se_cmd); } /** -- GitLab From 2017a7c8ee63e678c20479e24416aac20a8899dc Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 14 Jan 2013 16:55:55 +0100 Subject: [PATCH 1517/1799] s390/time: fix sched_clock() overflow commit ed4f20943cd4c7b55105c04daedf8d63ab6d499c upstream. Converting a 64 Bit TOD format value to nanoseconds means that the value must be divided by 4.096. In order to achieve that we multiply with 125 and divide by 512. When used within sched_clock() this triggers an overflow after appr. 417 days. Resulting in a sched_clock() return value that is much smaller than previously and therefore may cause all sort of weird things in subsystems that rely on a monotonic sched_clock() behaviour. To fix this implement a tod_to_ns() helper function which converts TOD values without overflow and call this function from both places that open coded the conversion: sched_clock() and kvm_s390_handle_wait(). Reviewed-by: Martin Schwidefsky Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/include/asm/timex.h | 28 ++++++++++++++++++++++++++++ arch/s390/kernel/time.c | 2 +- arch/s390/kvm/interrupt.c | 2 +- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index c447a27a7fdb..945b7cdf4934 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -137,4 +137,32 @@ static inline unsigned long long get_clock_monotonic(void) return get_clock_xt() - sched_clock_base_cc; } +/** + * tod_to_ns - convert a TOD format value to nanoseconds + * @todval: to be converted TOD format value + * Returns: number of nanoseconds that correspond to the TOD format value + * + * Converting a 64 Bit TOD format value to nanoseconds means that the value + * must be divided by 4.096. In order to achieve that we multiply with 125 + * and divide by 512: + * + * ns = (todval * 125) >> 9; + * + * In order to avoid an overflow with the multiplication we can rewrite this. + * With a split todval == 2^32 * th + tl (th upper 32 bits, tl lower 32 bits) + * we end up with + * + * ns = ((2^32 * th + tl) * 125 ) >> 9; + * -> ns = (2^23 * th * 125) + ((tl * 125) >> 9); + * + */ +static inline unsigned long long tod_to_ns(unsigned long long todval) +{ + unsigned long long ns; + + ns = ((todval >> 32) << 23) * 125; + ns += ((todval & 0xffffffff) * 125) >> 9; + return ns; +} + #endif diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index d4e1cb1dbcd1..c5531dbc8b2f 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -64,7 +64,7 @@ static DEFINE_PER_CPU(struct clock_event_device, comparators); */ unsigned long long notrace __kprobes sched_clock(void) { - return (get_clock_monotonic() * 125) >> 9; + return tod_to_ns(get_clock_monotonic()); } /* diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 2d9f9a72bb81..10e13b331d38 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -390,7 +390,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) return 0; } - sltime = ((vcpu->arch.sie_block->ckc - now)*125)>>9; + sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime); -- GitLab From d2e42ef98559ce48a516d40b64a7a489676d69f0 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 14 Nov 2012 20:43:31 +0000 Subject: [PATCH 1518/1799] x86/Sandy Bridge: reserve pages when integrated graphics is present commit a9acc5365dbda29f7be2884efb63771dc24bd815 upstream. SNB graphics devices have a bug that prevent them from accessing certain memory ranges, namely anything below 1M and in the pages listed in the table. So reserve those at boot if set detect a SNB gfx device on the CPU to avoid GPU hangs. Stephane Marchesin had a similar patch to the page allocator awhile back, but rather than reserving pages up front, it leaked them at allocation time. [ hpa: made a number of stylistic changes, marked arrays as static const, and made less verbose; use "memblock=debug" for full verbosity. ] Signed-off-by: Jesse Barnes Signed-off-by: H. Peter Anvin Cc: CAI Qian Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/setup.c | 78 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index ae98dbb5b8c1..d289ee73a248 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -620,6 +620,81 @@ static __init void reserve_ibft_region(void) static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; +static bool __init snb_gfx_workaround_needed(void) +{ + int i; + u16 vendor, devid; + static const u16 snb_ids[] = { + 0x0102, + 0x0112, + 0x0122, + 0x0106, + 0x0116, + 0x0126, + 0x010a, + }; + + /* Assume no if something weird is going on with PCI */ + if (!early_pci_allowed()) + return false; + + vendor = read_pci_config_16(0, 2, 0, PCI_VENDOR_ID); + if (vendor != 0x8086) + return false; + + devid = read_pci_config_16(0, 2, 0, PCI_DEVICE_ID); + for (i = 0; i < ARRAY_SIZE(snb_ids); i++) + if (devid == snb_ids[i]) + return true; + + return false; +} + +/* + * Sandy Bridge graphics has trouble with certain ranges, exclude + * them from allocation. + */ +static void __init trim_snb_memory(void) +{ + static const unsigned long bad_pages[] = { + 0x20050000, + 0x20110000, + 0x20130000, + 0x20138000, + 0x40004000, + }; + int i; + + if (!snb_gfx_workaround_needed()) + return; + + printk(KERN_DEBUG "reserving inaccessible SNB gfx pages\n"); + + /* + * Reserve all memory below the 1 MB mark that has not + * already been reserved. + */ + memblock_reserve(0, 1<<20); + + for (i = 0; i < ARRAY_SIZE(bad_pages); i++) { + if (memblock_reserve(bad_pages[i], PAGE_SIZE)) + printk(KERN_WARNING "failed to reserve 0x%08lx\n", + bad_pages[i]); + } +} + +/* + * Here we put platform-specific memory range workarounds, i.e. + * memory known to be corrupt or otherwise in need to be reserved on + * specific platforms. + * + * If this gets used more widely it could use a real dispatch mechanism. + */ +static void __init trim_platform_memory_ranges(void) +{ + trim_snb_memory(); +} + static void __init trim_bios_range(void) { /* @@ -640,6 +715,7 @@ static void __init trim_bios_range(void) * take them out. */ e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1); + sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); } @@ -919,6 +995,8 @@ void __init setup_arch(char **cmdline_p) setup_trampolines(); + trim_platform_memory_ranges(); + init_gbpages(); /* max_pfn_mapped is updated here */ -- GitLab From ee415da5538413edc5d63c07899abc0b2b36bc54 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Fri, 4 Jan 2013 17:02:18 +0100 Subject: [PATCH 1519/1799] ALSA: usb - fix race in creation of M-Audio Fast track pro driver commit b98ae2729dea161edc96c9d177459b6c28bcbba5 upstream. A patch in the 3.2 kernel caused regression with hotplugging the M-Audio Fast track pro, or sound after suspend. I don't have the device so I haven't done a full analysis, but it seems userspace (both udev and pulseaudio) got confused when a card was created, immediately destroyed, and then created again. However, at least one person in the bug report (martin djfun) reports that this patch resolves the issue for him. It also leaves a message in the log: "snd-usb-audio: probe of 1-1.1:1.1 failed with error -5" which is a bit misleading. It is better than non-working audio, but maybe there's a more elegant solution? BugLink: https://bugs.launchpad.net/bugs/1095315 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Cc: CAI Qian Signed-off-by: Greg Kroah-Hartman --- sound/usb/quirks.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 27817266867a..c46171a2bf2f 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -387,11 +387,13 @@ static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev) * rules */ err = usb_driver_set_configuration(dev, 2); - if (err < 0) { + if (err < 0) snd_printdd("error usb_driver_set_configuration: %d\n", err); - return -ENODEV; - } + /* Always return an error, so that we stop creating a device + that will just be destroyed and recreated with a new + configuration */ + return -ENODEV; } else snd_printk(KERN_INFO "usb-audio: Fast Track Pro config OK\n"); -- GitLab From 5c9611090f9d110a245cc54ddb9bb31b2cc2965f Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 14 Nov 2012 22:22:05 -0500 Subject: [PATCH 1520/1799] ext4: init pagevec in ext4_da_block_invalidatepages commit 66bea92c69477a75a5d37b9bfed5773c92a3c4b4 upstream. ext4_da_block_invalidatepages is missing a pagevec_init(), which means that pvec->cold contains random garbage. This affects whether the page goes to the front or back of the LRU when ->cold makes it to free_hot_cold_page() Reviewed-by: Lukas Czerner Reviewed-by: Carlos Maiolino Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" Signed-off-by: CAI Qian Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index dcd08e485762..a0d7e2617fda 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1424,6 +1424,8 @@ static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd) index = mpd->first_page; end = mpd->next_page - 1; + + pagevec_init(&pvec, 0); while (index <= end) { nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE); if (nr_pages == 0) -- GitLab From ced8dfbc6b44c7b14204a13ff95f22bdee52578f Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 9 Jun 2012 10:53:16 +0000 Subject: [PATCH 1521/1799] r8169: avoid NAPI scheduling delay. commit 7dbb491878a2c51d372a8890fa45a8ff80358af1 upstream. While reworking the r8169 driver a few months ago to perform the smallest amount of work in the irq handler, I took care of avoiding any irq mask register operation in the slow work dedicated user context thread. The slow work thread scheduled an extra round of NAPI work which would ultimately set the irq mask register as required, thus keeping such irq mask operations in the NAPI handler. It would eventually race with the irq handler and delay NAPI execution for - assuming no further irq - a whole ksoftirqd period. Mildly a problem for rare link changes or corner case PCI events. The race was always lost after the last bh disabling lock had been removed from the work thread and people started wondering where those pesky "NOHZ: local_softirq_pending 08" messages came from. Actually the irq mask register _can_ be set up directly in the slow work thread. Signed-off-by: Francois Romieu Reported-by: Dave Jones Tested-by: Marc Dionne Cc: Thomas Gleixner Cc: Hayes Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 0dc70c21767e..06ee243d41a8 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -5516,11 +5516,7 @@ static void rtl_slow_event_work(struct rtl8169_private *tp) if (status & LinkChg) __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true); - napi_disable(&tp->napi); - rtl_irq_disable(tp); - - napi_enable(&tp->napi); - napi_schedule(&tp->napi); + rtl_irq_enable_all(tp); } static void rtl_task(struct work_struct *work) -- GitLab From 92a7389317838f3338466df0c0e3d23ad33cb1f4 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 4 Dec 2012 23:43:57 -0800 Subject: [PATCH 1522/1799] target: Add link_magic for fabric allow_link destination target_items commit 0ff8754981261a80f4b77db2536dfea92c2d4539 upstream. This patch adds [dev,lun]_link_magic value assignment + checks within generic target_fabric_port_link() and target_fabric_mappedlun_link() code to ensure destination config_item *target_item sent from configfs_symlink() -> config_item_operations->allow_link() is the underlying se_device->dev_group and se_lun->lun_group that we expect to symlink. Reported-by: Sebastian Andrzej Siewior Cc: Sebastian Andrzej Siewior Signed-off-by: Nicholas Bellinger Signed-off-by: CAI Qian Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_device.c | 1 + drivers/target/target_core_fabric_configfs.c | 12 ++++++++++++ drivers/target/target_core_tpg.c | 1 + drivers/target/target_core_transport.c | 1 + include/target/target_core_base.h | 4 ++++ 5 files changed, 19 insertions(+) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 4df8022fe3c8..26c62f059754 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1665,6 +1665,7 @@ int core_dev_setup_virtual_lun0(void) ret = PTR_ERR(dev); goto out; } + dev->dev_link_magic = SE_DEV_LINK_MAGIC; se_dev->se_dev_ptr = dev; g_lun0_dev = dev; diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 405cc98eaed6..b009b89d2fb4 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -72,6 +72,12 @@ static int target_fabric_mappedlun_link( struct se_portal_group *se_tpg; struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s; int ret = 0, lun_access; + + if (lun->lun_link_magic != SE_LUN_LINK_MAGIC) { + pr_err("Bad lun->lun_link_magic, not a valid lun_ci pointer:" + " %p to struct lun: %p\n", lun_ci, lun); + return -EFAULT; + } /* * Ensure that the source port exists */ @@ -746,6 +752,12 @@ static int target_fabric_port_link( struct target_fabric_configfs *tf; int ret; + if (dev->dev_link_magic != SE_DEV_LINK_MAGIC) { + pr_err("Bad dev->dev_link_magic, not a valid se_dev_ci pointer:" + " %p to struct se_device: %p\n", se_dev_ci, dev); + return -EFAULT; + } + tpg_ci = &lun_ci->ci_parent->ci_group->cg_item; se_tpg = container_of(to_config_group(tpg_ci), struct se_portal_group, tpg_group); diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index e320ec24aa1b..ba537b6fd85e 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -677,6 +677,7 @@ int core_tpg_register( for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { lun = se_tpg->tpg_lun_list[i]; lun->unpacked_lun = i; + lun->lun_link_magic = SE_LUN_LINK_MAGIC; lun->lun_status = TRANSPORT_LUN_STATUS_FREE; atomic_set(&lun->lun_acl_count, 0); init_completion(&lun->lun_shutdown_comp); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index f52e5a0041b4..f687892b00be 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1341,6 +1341,7 @@ struct se_device *transport_add_device_to_core_hba( dev->se_hba = hba; dev->se_sub_dev = se_dev; dev->transport = transport; + dev->dev_link_magic = SE_DEV_LINK_MAGIC; INIT_LIST_HEAD(&dev->dev_list); INIT_LIST_HEAD(&dev->dev_sep_list); INIT_LIST_HEAD(&dev->dev_tmr_list); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 3ad5b33ee328..569c28236b09 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -779,6 +779,8 @@ struct se_subsystem_dev { }; struct se_device { +#define SE_DEV_LINK_MAGIC 0xfeeddeef + u32 dev_link_magic; /* RELATIVE TARGET PORT IDENTIFER Counter */ u16 dev_rpti_counter; /* Used for SAM Task Attribute ordering */ @@ -869,6 +871,8 @@ struct se_port_stat_grps { }; struct se_lun { +#define SE_LUN_LINK_MAGIC 0xffff7771 + u32 lun_link_magic; /* See transport_lun_status_table */ enum transport_lun_status_table lun_status; u32 lun_access; -- GitLab From 5ad7813d5a6ca36e36d41ebfb27ffaf3f3006b45 Mon Sep 17 00:00:00 2001 From: Tom Mingarelli Date: Tue, 20 Nov 2012 19:43:17 +0000 Subject: [PATCH 1523/1799] intel-iommu: Prevent devices with RMRRs from being placed into SI Domain commit ea2447f700cab264019b52e2b417d689e052dcfd upstream. This patch is to prevent non-USB devices that have RMRRs associated with them from being placed into the SI Domain during init. This fixes the issue where the RMRR info for devices being placed in and out of the SI Domain gets lost. Signed-off-by: Thomas Mingarelli Tested-by: Shuah Khan Reviewed-by: Donald Dutile Reviewed-by: Alex Williamson Signed-off-by: Joerg Roedel Cc: CAI Qian Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel-iommu.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 9c34db8e7295..be6660696c9c 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2321,8 +2321,39 @@ static int domain_add_dev_info(struct dmar_domain *domain, return 0; } +static bool device_has_rmrr(struct pci_dev *dev) +{ + struct dmar_rmrr_unit *rmrr; + int i; + + for_each_rmrr_units(rmrr) { + for (i = 0; i < rmrr->devices_cnt; i++) { + /* + * Return TRUE if this RMRR contains the device that + * is passed in. + */ + if (rmrr->devices[i] == dev) + return true; + } + } + return false; +} + static int iommu_should_identity_map(struct pci_dev *pdev, int startup) { + + /* + * We want to prevent any device associated with an RMRR from + * getting placed into the SI Domain. This is done because + * problems exist when devices are moved in and out of domains + * and their respective RMRR info is lost. We exempt USB devices + * from this process due to their usage of RMRRs that are known + * to not be needed after BIOS hand-off to OS. + */ + if (device_has_rmrr(pdev) && + (pdev->class >> 8) != PCI_CLASS_SERIAL_USB) + return 0; + if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev)) return 1; -- GitLab From 6365d1039ebcdd214a891df7406e709db4d3fc30 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Tue, 4 Dec 2012 06:00:17 +0000 Subject: [PATCH 1524/1799] igb: release already assigned MSI-X interrupts if setup fails commit 52285b762b3681669215bf1d17ca6143448ab7d3 upstream. During MSI-X setup the system might run out of vectors. If this happens the already assigned vectors for this NIC should be freed before trying the disable MSI-X. Failing to do so results in the following oops. kernel BUG at drivers/pci/msi.c:341! [...] Call Trace: [] pci_disable_msix+0x3d/0x60 [] igb_reset_interrupt_capability+0x27/0x5c [igb] [] igb_clear_interrupt_scheme+0x26/0x2d [igb] [] igb_request_irq+0x73/0x297 [igb] [] __igb_open+0xc8/0x223 [igb] [] igb_open+0x13/0x15 [igb] [] __dev_open+0xbf/0x120 [] __dev_change_flags+0xa1/0x180 [] dev_change_flags+0x28/0x70 [] devinet_ioctl+0x5b7/0x620 [] inet_ioctl+0x88/0xa0 [] sock_do_ioctl+0x30/0x70 [] sock_ioctl+0x72/0x270 [] do_vfs_ioctl+0x8c/0x340 [] sys_ioctl+0xa1/0xb0 [] system_call_fastpath+0x16/0x1b Code: 48 89 df e8 1f 40 ed ff 4d 39 e6 49 8b 45 10 75 b6 48 83 c4 18 5b 41 5c 41 5d 41 5e 41 5f c9 c3 48 8b 7b 20 e8 3e 91 db ff eb ae <0f> 0b eb fe 0f 1f 84 00 00 00 00 00 55 48 89 e5 0f 1f 44 00 00 RIP [] free_msi_irqs+0x124/0x130 RSP Signed-off-by: Stefan Assmann Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: Abdallah Chatila --- drivers/net/ethernet/intel/igb/igb_main.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 8683ca4748c8..6b4f0148ee6c 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -951,17 +951,18 @@ static int igb_request_msix(struct igb_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct e1000_hw *hw = &adapter->hw; - int i, err = 0, vector = 0; + int i, err = 0, vector = 0, free_vector = 0; err = request_irq(adapter->msix_entries[vector].vector, igb_msix_other, 0, netdev->name, adapter); if (err) - goto out; - vector++; + goto err_out; for (i = 0; i < adapter->num_q_vectors; i++) { struct igb_q_vector *q_vector = adapter->q_vector[i]; + vector++; + q_vector->itr_register = hw->hw_addr + E1000_EITR(vector); if (q_vector->rx.ring && q_vector->tx.ring) @@ -980,13 +981,22 @@ static int igb_request_msix(struct igb_adapter *adapter) igb_msix_ring, 0, q_vector->name, q_vector); if (err) - goto out; - vector++; + goto err_free; } igb_configure_msix(adapter); return 0; -out: + +err_free: + /* free already assigned IRQs */ + free_irq(adapter->msix_entries[free_vector++].vector, adapter); + + vector--; + for (i = 0; i < vector; i++) { + free_irq(adapter->msix_entries[free_vector++].vector, + adapter->q_vector[i]); + } +err_out: return err; } -- GitLab From d239fdb0d4d3088b5161f0c92ed929143b45d830 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Thu, 23 Feb 2012 12:56:26 +0100 Subject: [PATCH 1525/1799] drbd: add missing part_round_stats to _drbd_start_io_acct commit 72585d2428fa3a0daab02ebad1f41e5ef517dbaa upstream. Without this, iostat frequently sees bogus svctime and >= 100% "utilization". Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg Cc: Raoul Bhatia Signed-off-by: Greg Kroah-Hartman --- drivers/block/drbd/drbd_req.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 4a0f314086e5..be984e073666 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -37,6 +37,7 @@ static void _drbd_start_io_acct(struct drbd_conf *mdev, struct drbd_request *req const int rw = bio_data_dir(bio); int cpu; cpu = part_stat_lock(); + part_round_stats(cpu, &mdev->vdisk->part0); part_stat_inc(cpu, &mdev->vdisk->part0, ios[rw]); part_stat_add(cpu, &mdev->vdisk->part0, sectors[rw], bio_sectors(bio)); part_inc_in_flight(&mdev->vdisk->part0, rw); -- GitLab From ffe288276822348a3717e11cee6646d856a409c4 Mon Sep 17 00:00:00 2001 From: Matt Wilson Date: Tue, 15 Jan 2013 13:21:27 +0000 Subject: [PATCH 1526/1799] xen/grant-table: correctly initialize grant table version 1 commit d0b4d64aadb9f4a90669848de9ef3819050a98cd upstream. Commit 85ff6acb075a484780b3d763fdf41596d8fc0970 (xen/granttable: Grant tables V2 implementation) changed the GREFS_PER_GRANT_FRAME macro from a constant to a conditional expression. The expression depends on grant_table_version being appropriately set. Unfortunately, at init time grant_table_version will be 0. The GREFS_PER_GRANT_FRAME conditional expression checks for "grant_table_version == 1", and therefore returns the number of grant references per frame for v2. This causes gnttab_init() to allocate fewer pages for gnttab_list, as a frame can old half the number of v2 entries than v1 entries. After gnttab_resume() is called, grant_table_version is appropriately set. nr_init_grefs will then be miscalculated and gnttab_free_count will hold a value larger than the actual number of free gref entries. If a guest is heavily utilizing improperly initialized v1 grant tables, memory corruption can occur. One common manifestation is corruption of the vmalloc list, resulting in a poisoned pointer derefrence when accessing /proc/meminfo or /proc/vmallocinfo: [ 40.770064] BUG: unable to handle kernel paging request at 0000200200001407 [ 40.770083] IP: [] get_vmalloc_info+0x70/0x110 [ 40.770102] PGD 0 [ 40.770107] Oops: 0000 [#1] SMP [ 40.770114] CPU 10 This patch introduces a static variable, grefs_per_grant_frame, to cache the calculated value. gnttab_init() now calls gnttab_request_version() early so that grant_table_version and grefs_per_grant_frame can be appropriately set. A few BUG_ON()s have been added to prevent this type of bug from reoccurring in the future. Signed-off-by: Matt Wilson Reviewed-and-Tested-by: Steven Noonan Acked-by: Ian Campbell Cc: Konrad Rzeszutek Wilk Cc: Annie Li Cc: xen-devel@lists.xen.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/xen/grant-table.c | 48 +++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index fda491cd53c1..7e34beed9ea9 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -53,10 +53,6 @@ /* External tools reserve first few grant table entries. */ #define NR_RESERVED_ENTRIES 8 #define GNTTAB_LIST_END 0xffffffff -#define GREFS_PER_GRANT_FRAME \ -(grant_table_version == 1 ? \ -(PAGE_SIZE / sizeof(struct grant_entry_v1)) : \ -(PAGE_SIZE / sizeof(union grant_entry_v2))) static grant_ref_t **gnttab_list; static unsigned int nr_grant_frames; @@ -151,6 +147,7 @@ static struct gnttab_ops *gnttab_interface; static grant_status_t *grstatus; static int grant_table_version; +static int grefs_per_grant_frame; static struct gnttab_free_callback *gnttab_free_callback_list; @@ -679,12 +676,14 @@ static int grow_gnttab_list(unsigned int more_frames) unsigned int new_nr_grant_frames, extra_entries, i; unsigned int nr_glist_frames, new_nr_glist_frames; + BUG_ON(grefs_per_grant_frame == 0); + new_nr_grant_frames = nr_grant_frames + more_frames; - extra_entries = more_frames * GREFS_PER_GRANT_FRAME; + extra_entries = more_frames * grefs_per_grant_frame; - nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; + nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; new_nr_glist_frames = - (new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; + (new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; for (i = nr_glist_frames; i < new_nr_glist_frames; i++) { gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC); if (!gnttab_list[i]) @@ -692,12 +691,12 @@ static int grow_gnttab_list(unsigned int more_frames) } - for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames; - i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++) + for (i = grefs_per_grant_frame * nr_grant_frames; + i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++) gnttab_entry(i) = i + 1; gnttab_entry(i) = gnttab_free_head; - gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames; + gnttab_free_head = grefs_per_grant_frame * nr_grant_frames; gnttab_free_count += extra_entries; nr_grant_frames = new_nr_grant_frames; @@ -799,7 +798,8 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs); static unsigned nr_status_frames(unsigned nr_grant_frames) { - return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP; + BUG_ON(grefs_per_grant_frame == 0); + return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP; } static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes) @@ -957,6 +957,7 @@ static void gnttab_request_version(void) rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); if (rc == 0 && gsv.version == 2) { grant_table_version = 2; + grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2); gnttab_interface = &gnttab_v2_ops; } else if (grant_table_version == 2) { /* @@ -969,17 +970,17 @@ static void gnttab_request_version(void) panic("we need grant tables version 2, but only version 1 is available"); } else { grant_table_version = 1; + grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1); gnttab_interface = &gnttab_v1_ops; } printk(KERN_INFO "Grant tables using version %d layout.\n", grant_table_version); } -int gnttab_resume(void) +static int gnttab_setup(void) { unsigned int max_nr_gframes; - gnttab_request_version(); max_nr_gframes = gnttab_max_grant_frames(); if (max_nr_gframes < nr_grant_frames) return -ENOSYS; @@ -1002,6 +1003,12 @@ int gnttab_resume(void) return 0; } +int gnttab_resume(void) +{ + gnttab_request_version(); + return gnttab_setup(); +} + int gnttab_suspend(void) { gnttab_interface->unmap_frames(); @@ -1013,9 +1020,10 @@ static int gnttab_expand(unsigned int req_entries) int rc; unsigned int cur, extra; + BUG_ON(grefs_per_grant_frame == 0); cur = nr_grant_frames; - extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / - GREFS_PER_GRANT_FRAME); + extra = ((req_entries + (grefs_per_grant_frame-1)) / + grefs_per_grant_frame); if (cur + extra > gnttab_max_grant_frames()) return -ENOSPC; @@ -1033,21 +1041,23 @@ int gnttab_init(void) unsigned int nr_init_grefs; int ret; + gnttab_request_version(); nr_grant_frames = 1; boot_max_nr_grant_frames = __max_nr_grant_frames(); /* Determine the maximum number of frames required for the * grant reference free list on the current hypervisor. */ + BUG_ON(grefs_per_grant_frame == 0); max_nr_glist_frames = (boot_max_nr_grant_frames * - GREFS_PER_GRANT_FRAME / RPP); + grefs_per_grant_frame / RPP); gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), GFP_KERNEL); if (gnttab_list == NULL) return -ENOMEM; - nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; + nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; for (i = 0; i < nr_glist_frames; i++) { gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); if (gnttab_list[i] == NULL) { @@ -1056,12 +1066,12 @@ int gnttab_init(void) } } - if (gnttab_resume() < 0) { + if (gnttab_setup() < 0) { ret = -ENODEV; goto ini_nomem; } - nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME; + nr_init_grefs = nr_grant_frames * grefs_per_grant_frame; for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) gnttab_entry(i) = i + 1; -- GitLab From df1ffc8ee5cefbadd7477dda7ba0facafa3853a7 Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Wed, 16 Jan 2013 12:00:55 +0000 Subject: [PATCH 1527/1799] xen: Fix stack corruption in xen_failsafe_callback for 32bit PVOPS guests. commit 9174adbee4a9a49d0139f5d71969852b36720809 upstream. This fixes CVE-2013-0190 / XSA-40 There has been an error on the xen_failsafe_callback path for failed iret, which causes the stack pointer to be wrong when entering the iret_exc error path. This can result in the kernel crashing. In the classic kernel case, the relevant code looked a little like: popl %eax # Error code from hypervisor jz 5f addl $16,%esp jmp iret_exc # Hypervisor said iret fault 5: addl $16,%esp # Hypervisor said segment selector fault Here, there are two identical addls on either option of a branch which appears to have been optimised by hoisting it above the jz, and converting it to an lea, which leaves the flags register unaffected. In the PVOPS case, the code looks like: popl_cfi %eax # Error from the hypervisor lea 16(%esp),%esp # Add $16 before choosing fault path CFI_ADJUST_CFA_OFFSET -16 jz 5f addl $16,%esp # Incorrectly adjust %esp again jmp iret_exc It is possible unprivileged userspace applications to cause this behaviour, for example by loading an LDT code selector, then changing the code selector to be not-present. At this point, there is a race condition where it is possible for the hypervisor to return back to userspace from an interrupt, fault on its own iret, and inject a failsafe_callback into the kernel. This bug has been present since the introduction of Xen PVOPS support in commit 5ead97c84 (xen: Core Xen implementation), in 2.6.23. Signed-off-by: Frediano Ziglio Signed-off-by: Andrew Cooper Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/entry_32.S | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 6d4f7ba227f6..2af4ccd88d16 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -1074,7 +1074,6 @@ ENTRY(xen_failsafe_callback) lea 16(%esp),%esp CFI_ADJUST_CFA_OFFSET -16 jz 5f - addl $16,%esp jmp iret_exc 5: pushl_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL -- GitLab From a4ee70a6e231c775460a7e1143cde6fc5ec7c03c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Tue, 15 Jan 2013 10:29:49 +0100 Subject: [PATCH 1528/1799] USB: option: add TP-LINK HSUPA Modem MA180 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 99beb2e9687ffd61c92a9875141eabe6f57a71b9 upstream. The driver description files gives these names to the vendor specific functions on this modem: Diagnostics VID_2357&PID_0201&MI_00 NMEA VID_2357&PID_0201&MI_01 Modem VID_2357&PID_0201&MI_03 Networkcard VID_2357&PID_0201&MI_04 Reported-by: Thomas Schäfer Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ba23ad55f41a..4ea00fa39c4c 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -449,6 +449,10 @@ static void option_instat_callback(struct urb *urb); #define PETATEL_VENDOR_ID 0x1ff4 #define PETATEL_PRODUCT_NP10T 0x600e +/* TP-LINK Incorporated products */ +#define TPLINK_VENDOR_ID 0x2357 +#define TPLINK_PRODUCT_MA180 0x0201 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -1311,6 +1315,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) }, { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, + { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- GitLab From fd426d3b60d656d3b0df7c5ee2cdcb0a4e6f8850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 17 Jan 2013 15:14:22 +0100 Subject: [PATCH 1529/1799] USB: option: blacklist network interface on ONDA MT8205 4G LTE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bjørn Mork commit 2291dff02e5f8c708a46a7c4c888f2c467e26642 upstream. The driver description files gives these names to the vendor specific functions on this modem: Diag VID_19D2&PID_0265&MI_00 NMEA VID_19D2&PID_0265&MI_01 AT cmd VID_19D2&PID_0265&MI_02 Modem VID_19D2&PID_0265&MI_03 Net VID_19D2&PID_0265&MI_04 Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 4ea00fa39c4c..0778cd098521 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -934,7 +934,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff), /* ONDA MT8205 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */ .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) }, -- GitLab From 51478116612441b178bc747b445e592586e1f817 Mon Sep 17 00:00:00 2001 From: chao bi Date: Wed, 12 Dec 2012 11:40:56 +0800 Subject: [PATCH 1530/1799] serial:ifx6x60:Delete SPI timer when shut down port commit 014b9b4ce84281ccb3d723c792bed19815f3571a upstream. When shut down SPI port, it's possible that MRDY has been asserted and a SPI timer was activated waiting for SRDY assert, in the case, it needs to delete this timer. Signed-off-by: Chen Jun Signed-off-by: channing Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ifx6x60.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 144cd3987d4c..17f587c5dbab 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -552,6 +552,7 @@ static void ifx_port_shutdown(struct tty_port *port) container_of(port, struct ifx_spi_device, tty_port); mrdy_set_low(ifx_dev); + del_timer(&ifx_dev->spi_timer); clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); tasklet_kill(&ifx_dev->io_work_tasklet); } -- GitLab From f6ffcce2ef152bebaeeed0cd9fd117e23a3c46ff Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 14 Jan 2013 20:09:26 +0100 Subject: [PATCH 1531/1799] tty: 8250_dw: Fix inverted arguments to serial_out in IRQ handler commit 68e56cb3a068f9c30971c6117fbbd1e32918e49e upstream. Signed-off-by: Maxime Ripard Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index f574eef3075f..b6dc908a24c6 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -79,7 +79,7 @@ static int dw8250_handle_irq(struct uart_port *p) } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { /* Clear the USR and write the LCR again. */ (void)p->serial_in(p, UART_USR); - p->serial_out(p, d->last_lcr, UART_LCR); + p->serial_out(p, UART_LCR, d->last_lcr); return 1; } -- GitLab From d7ddb69a53cd7c03c4c0660d13534214d2782c21 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Wed, 9 Jan 2013 22:23:32 +0100 Subject: [PATCH 1532/1799] staging: wlan-ng: Fix clamping of returned SSID length commit 811a37effdb11e54e1ff1ddaa944286c88f58487 upstream. Commit 2e254212 broke listing of available network names, since it clamped the length of the returned SSID to WLAN_BSSID_LEN (6) instead of WLAN_SSID_MAXLEN (32). https://bugzilla.kernel.org/show_bug.cgi?id=52501 Signed-off-by: Tormod Volden Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index c3bb05dd744f..4110a2f9425e 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -406,7 +406,7 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) /* SSID */ req->ssid.status = P80211ENUM_msgitem_status_data_ok; req->ssid.data.len = le16_to_cpu(item->ssid.len); - req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_BSSID_LEN); + req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN); memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); /* supported rates */ -- GitLab From 111be1d7aaa33a36bc3e426d882454ca9b966721 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 14 Jan 2013 01:29:17 +0000 Subject: [PATCH 1533/1799] staging: vt6656: Fix inconsistent structure packing commit 1ee4c55fc9620451b2a825d793042a7e0775391b upstream. vt6656 has several headers that use the #pragma pack(1) directive to enable structure packing, but never disable it. The layout of structures defined in other headers can then depend on which order the various headers are included in, breaking the One Definition Rule. In practice this resulted in crashes on x86_64 until the order of header inclusion was changed for some files in commit 11d404cb56ecd ('staging: vt6656: fix headers and add cfg80211.'). But we need a proper fix that won't be affected by future changes to the order of inclusion. This removes the #pragma pack(1) directives and adds __packed to the structure definitions for which packing appears to have been intended. Reported-and-tested-by: Malcolm Priestley Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/bssdb.h | 1 - drivers/staging/vt6656/int.h | 1 - drivers/staging/vt6656/iocmd.h | 33 ++++++++++++++++----------------- drivers/staging/vt6656/iowpa.h | 8 +++----- 4 files changed, 19 insertions(+), 24 deletions(-) diff --git a/drivers/staging/vt6656/bssdb.h b/drivers/staging/vt6656/bssdb.h index a8f97ebb659b..991ce3eecd8d 100644 --- a/drivers/staging/vt6656/bssdb.h +++ b/drivers/staging/vt6656/bssdb.h @@ -92,7 +92,6 @@ typedef struct tagSRSNCapObject { } SRSNCapObject, *PSRSNCapObject; // BSS info(AP) -#pragma pack(1) typedef struct tagKnownBSS { // BSS info BOOL bActive; diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h index a5d96b968176..27bc7f548abb 100644 --- a/drivers/staging/vt6656/int.h +++ b/drivers/staging/vt6656/int.h @@ -34,7 +34,6 @@ #include "device.h" /*--------------------- Export Definitions -------------------------*/ -#pragma pack(1) typedef struct tagSINTData { BYTE byTSR0; BYTE byPkt0; diff --git a/drivers/staging/vt6656/iocmd.h b/drivers/staging/vt6656/iocmd.h index 22710cef751d..ae6e2d237b20 100644 --- a/drivers/staging/vt6656/iocmd.h +++ b/drivers/staging/vt6656/iocmd.h @@ -95,13 +95,12 @@ typedef enum tagWZONETYPE { // Ioctl interface structure // Command structure // -#pragma pack(1) typedef struct tagSCmdRequest { u8 name[16]; void *data; u16 wResult; u16 wCmdCode; -} SCmdRequest, *PSCmdRequest; +} __packed SCmdRequest, *PSCmdRequest; // // Scan @@ -111,7 +110,7 @@ typedef struct tagSCmdScan { u8 ssid[SSID_MAXLEN + 2]; -} SCmdScan, *PSCmdScan; +} __packed SCmdScan, *PSCmdScan; // // BSS Join @@ -126,7 +125,7 @@ typedef struct tagSCmdBSSJoin { BOOL bPSEnable; BOOL bShareKeyAuth; -} SCmdBSSJoin, *PSCmdBSSJoin; +} __packed SCmdBSSJoin, *PSCmdBSSJoin; // // Zonetype Setting @@ -137,7 +136,7 @@ typedef struct tagSCmdZoneTypeSet { BOOL bWrite; WZONETYPE ZoneType; -} SCmdZoneTypeSet, *PSCmdZoneTypeSet; +} __packed SCmdZoneTypeSet, *PSCmdZoneTypeSet; typedef struct tagSWPAResult { char ifname[100]; @@ -145,7 +144,7 @@ typedef struct tagSWPAResult { u8 key_mgmt; u8 eap_type; BOOL authenticated; -} SWPAResult, *PSWPAResult; +} __packed SWPAResult, *PSWPAResult; typedef struct tagSCmdStartAP { @@ -157,7 +156,7 @@ typedef struct tagSCmdStartAP { BOOL bShareKeyAuth; u8 byBasicRate; -} SCmdStartAP, *PSCmdStartAP; +} __packed SCmdStartAP, *PSCmdStartAP; typedef struct tagSCmdSetWEP { @@ -167,7 +166,7 @@ typedef struct tagSCmdSetWEP { BOOL bWepKeyAvailable[WEP_NKEYS]; u32 auWepKeyLength[WEP_NKEYS]; -} SCmdSetWEP, *PSCmdSetWEP; +} __packed SCmdSetWEP, *PSCmdSetWEP; typedef struct tagSBSSIDItem { @@ -180,14 +179,14 @@ typedef struct tagSBSSIDItem { BOOL bWEPOn; u32 uRSSI; -} SBSSIDItem; +} __packed SBSSIDItem; typedef struct tagSBSSIDList { u32 uItem; SBSSIDItem sBSSIDList[0]; -} SBSSIDList, *PSBSSIDList; +} __packed SBSSIDList, *PSBSSIDList; typedef struct tagSNodeItem { @@ -208,7 +207,7 @@ typedef struct tagSNodeItem { u32 uTxAttempts; u16 wFailureRatio; -} SNodeItem; +} __packed SNodeItem; typedef struct tagSNodeList { @@ -216,7 +215,7 @@ typedef struct tagSNodeList { u32 uItem; SNodeItem sNodeList[0]; -} SNodeList, *PSNodeList; +} __packed SNodeList, *PSNodeList; typedef struct tagSCmdLinkStatus { @@ -229,7 +228,7 @@ typedef struct tagSCmdLinkStatus { u32 uChannel; u32 uLinkRate; -} SCmdLinkStatus, *PSCmdLinkStatus; +} __packed SCmdLinkStatus, *PSCmdLinkStatus; // // 802.11 counter @@ -247,7 +246,7 @@ typedef struct tagSDot11MIBCount { u32 ReceivedFragmentCount; u32 MulticastReceivedFrameCount; u32 FCSErrorCount; -} SDot11MIBCount, *PSDot11MIBCount; +} __packed SDot11MIBCount, *PSDot11MIBCount; @@ -355,13 +354,13 @@ typedef struct tagSStatMIBCount { u32 ullTxBroadcastBytes[2]; u32 ullTxMulticastBytes[2]; u32 ullTxDirectedBytes[2]; -} SStatMIBCount, *PSStatMIBCount; +} __packed SStatMIBCount, *PSStatMIBCount; typedef struct tagSCmdValue { u32 dwValue; -} SCmdValue, *PSCmdValue; +} __packed SCmdValue, *PSCmdValue; // // hostapd & viawget ioctl related @@ -431,7 +430,7 @@ struct viawget_hostapd_param { u8 ssid[32]; } scan_req; } u; -}; +} __packed; /*--------------------- Export Classes ----------------------------*/ diff --git a/drivers/staging/vt6656/iowpa.h b/drivers/staging/vt6656/iowpa.h index 959c8868f6e2..2522ddec718d 100644 --- a/drivers/staging/vt6656/iowpa.h +++ b/drivers/staging/vt6656/iowpa.h @@ -67,12 +67,11 @@ enum { -#pragma pack(1) typedef struct viawget_wpa_header { u8 type; u16 req_ie_len; u16 resp_ie_len; -} viawget_wpa_header; +} __packed viawget_wpa_header; struct viawget_wpa_param { u32 cmd; @@ -113,9 +112,8 @@ struct viawget_wpa_param { u8 *buf; } scan_results; } u; -}; +} __packed; -#pragma pack(1) struct viawget_scan_result { u8 bssid[6]; u8 ssid[32]; @@ -130,7 +128,7 @@ struct viawget_scan_result { int noise; int level; int maxrate; -}; +} __packed; /*--------------------- Export Classes ----------------------------*/ -- GitLab From 02f3169eee620366301c23d29622eb0f69046607 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 21 Jan 2013 11:47:35 -0800 Subject: [PATCH 1534/1799] Linux 3.4.27 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2d84a1d4d261..f139ce7b942a 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 26 +SUBLEVEL = 27 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From aa824d5b726d7d7d90331bcacc7807b83f02fa54 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 15 Jan 2013 16:17:54 +0000 Subject: [PATCH 1535/1799] drm/i915: Invalidate the relocation presumed_offsets along the slow path commit 262b6d363fcff16359c93bd58c297f961f6e6273 upstream. In the slow path, we are forced to copy the relocations prior to acquiring the struct mutex in order to handle pagefaults. We forgo copying the new offsets back into the relocation entries in order to prevent a recursive locking bug should we trigger a pagefault whilst holding the mutex for the reservations of the execbuffer. Therefore, we need to reset the presumed_offsets just in case the objects are rebound back into their old locations after relocating for this exexbuffer - if that were to happen we would assume the relocations were valid and leave the actual pointers to the kernels dangling, instant hang. Fixes regression from commit bcf50e2775bbc3101932d8e4ab8c7902aa4163b4 Author: Chris Wilson Date: Sun Nov 21 22:07:12 2010 +0000 drm/i915: Handle pagefaults in execbuffer user relocations Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55984 Signed-off-by: Chris Wilson Cc: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index de431942ded4..d4417e3cc3da 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -707,6 +707,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, total = 0; for (i = 0; i < count; i++) { struct drm_i915_gem_relocation_entry __user *user_relocs; + u64 invalid_offset = (u64)-1; + int j; user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr; @@ -717,6 +719,25 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, goto err; } + /* As we do not update the known relocation offsets after + * relocating (due to the complexities in lock handling), + * we need to mark them as invalid now so that we force the + * relocation processing next time. Just in case the target + * object is evicted and then rebound into its old + * presumed_offset before the next execbuffer - if that + * happened we would make the mistake of assuming that the + * relocations were valid. + */ + for (j = 0; j < exec[i].relocation_count; j++) { + if (copy_to_user(&user_relocs[j].presumed_offset, + &invalid_offset, + sizeof(invalid_offset))) { + ret = -EFAULT; + mutex_lock(&dev->struct_mutex); + goto err; + } + } + reloc_offset[i] = total; total += exec[i].relocation_count; } -- GitLab From d027bb39240aa55b86738508fb5612b9125a886f Mon Sep 17 00:00:00 2001 From: Hugh Daschbach Date: Fri, 4 Jan 2013 14:39:09 -0800 Subject: [PATCH 1536/1799] libata: ahci: Add support for Enmotus Bobcat device. commit 7f9c9f8e24590e7dcd26ca408458c43df5b83e61 upstream. Silicon does not support standard AHCI BAR assignment. Add vendor/device exception to force BAR 2. Signed-off-by: Hugh Daschbach Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ahci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 93cbc4484ccb..5d0fb6b51883 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -53,6 +53,7 @@ enum { AHCI_PCI_BAR_STA2X11 = 0, + AHCI_PCI_BAR_ENMOTUS = 2, AHCI_PCI_BAR_STANDARD = 5, }; @@ -407,6 +408,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* Asmedia */ { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1061 */ + /* Enmotus */ + { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, + /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, @@ -1079,9 +1083,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(&pdev->dev, "PDC42819 can only drive SATA devices with this driver\n"); - /* The Connext uses non-standard BAR */ + /* Both Connext and Enmotus devices use non-standard BARs */ if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) ahci_pci_bar = AHCI_PCI_BAR_STA2X11; + else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) + ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; /* acquire resources */ rc = pcim_enable_device(pdev); -- GitLab From f2a010040e2c368a76f7ea0ed6533f5779cb6b4b Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 14 Dec 2012 09:48:15 -0500 Subject: [PATCH 1537/1799] ftrace: Be first to run code modification on modules commit c1bf08ac26e92122faab9f6c32ea8aba94612dae upstream. If some other kernel subsystem has a module notifier, and adds a kprobe to a ftrace mcount point (now that kprobes work on ftrace points), when the ftrace notifier runs it will fail and disable ftrace, as well as kprobes that are attached to ftrace points. Here's the error: WARNING: at kernel/trace/ftrace.c:1618 ftrace_bug+0x239/0x280() Hardware name: Bochs Modules linked in: fat(+) stap_56d28a51b3fe546293ca0700b10bcb29__8059(F) nfsv4 auth_rpcgss nfs dns_resolver fscache xt_nat iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack lockd sunrpc ppdev parport_pc parport microcode virtio_net i2c_piix4 drm_kms_helper ttm drm i2c_core [last unloaded: bid_shared] Pid: 8068, comm: modprobe Tainted: GF 3.7.0-0.rc8.git0.1.fc19.x86_64 #1 Call Trace: [] warn_slowpath_common+0x7f/0xc0 [] ? __probe_kernel_read+0x46/0x70 [] ? 0xffffffffa017ffff [] ? 0xffffffffa017ffff [] warn_slowpath_null+0x1a/0x20 [] ftrace_bug+0x239/0x280 [] ftrace_process_locs+0x376/0x520 [] ftrace_module_notify+0x47/0x50 [] notifier_call_chain+0x4d/0x70 [] __blocking_notifier_call_chain+0x58/0x80 [] blocking_notifier_call_chain+0x16/0x20 [] sys_init_module+0x73/0x220 [] system_call_fastpath+0x16/0x1b ---[ end trace 9ef46351e53bbf80 ]--- ftrace failed to modify [] init_once+0x0/0x20 [fat] actual: cc:bb:d2:4b:e1 A kprobe was added to the init_once() function in the fat module on load. But this happened before ftrace could have touched the code. As ftrace didn't run yet, the kprobe system had no idea it was a ftrace point and simply added a breakpoint to the code (0xcc in the cc:bb:d2:4b:e1). Then when ftrace went to modify the location from a call to mcount/fentry into a nop, it didn't see a call op, but instead it saw the breakpoint op and not knowing what to do with it, ftrace shut itself down. The solution is to simply give the ftrace module notifier the max priority. This should have been done regardless, as the core code ftrace modification also happens very early on in boot up. This makes the module modification closer to core modification. Link: http://lkml.kernel.org/r/20130107140333.593683061@goodmis.org Acked-by: Masami Hiramatsu Reported-by: Frank Ch. Eigler Signed-off-by: Steven Rostedt --- 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 100b7fd1a64b..6b194d842b18 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3869,7 +3869,7 @@ static int ftrace_module_notify(struct notifier_block *self, struct notifier_block ftrace_module_nb = { .notifier_call = ftrace_module_notify, - .priority = 0, + .priority = INT_MAX, /* Run before anything that can use kprobes */ }; extern unsigned long __start_mcount_loc[]; -- GitLab From 9c5f1b49341154b579851425dabb32cb3aa9b5db Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Fri, 18 Jan 2013 23:56:39 +0200 Subject: [PATCH 1538/1799] evm: checking if removexattr is not a NULL commit a67adb997419fb53540d4a4f79c6471c60bc69b6 upstream. The following lines of code produce a kernel oops. fd = socket(PF_FILE, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); fchmod(fd, 0666); [ 139.922364] BUG: unable to handle kernel NULL pointer dereference at (null) [ 139.924982] IP: [< (null)>] (null) [ 139.924982] *pde = 00000000 [ 139.924982] Oops: 0000 [#5] SMP [ 139.924982] Modules linked in: fuse dm_crypt dm_mod i2c_piix4 serio_raw evdev binfmt_misc button [ 139.924982] Pid: 3070, comm: acpid Tainted: G D 3.8.0-rc2-kds+ #465 Bochs Bochs [ 139.924982] EIP: 0060:[<00000000>] EFLAGS: 00010246 CPU: 0 [ 139.924982] EIP is at 0x0 [ 139.924982] EAX: cf5ef000 EBX: cf5ef000 ECX: c143d600 EDX: c15225f2 [ 139.924982] ESI: cf4d2a1c EDI: cf4d2a1c EBP: cc02df10 ESP: cc02dee4 [ 139.924982] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 [ 139.924982] CR0: 80050033 CR2: 00000000 CR3: 0c059000 CR4: 000006d0 [ 139.924982] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 139.924982] DR6: ffff0ff0 DR7: 00000400 [ 139.924982] Process acpid (pid: 3070, ti=cc02c000 task=d7705340 task.ti=cc02c000) [ 139.924982] Stack: [ 139.924982] c1203c88 00000000 cc02def4 cf4d2a1c ae21eefa 471b60d5 1083c1ba c26a5940 [ 139.924982] e891fb5e 00000041 00000004 cc02df1c c1203964 00000000 cc02df4c c10e20c3 [ 139.924982] 00000002 00000000 00000000 22222222 c1ff2222 cf5ef000 00000000 d76efb08 [ 139.924982] Call Trace: [ 139.924982] [] ? evm_update_evmxattr+0x5b/0x62 [ 139.924982] [] evm_inode_post_setattr+0x22/0x26 [ 139.924982] [] notify_change+0x25f/0x281 [ 139.924982] [] chmod_common+0x59/0x76 [ 139.924982] [] ? put_unused_fd+0x33/0x33 [ 139.924982] [] sys_fchmod+0x39/0x5c [ 139.924982] [] syscall_call+0x7/0xb [ 139.924982] Code: Bad EIP value. This happens because sockets do not define the removexattr operation. Before removing the xattr, verify the removexattr function pointer is not NULL. Signed-off-by: Dmitry Kasatkin Signed-off-by: Mimi Zohar Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman --- security/integrity/evm/evm_crypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index 49a464f5595b..62fa2c574986 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -205,9 +205,9 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name, rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM, &xattr_data, sizeof(xattr_data), 0); - } - else if (rc == -ENODATA) + } else if (rc == -ENODATA && inode->i_op->removexattr) { rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM); + } return rc; } -- GitLab From b08d81801e151fbcefa81a551eadf2beff554752 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 21 Jan 2013 20:47:41 +0100 Subject: [PATCH 1539/1799] ptrace: introduce signal_wake_up_state() and ptrace_signal_wake_up() commit 910ffdb18a6408e14febbb6e4b6840fd2c928c82 upstream. Cleanup and preparation for the next change. signal_wake_up(resume => true) is overused. None of ptrace/jctl callers actually want to wakeup a TASK_WAKEKILL task, but they can't specify the necessary mask. Turn signal_wake_up() into signal_wake_up_state(state), reintroduce signal_wake_up() as a trivial helper, and add ptrace_signal_wake_up() which adds __TASK_TRACED. This way ptrace_signal_wake_up() can work "inside" ptrace_request() even if the tracee doesn't have the TASK_WAKEKILL bit set. Signed-off-by: Oleg Nesterov Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/sched.h | 11 ++++++++++- kernel/ptrace.c | 8 ++++---- kernel/signal.c | 14 ++++---------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 48241aa976c8..3dd0efbb70f2 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2695,7 +2695,16 @@ static inline void thread_group_cputime_init(struct signal_struct *sig) extern void recalc_sigpending_and_wake(struct task_struct *t); extern void recalc_sigpending(void); -extern void signal_wake_up(struct task_struct *t, int resume_stopped); +extern void signal_wake_up_state(struct task_struct *t, unsigned int state); + +static inline void signal_wake_up(struct task_struct *t, bool resume) +{ + signal_wake_up_state(t, resume ? TASK_WAKEKILL : 0); +} +static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume) +{ + signal_wake_up_state(t, resume ? __TASK_TRACED : 0); +} /* * Wrappers for p->thread_info->cpu access. No-op on UP. diff --git a/kernel/ptrace.c b/kernel/ptrace.c index ee8d49b9c309..c44438462144 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -117,7 +117,7 @@ void __ptrace_unlink(struct task_struct *child) * TASK_KILLABLE sleeps. */ if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) - signal_wake_up(child, task_is_traced(child)); + ptrace_signal_wake_up(child, true); spin_unlock(&child->sighand->siglock); } @@ -311,7 +311,7 @@ static int ptrace_attach(struct task_struct *task, long request, */ if (task_is_stopped(task) && task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) - signal_wake_up(task, 1); + signal_wake_up_state(task, __TASK_STOPPED); spin_unlock(&task->sighand->siglock); @@ -728,7 +728,7 @@ int ptrace_request(struct task_struct *child, long request, * tracee into STOP. */ if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP))) - signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); + ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); unlock_task_sighand(child, &flags); ret = 0; @@ -754,7 +754,7 @@ int ptrace_request(struct task_struct *child, long request, * start of this trap and now. Trigger re-trap. */ if (child->jobctl & JOBCTL_TRAP_NOTIFY) - signal_wake_up(child, true); + ptrace_signal_wake_up(child, true); ret = 0; } unlock_task_sighand(child, &flags); diff --git a/kernel/signal.c b/kernel/signal.c index 17afcaf582d0..fbeca4a2b2b8 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -677,23 +677,17 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) * No need to set need_resched since signal event passing * goes through ->blocked */ -void signal_wake_up(struct task_struct *t, int resume) +void signal_wake_up_state(struct task_struct *t, unsigned int state) { - unsigned int mask; - set_tsk_thread_flag(t, TIF_SIGPENDING); - /* - * For SIGKILL, we want to wake it up in the stopped/traced/killable + * TASK_WAKEKILL also means wake it up in the stopped/traced/killable * case. We don't check t->state here because there is a race with it * executing another processor and just now entering stopped state. * By using wake_up_state, we ensure the process will wake up and * handle its death signal. */ - mask = TASK_INTERRUPTIBLE; - if (resume) - mask |= TASK_WAKEKILL; - if (!wake_up_state(t, mask)) + if (!wake_up_state(t, state | TASK_INTERRUPTIBLE)) kick_process(t); } @@ -842,7 +836,7 @@ static void ptrace_trap_notify(struct task_struct *t) assert_spin_locked(&t->sighand->siglock); task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); - signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); + ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); } /* -- GitLab From 9b6d794e7e56f3a413c57a15d4e07fb7efe6530a Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 21 Jan 2013 20:48:00 +0100 Subject: [PATCH 1540/1799] ptrace: ensure arch_ptrace/ptrace_request can never race with SIGKILL commit 9899d11f654474d2d54ea52ceaa2a1f4db3abd68 upstream. putreg() assumes that the tracee is not running and pt_regs_access() can safely play with its stack. However a killed tracee can return from ptrace_stop() to the low-level asm code and do RESTORE_REST, this means that debugger can actually read/modify the kernel stack until the tracee does SAVE_REST again. set_task_blockstep() can race with SIGKILL too and in some sense this race is even worse, the very fact the tracee can be woken up breaks the logic. As Linus suggested we can clear TASK_WAKEKILL around the arch_ptrace() call, this ensures that nobody can ever wakeup the tracee while the debugger looks at it. Not only this fixes the mentioned problems, we can do some cleanups/simplifications in arch_ptrace() paths. Probably ptrace_unfreeze_traced() needs more callers, for example it makes sense to make the tracee killable for oom-killer before access_process_vm(). While at it, add the comment into may_ptrace_stop() to explain why ptrace_stop() still can't rely on SIGKILL and signal_pending_state(). Reported-by: Salman Qazi Reported-by: Suleiman Souhlal Suggested-by: Linus Torvalds Signed-off-by: Oleg Nesterov Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/ptrace.c | 64 +++++++++++++++++++++++++++++++++++++++++-------- kernel/signal.c | 5 ++++ 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c index c44438462144..daf4394d1aba 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -122,6 +122,40 @@ void __ptrace_unlink(struct task_struct *child) spin_unlock(&child->sighand->siglock); } +/* Ensure that nothing can wake it up, even SIGKILL */ +static bool ptrace_freeze_traced(struct task_struct *task) +{ + bool ret = false; + + /* Lockless, nobody but us can set this flag */ + if (task->jobctl & JOBCTL_LISTENING) + return ret; + + spin_lock_irq(&task->sighand->siglock); + if (task_is_traced(task) && !__fatal_signal_pending(task)) { + task->state = __TASK_TRACED; + ret = true; + } + spin_unlock_irq(&task->sighand->siglock); + + return ret; +} + +static void ptrace_unfreeze_traced(struct task_struct *task) +{ + if (task->state != __TASK_TRACED) + return; + + WARN_ON(!task->ptrace || task->parent != current); + + spin_lock_irq(&task->sighand->siglock); + if (__fatal_signal_pending(task)) + wake_up_state(task, __TASK_TRACED); + else + task->state = TASK_TRACED; + spin_unlock_irq(&task->sighand->siglock); +} + /** * ptrace_check_attach - check whether ptracee is ready for ptrace operation * @child: ptracee to check for @@ -151,24 +185,29 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state) * be changed by us so it's not changing right after this. */ read_lock(&tasklist_lock); - if ((child->ptrace & PT_PTRACED) && child->parent == current) { + if (child->ptrace && child->parent == current) { + WARN_ON(child->state == __TASK_TRACED); /* * child->sighand can't be NULL, release_task() * does ptrace_unlink() before __exit_signal(). */ - spin_lock_irq(&child->sighand->siglock); - WARN_ON_ONCE(task_is_stopped(child)); - if (ignore_state || (task_is_traced(child) && - !(child->jobctl & JOBCTL_LISTENING))) + if (ignore_state || ptrace_freeze_traced(child)) ret = 0; - spin_unlock_irq(&child->sighand->siglock); } read_unlock(&tasklist_lock); - if (!ret && !ignore_state) - ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH; + if (!ret && !ignore_state) { + if (!wait_task_inactive(child, __TASK_TRACED)) { + /* + * This can only happen if may_ptrace_stop() fails and + * ptrace_stop() changes ->state back to TASK_RUNNING, + * so we should not worry about leaking __TASK_TRACED. + */ + WARN_ON(child->state == __TASK_TRACED); + ret = -ESRCH; + } + } - /* All systems go.. */ return ret; } @@ -891,6 +930,8 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr, goto out_put_task_struct; ret = arch_ptrace(child, request, addr, data); + if (ret || request != PTRACE_DETACH) + ptrace_unfreeze_traced(child); out_put_task_struct: put_task_struct(child); @@ -1030,8 +1071,11 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, ret = ptrace_check_attach(child, request == PTRACE_KILL || request == PTRACE_INTERRUPT); - if (!ret) + if (!ret) { ret = compat_arch_ptrace(child, request, addr, data); + if (ret || request != PTRACE_DETACH) + ptrace_unfreeze_traced(child); + } out_put_task_struct: put_task_struct(child); diff --git a/kernel/signal.c b/kernel/signal.c index fbeca4a2b2b8..a4363a982b03 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1802,6 +1802,10 @@ static inline int may_ptrace_stop(void) * If SIGKILL was already sent before the caller unlocked * ->siglock we must see ->core_state != NULL. Otherwise it * is safe to enter schedule(). + * + * This is almost outdated, a task with the pending SIGKILL can't + * block in TASK_TRACED. But PTRACE_EVENT_EXIT can be reported + * after SIGKILL was already dequeued. */ if (unlikely(current->mm->core_state) && unlikely(current->mm == current->parent->mm)) @@ -1927,6 +1931,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) if (gstop_done) do_notify_parent_cldstop(current, false, why); + /* tasklist protects us from ptrace_freeze_traced() */ __set_current_state(TASK_RUNNING); if (clear_code) current->exit_code = 0; -- GitLab From 465760c68a4e5037f10a7eab1df3fb2aff1e03a4 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 21 Jan 2013 20:48:17 +0100 Subject: [PATCH 1541/1799] wake_up_process() should be never used to wakeup a TASK_STOPPED/TRACED task commit 9067ac85d533651b98c2ff903182a20cbb361fcb upstream. wake_up_process() should never wakeup a TASK_STOPPED/TRACED task. Change it to use TASK_NORMAL and add the WARN_ON(). TASK_ALL has no other users, probably can be killed. Signed-off-by: Oleg Nesterov Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/sched/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 1d22981cd431..e1718bc35e16 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1688,7 +1688,8 @@ static void try_to_wake_up_local(struct task_struct *p) */ int wake_up_process(struct task_struct *p) { - return try_to_wake_up(p, TASK_ALL, 0); + WARN_ON(task_is_stopped_or_traced(p)); + return try_to_wake_up(p, TASK_NORMAL, 0); } EXPORT_SYMBOL(wake_up_process); -- GitLab From 7145808ebc1f0188cf9decbfd23279b0c10022f1 Mon Sep 17 00:00:00 2001 From: Betty Dall Date: Sun, 13 Jan 2013 15:46:18 -0700 Subject: [PATCH 1542/1799] PCI/AER: pci_get_domain_bus_and_slot() call missing required pci_dev_put() commit a82b6af37d20bfe6e99a4d890f1cf1d89059929f upstream. The function aer_recover_queue() calls pci_get_domain_bus_and_slot(), which requires that the caller decrement the reference count with pci_dev_put(). This patch adds the missing call to pci_dev_put(). Signed-off-by: Betty Dall Signed-off-by: Bjorn Helgaas Reviewed-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pcie/aer/aerdrv_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 0ca053538146..a56105b66f12 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -637,6 +637,7 @@ static void aer_recover_work_func(struct work_struct *work) continue; } do_recovery(pdev, entry.severity); + pci_dev_put(pdev); } } #endif -- GitLab From 11cfb2b163f483a4c97e5a229635d0f6b23bd5ac Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 27 Nov 2012 14:09:40 +0000 Subject: [PATCH 1543/1799] PCI: Allow pcie_aspm=force even when FADT indicates it is unsupported commit 9e16721498b0c3d3ebfa0b503c63d35c0a4c0642 upstream. Right now using pcie_aspm=force will not enable ASPM if the FADT indicates ASPM is unsupported. However, the semantics of force should probably allow for this, especially as they did before 3c076351c4 ("PCI: Rework ASPM disable code") This patch just skips the clearing of any ASPM setup that the firmware has carried out on this bus if pcie_aspm=force is being used. Reference: http://bugs.launchpad.net/bugs/962038 Signed-off-by: Colin Ian King Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pcie/aspm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index b500840a143b..474f22f304e4 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -798,6 +798,9 @@ void pcie_clear_aspm(struct pci_bus *bus) { struct pci_dev *child; + if (aspm_force) + return; + /* * Clear any ASPM setup that the firmware has carried out on this bus */ -- GitLab From 5f3e5a32d083008c1ad850375d24fc85a27803e4 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Fri, 11 Jan 2013 10:15:54 +0800 Subject: [PATCH 1544/1799] PCI: pciehp: Use per-slot workqueues to avoid deadlock commit c2be6f93b383c873a4f9d521afa49b1b67d06085 upstream. When we have a hotplug-capable PCIe port with a second hotplug-capable PCIe port below it, removing the device below the upstream port causes a deadlock. The deadlock happens because we use the pciehp_wq workqueue to run pciehp_power_thread(), which uses pciehp_disable_slot() to remove devices below the upstream port. When we remove the downstream PCIe port, we call pciehp_remove(), the pciehp driver's .remove() method. That calls flush_workqueue(pciehp_wq), which deadlocks because the pciehp_power_thread() work item is still running. This patch avoids the deadlock by creating a workqueue for every PCIe port and removing the single shared workqueue. Here's the call path that leads to the deadlock: pciehp_queue_pushbutton_work queue_work(pciehp_wq) # queue pciehp_power_thread ... pciehp_power_thread pciehp_disable_slot remove_board pciehp_unconfigure_device pci_stop_and_remove_bus_device ... pciehp_remove # pciehp driver .remove method pciehp_release_ctrl pcie_cleanup_slot flush_workqueue(pciehp_wq) This is fairly urgent because it can be caused by simply unplugging a Thunderbolt adapter, as reported by Daniel below. [bhelgaas: changelog] Reference: http://lkml.kernel.org/r/CAMVG2ssiRgcTD1bej2tkUUfsWmpL5eNtPcNif9va2-Gzb2u8nQ@mail.gmail.com Reported-and-tested-by: Daniel J Blueman Reviewed-by: Kenji Kaneshige Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 2 +- drivers/pci/hotplug/pciehp_core.c | 11 ++--------- drivers/pci/hotplug/pciehp_ctrl.c | 8 ++++---- drivers/pci/hotplug/pciehp_hpc.c | 11 ++++++++++- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 4b7cce1de6ec..a321b77a5e82 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -44,7 +44,6 @@ extern bool pciehp_poll_mode; extern int pciehp_poll_time; extern bool pciehp_debug; extern bool pciehp_force; -extern struct workqueue_struct *pciehp_wq; #define dbg(format, arg...) \ do { \ @@ -78,6 +77,7 @@ struct slot { struct hotplug_slot *hotplug_slot; struct delayed_work work; /* work for button event */ struct mutex lock; + struct workqueue_struct *wq; }; struct event_info { diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 365c6b96c642..9e39df969560 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -42,7 +42,6 @@ bool pciehp_debug; bool pciehp_poll_mode; int pciehp_poll_time; bool pciehp_force; -struct workqueue_struct *pciehp_wq; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman , Dely Sy " @@ -340,18 +339,13 @@ static int __init pcied_init(void) { int retval = 0; - pciehp_wq = alloc_workqueue("pciehp", 0, 0); - if (!pciehp_wq) - return -ENOMEM; - pciehp_firmware_init(); retval = pcie_port_service_register(&hpdriver_portdrv); dbg("pcie_port_service_register = %d\n", retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - if (retval) { - destroy_workqueue(pciehp_wq); + if (retval) dbg("Failure to register service\n"); - } + return retval; } @@ -359,7 +353,6 @@ static void __exit pcied_cleanup(void) { dbg("unload_pciehpd()\n"); pcie_port_service_unregister(&hpdriver_portdrv); - destroy_workqueue(pciehp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 27f44295a657..38f018679175 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -49,7 +49,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->p_slot = p_slot; INIT_WORK(&info->work, interrupt_event_handler); - queue_work(pciehp_wq, &info->work); + queue_work(p_slot->wq, &info->work); return 0; } @@ -344,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) kfree(info); goto out; } - queue_work(pciehp_wq, &info->work); + queue_work(p_slot->wq, &info->work); out: mutex_unlock(&p_slot->lock); } @@ -377,7 +377,7 @@ static void handle_button_press_event(struct slot *p_slot) if (ATTN_LED(ctrl)) pciehp_set_attention_status(p_slot, 0); - queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ); + queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); break; case BLINKINGOFF_STATE: case BLINKINGON_STATE: @@ -439,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot) else p_slot->state = POWERON_STATE; - queue_work(pciehp_wq, &info->work); + queue_work(p_slot->wq, &info->work); } static void interrupt_event_handler(struct work_struct *work) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index a960faec1021..9dd2c01a2e18 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -874,23 +874,32 @@ static void pcie_shutdown_notification(struct controller *ctrl) static int pcie_init_slot(struct controller *ctrl) { struct slot *slot; + char name[32]; slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) return -ENOMEM; + snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl)); + slot->wq = alloc_workqueue(name, 0, 0); + if (!slot->wq) + goto abort; + slot->ctrl = ctrl; mutex_init(&slot->lock); INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); ctrl->slot = slot; return 0; +abort: + kfree(slot); + return -ENOMEM; } static void pcie_cleanup_slot(struct controller *ctrl) { struct slot *slot = ctrl->slot; cancel_delayed_work(&slot->work); - flush_workqueue(pciehp_wq); + destroy_workqueue(slot->wq); kfree(slot); } -- GitLab From 1dbcda3ab27031e2b744b1f8ba48370304340519 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 11 Jan 2013 12:07:22 -0700 Subject: [PATCH 1545/1799] PCI: shpchp: Handle push button event asynchronously commit d347e75847c1fb299c97736638f45e6ea39702d4 upstream. Use non-ordered workqueue for attention button events. Attention button events on each slot can be handled asynchronously. So we should use non-ordered workqueue. This patch also removes ordered workqueue in shpchp as a result. 486b10b9f4 ("PCI: pciehp: Handle push button event asynchronously") made the same change to pciehp. I split this out from a patch by Yijing Wang so we fix one thing at a time and to make the shpchp history correspond more closely with the pciehp history. Signed-off-by: Bjorn Helgaas CC: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 1 - drivers/pci/hotplug/shpchp_core.c | 10 ---------- drivers/pci/hotplug/shpchp_ctrl.c | 2 +- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index ca64932e658b..1b69d955a31f 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -47,7 +47,6 @@ extern bool shpchp_poll_mode; extern int shpchp_poll_time; extern bool shpchp_debug; extern struct workqueue_struct *shpchp_wq; -extern struct workqueue_struct *shpchp_ordered_wq; #define dbg(format, arg...) \ do { \ diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 7414fd9ad1d2..5f1f0d93dc13 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -40,7 +40,6 @@ bool shpchp_debug; bool shpchp_poll_mode; int shpchp_poll_time; struct workqueue_struct *shpchp_wq; -struct workqueue_struct *shpchp_ordered_wq; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman , Dely Sy " @@ -175,7 +174,6 @@ void cleanup_slots(struct controller *ctrl) list_del(&slot->slot_list); cancel_delayed_work(&slot->work); flush_workqueue(shpchp_wq); - flush_workqueue(shpchp_ordered_wq); pci_hp_deregister(slot->hotplug_slot); } } @@ -364,17 +362,10 @@ static int __init shpcd_init(void) if (!shpchp_wq) return -ENOMEM; - shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0); - if (!shpchp_ordered_wq) { - destroy_workqueue(shpchp_wq); - return -ENOMEM; - } - retval = pci_register_driver(&shpc_driver); dbg("%s: pci_register_driver = %d\n", __func__, retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); if (retval) { - destroy_workqueue(shpchp_ordered_wq); destroy_workqueue(shpchp_wq); } return retval; @@ -384,7 +375,6 @@ static void __exit shpcd_cleanup(void) { dbg("unload_shpchpd()\n"); pci_unregister_driver(&shpc_driver); - destroy_workqueue(shpchp_ordered_wq); destroy_workqueue(shpchp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index b00b09bdd38a..bba5b3e0bf8a 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -456,7 +456,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work) kfree(info); goto out; } - queue_work(shpchp_ordered_wq, &info->work); + queue_work(shpchp_wq, &info->work); out: mutex_unlock(&p_slot->lock); } -- GitLab From a94af21f3f1e333efd205a8bfd9a51aaec505d0e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 22 Jan 2013 11:37:35 -0500 Subject: [PATCH 1546/1799] USB: UHCI: fix IRQ race during initialization commit 0f815a0a700bc10547449bde6c106051a035a1b9 upstream. This patch (as1644) fixes a race that occurs during startup in uhci-hcd. If the IRQ line is shared with other devices, it's possible for the handler routine to be called before the data structures are fully initialized. The problem is fixed by adding a check to the IRQ handler routine. If the initialization hasn't finished yet, the routine will return immediately. Signed-off-by: Alan Stern Reported-by: Don Zickus Tested-by: "Huang, Adrian (ISS Linux TW)" Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-hcd.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index e4db350602b8..3fe069f536b2 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -447,6 +447,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) return IRQ_NONE; uhci_writew(uhci, status, USBSTS); /* Clear it */ + spin_lock(&uhci->lock); + if (unlikely(!uhci->is_initialized)) /* not yet configured */ + goto done; + if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { if (status & USBSTS_HSE) dev_err(uhci_dev(uhci), "host system error, " @@ -455,7 +459,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) dev_err(uhci_dev(uhci), "host controller process " "error, something bad happened!\n"); if (status & USBSTS_HCH) { - spin_lock(&uhci->lock); if (uhci->rh_state >= UHCI_RH_RUNNING) { dev_err(uhci_dev(uhci), "host controller halted, " @@ -473,15 +476,15 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) * pending unlinks */ mod_timer(&hcd->rh_timer, jiffies); } - spin_unlock(&uhci->lock); } } - if (status & USBSTS_RD) + if (status & USBSTS_RD) { + spin_unlock(&uhci->lock); usb_hcd_poll_rh_status(hcd); - else { - spin_lock(&uhci->lock); + } else { uhci_scan_schedule(uhci); + done: spin_unlock(&uhci->lock); } @@ -662,9 +665,9 @@ static int uhci_start(struct usb_hcd *hcd) */ mb(); + spin_lock_irq(&uhci->lock); configure_hc(uhci); uhci->is_initialized = 1; - spin_lock_irq(&uhci->lock); start_rh(uhci); spin_unlock_irq(&uhci->lock); return 0; -- GitLab From 462434eff40df54e9d5d1b5f8f21383fb382805c Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Fri, 18 Jan 2013 16:53:56 +0530 Subject: [PATCH 1547/1799] usb: dwc3: gadget: fix ep->maxburst for ep0 commit 6048e4c69d80600baba35856651056860d5d8f5a upstream. dwc3_gadget_set_ep_config expects maxburst as incremented by 1. So, by default initialize ep->maxburst to 1 for ep0. Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index cee0c3e8ab3a..f62629b029fc 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1453,6 +1453,7 @@ static int __devinit dwc3_gadget_init_endpoints(struct dwc3 *dwc) if (epnum == 0 || epnum == 1) { dep->endpoint.maxpacket = 512; + dep->endpoint.maxburst = 1; dep->endpoint.ops = &dwc3_gadget_ep0_ops; if (!epnum) dwc->gadget.ep0 = &dep->endpoint; -- GitLab From af22aff300fc5d70db97e1d551a0f2d1408027be Mon Sep 17 00:00:00 2001 From: "Joel D. Diaz" Date: Wed, 10 Oct 2012 10:36:11 +0200 Subject: [PATCH 1548/1799] SCSI: sd: Reshuffle init_sd to avoid crash commit afd5e34b2bb34881d3a789e62486814a49b47faa upstream. scsi_register_driver will register a prep_fn() function, which in turn migh need to use the sd_cdp_pool for DIF. Which hasn't been initialised at this point, leading to a crash. So reshuffle the init_sd() and exit_sd() paths to have the driver registered last. Signed-off-by: Joel D. Diaz Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley Cc: CAI Qian Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/sd.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a239382b2bdd..5b3cadbffcfc 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2919,10 +2919,6 @@ static int __init init_sd(void) if (err) goto err_out; - err = scsi_register_driver(&sd_template.gendrv); - if (err) - goto err_out_class; - sd_cdb_cache = kmem_cache_create("sd_ext_cdb", SD_EXT_CDB_SIZE, 0, 0, NULL); if (!sd_cdb_cache) { @@ -2936,8 +2932,15 @@ static int __init init_sd(void) goto err_out_cache; } + err = scsi_register_driver(&sd_template.gendrv); + if (err) + goto err_out_driver; + return 0; +err_out_driver: + mempool_destroy(sd_cdb_pool); + err_out_cache: kmem_cache_destroy(sd_cdb_cache); @@ -2960,10 +2963,10 @@ static void __exit exit_sd(void) SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n")); + scsi_unregister_driver(&sd_template.gendrv); mempool_destroy(sd_cdb_pool); kmem_cache_destroy(sd_cdb_cache); - scsi_unregister_driver(&sd_template.gendrv); class_unregister(&sd_disk_class); for (i = 0; i < SD_MAJORS; i++) -- GitLab From 220a0bc2df2b7385d278864fa1f8b47f9c78c8a2 Mon Sep 17 00:00:00 2001 From: Zhenzhong Duan Date: Thu, 20 Dec 2012 15:05:13 -0800 Subject: [PATCH 1549/1799] drivers/firmware/dmi_scan.c: check dmi version when get system uuid commit f1d8e614d74b09531b9a85e812485340f3df7b1c upstream. As of version 2.6 of the SMBIOS specification, the first 3 fields of the UUID are supposed to be little-endian encoded. Also a minor fix to match variable meaning and mute checkpatch.pl [akpm@linux-foundation.org: tweak code comment] Signed-off-by: Zhenzhong Duan Cc: Feng Jin Cc: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Abdallah Chatila Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/dmi_scan.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index b298158cb922..3714e3c03df6 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -16,6 +16,7 @@ */ static char dmi_empty_string[] = " "; +static u16 __initdata dmi_ver; /* * Catch too early calls to dmi_check_system(): */ @@ -161,8 +162,10 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde return; for (i = 0; i < 16 && (is_ff || is_00); i++) { - if(d[i] != 0x00) is_ff = 0; - if(d[i] != 0xFF) is_00 = 0; + if (d[i] != 0x00) + is_00 = 0; + if (d[i] != 0xFF) + is_ff = 0; } if (is_ff || is_00) @@ -172,7 +175,15 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde if (!s) return; - sprintf(s, "%pUB", d); + /* + * As of version 2.6 of the SMBIOS specification, the first 3 fields of + * the UUID are supposed to be little-endian encoded. The specification + * says that this is the defacto standard. + */ + if (dmi_ver >= 0x0206) + sprintf(s, "%pUL", d); + else + sprintf(s, "%pUB", d); dmi_ident[slot] = s; } @@ -414,6 +425,7 @@ static int __init dmi_present(const char __iomem *p) * DMI version 0.0 means that the real version is taken from * the SMBIOS version, which we don't know at this point. */ + dmi_ver = (buf[14] & 0xf0) << 4 | (buf[14] & 0x0f); if (buf[14] != 0) printk(KERN_INFO "DMI %d.%d present.\n", buf[14] >> 4, buf[14] & 0xF); -- GitLab From b88532f7efaff806193edbbe826ef0d0f8ac1063 Mon Sep 17 00:00:00 2001 From: Zhenzhong Duan Date: Thu, 20 Dec 2012 15:05:14 -0800 Subject: [PATCH 1550/1799] drivers/firmware/dmi_scan.c: fetch dmi version from SMBIOS if it exists commit 9f9c9cbb60576a1518d0bf93fb8e499cffccf377 upstream. The right dmi version is in SMBIOS if it's zero in DMI region This issue was originally found from an oracle bug. One customer noticed system UUID doesn't match between dmidecode & uek2. - HP ProLiant BL460c G6 : # cat /sys/devices/virtual/dmi/id/product_uuid 00000000-0000-4C48-3031-4D5030333531 # dmidecode | grep -i uuid UUID: 00000000-0000-484C-3031-4D5030333531 From SMBIOS 2.6 on, spec use little-endian encoding for UUID other than network byte order. So we need to get dmi version to distinguish. If version is 0.0, the real version is taken from the SMBIOS version. This is part of original kernel comment in code. [akpm@linux-foundation.org: checkpatch fixes] Signed-off-by: Zhenzhong Duan Cc: Feng Jin Cc: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Abdallah Chatila Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/dmi_scan.c | 62 ++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 3714e3c03df6..fd3ae6290d71 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -119,12 +119,12 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *, return 0; } -static int __init dmi_checksum(const u8 *buf) +static int __init dmi_checksum(const u8 *buf, u8 len) { u8 sum = 0; int a; - for (a = 0; a < 15; a++) + for (a = 0; a < len; a++) sum += buf[a]; return sum == 0; @@ -415,30 +415,57 @@ static int __init dmi_present(const char __iomem *p) u8 buf[15]; memcpy_fromio(buf, p, 15); - if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) { + if (dmi_checksum(buf, 15)) { dmi_num = (buf[13] << 8) | buf[12]; dmi_len = (buf[7] << 8) | buf[6]; dmi_base = (buf[11] << 24) | (buf[10] << 16) | (buf[9] << 8) | buf[8]; - /* - * DMI version 0.0 means that the real version is taken from - * the SMBIOS version, which we don't know at this point. - */ - dmi_ver = (buf[14] & 0xf0) << 4 | (buf[14] & 0x0f); - if (buf[14] != 0) - printk(KERN_INFO "DMI %d.%d present.\n", - buf[14] >> 4, buf[14] & 0xF); - else - printk(KERN_INFO "DMI present.\n"); if (dmi_walk_early(dmi_decode) == 0) { + if (dmi_ver) + pr_info("SMBIOS %d.%d present.\n", + dmi_ver >> 8, dmi_ver & 0xFF); + else { + dmi_ver = (buf[14] & 0xF0) << 4 | + (buf[14] & 0x0F); + pr_info("Legacy DMI %d.%d present.\n", + dmi_ver >> 8, dmi_ver & 0xFF); + } dmi_dump_ids(); return 0; } } + dmi_ver = 0; return 1; } +static int __init smbios_present(const char __iomem *p) +{ + u8 buf[32]; + int offset = 0; + + memcpy_fromio(buf, p, 32); + if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) { + dmi_ver = (buf[6] << 8) + buf[7]; + + /* Some BIOS report weird SMBIOS version, fix that up */ + switch (dmi_ver) { + case 0x021F: + case 0x0221: + pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", + dmi_ver & 0xFF, 3); + dmi_ver = 0x0203; + break; + case 0x0233: + pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6); + dmi_ver = 0x0206; + break; + } + offset = 16; + } + return dmi_present(buf + offset); +} + void __init dmi_scan_machine(void) { char __iomem *p, *q; @@ -456,7 +483,7 @@ void __init dmi_scan_machine(void) if (p == NULL) goto error; - rc = dmi_present(p + 0x10); /* offset of _DMI_ string */ + rc = smbios_present(p); dmi_iounmap(p, 32); if (!rc) { dmi_available = 1; @@ -474,7 +501,12 @@ void __init dmi_scan_machine(void) goto error; for (q = p; q < p + 0x10000; q += 16) { - rc = dmi_present(q); + if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0) + rc = smbios_present(q); + else if (memcmp(q, "_DMI_", 5) == 0) + rc = dmi_present(q); + else + continue; if (!rc) { dmi_available = 1; dmi_iounmap(p, 0x10000); -- GitLab From b7cd50fb1dd6527706415bb61461d6f283a23dd4 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 4 Sep 2012 16:25:25 +0100 Subject: [PATCH 1551/1799] ahci: Add identifiers for ASM106x devices commit 7b4f6ecacb14f384adc1a5a67ad95eb082c02bd1 upstream. They don't always appear as AHCI class devices but instead as IDE class. Based on an initial patch by Hiroaki Nito Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=42804 Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik Signed-off-by: Abdallah Chatila Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ahci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 5d0fb6b51883..71a4d040f140 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -406,7 +406,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ /* Asmedia */ - { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1061 */ + { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ + { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ + { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ + { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ /* Enmotus */ { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, -- GitLab From 115b96e58609cff057d22d0e6118dae093763461 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 22 Jan 2013 17:43:40 +0100 Subject: [PATCH 1552/1799] ALSA: usb-audio: Fix regression by disconnection-race-fix patch [NOTE: the regression below is found only in 3.2-3.4 stable trees, so there is no upstream commit corresponding to this patch] The recent fix for the race at disconnection of usb-audio devices (upstream commit 978520b7) triggers Oops when a device is unplugged while playing on 3.2 and 3.4 kernels. The culprit is that the shutdown flag check was wrongly added around the urb deactivation code snippet. The urb deactivation code has to be performed even after the device disconnected. Otherwise it remains undead and pokes the wild access in the end. The regression fix is simply reverting the shutdown flag check in that code. Reported-and-tested-by: Chris J Arges Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/endpoint.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 24c511491b45..9ab2b3e22224 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -148,10 +148,8 @@ void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force) int i; /* stop urbs (to be sure) */ - if (!subs->stream->chip->shutdown) { - deactivate_urbs(subs, force, 1); - wait_clear_urbs(subs); - } + deactivate_urbs(subs, force, 1); + wait_clear_urbs(subs); for (i = 0; i < MAX_URBS; i++) release_urb_ctx(&subs->dataurb[i]); -- GitLab From 35d620d4a06a739c97f9e4ea53374df8c2c95281 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 14 Dec 2012 23:38:28 +0100 Subject: [PATCH 1553/1799] drm/i915: Implement WaDisableHiZPlanesWhenMSAAEnabled commit 4283908ef7f11a72c3b80dd4cf026f1a86429f82 upstream. Quoting from Bspec, 3D_CHICKEN1, bit 10 This bit needs to be set always to "1", Project: DevSNB " Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter Signed-off-by: Abdallah Chatila Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_display.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 27a296a1415e..dde62bf3b1cf 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -27,6 +27,8 @@ #define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) +#define _MASKED_BIT_ENABLE(a) (((a) << 16) | (a)) + /* * The Bridge device's PCI config space has information about the * fb aperture size and the amount of pre-reserved memory. @@ -433,6 +435,7 @@ * the enables for writing to the corresponding low bit. */ #define _3D_CHICKEN 0x02084 +#define _3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB (1 << 10) #define _3D_CHICKEN2 0x0208c /* Disables pipelining of read flushes past the SF-WIZ interface. * Required on all Ironlake steppings according to the B-Spec, but the diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8e95c9432869..3c9b9c570405 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8592,6 +8592,10 @@ static void gen6_init_clock_gating(struct drm_device *dev) I915_READ(ILK_DISPLAY_CHICKEN2) | ILK_ELPIN_409_SELECT); + /* WaDisableHiZPlanesWhenMSAAEnabled */ + I915_WRITE(_3D_CHICKEN, + _MASKED_BIT_ENABLE(_3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB)); + I915_WRITE(WM3_LP_ILK, 0); I915_WRITE(WM2_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0); -- GitLab From b8b02d1a89f6f0598d815476acce249a4b891020 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 16 Jan 2013 23:40:07 +0100 Subject: [PATCH 1554/1799] ACPI / cpuidle: Fix NULL pointer issues when cpuidle is disabled commit b88a634a903d9670aa5f2f785aa890628ce0dece upstream. If cpuidle is disabled, that means that: per_cpu(acpi_cpuidle_device, pr->id) is set to NULL as the acpi_processor_power_init ends up failing at retval = cpuidle_register_driver(&acpi_idle_driver) (in acpi_processor_power_init) and never sets the per_cpu idle device. So when acpi_processor_hotplug on CPU online notification tries to reference said device it crashes: cpu 3 spinlock event irq 62 BUG: unable to handle kernel NULL pointer dereference at 0000000000000004 IP: [] acpi_processor_setup_cpuidle_cx+0x3f/0x105 PGD a259b067 PUD ab38b067 PMD 0 Oops: 0002 [#1] SMP odules linked in: dm_multipath dm_mod xen_evtchn iscsi_boot_sysfs iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi libcrc32c crc32c nouveau mxm_wmi wmi radeon ttm sg sr_mod sd_mod cdrom ata_generic ata_piix libata crc32c_intel scsi_mod atl1c i915 fbcon tileblit font bitblit softcursor drm_kms_helper video xen_blkfront xen_netfront fb_sys_fops sysimgblt sysfillrect syscopyarea xenfs xen_privcmd mperf CPU 1 Pid: 3047, comm: bash Not tainted 3.8.0-rc3upstream-00250-g165c029 #1 MSI MS-7680/H61M-P23 (MS-7680) RIP: e030:[] [] acpi_processor_setup_cpuidle_cx+0x3f/0x105 RSP: e02b:ffff88001742dca8 EFLAGS: 00010202 RAX: 0000000000010be9 RBX: ffff8800a0a61800 RCX: ffff880105380000 RDX: 0000000000000003 RSI: 0000000000000200 RDI: ffff8800a0a61800 RBP: ffff88001742dce8 R08: ffffffff81812360 R09: 0000000000000200 R10: aaaaaaaaaaaaaaaa R11: 0000000000000001 R12: ffff8800a0a61800 R13: 00000000ffffff01 R14: 0000000000000000 R15: ffffffff81a907a0 FS: 00007fd6942f7700(0000) GS:ffff880105280000(0000) knlGS:0000000000000000 CS: e033 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000004 CR3: 00000000a6773000 CR4: 0000000000042660 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process bash (pid: 3047, threadinfo ffff88001742c000, task ffff880017944000) Stack: 0000000000000150 ffff880100f59e00 ffff88001742dcd8 ffff8800a0a61800 0000000000000000 00000000ffffff01 0000000000000000 ffffffff81a907a0 ffff88001742dd18 ffffffff813815b1 ffff88001742dd08 ffffffff810ae336 Call Trace: [] acpi_processor_hotplug+0x7c/0x9f [] ? schedule_delayed_work_on+0x16/0x20 [] acpi_cpu_soft_notify+0x90/0xca [] notifier_call_chain+0x4d/0x70 [] __raw_notifier_call_chain+0x9/0x10 [] __cpu_notify+0x1b/0x30 [] _cpu_up+0x103/0x14b [] cpu_up+0xd9/0xec [] store_online+0x94/0xd0 [] dev_attr_store+0x1b/0x20 [] sysfs_write_file+0xf4/0x170 This patch fixes it. Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/processor_idle.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f3decb30223f..9d21cc7d440d 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1018,6 +1018,9 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) return -EINVAL; } + if (!dev) + return -EINVAL; + dev->cpu = pr->id; if (max_cstate == 0) -- GitLab From 54980d10c77318729ce2549635e3950fe338ba53 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Sat, 19 Jan 2013 00:28:22 +0100 Subject: [PATCH 1555/1799] ACPI / processor: Get power info before updating the C-states commit f427e5f1cf75bba84cccdac1d8a90552d9ae1065 upstream. acpi_processor_get_power_info() has to be called before acpi_processor_setup_cpuidle_states() to have the latest information available. This fixes the missing C-state information after AC-->DC transition. Signed-off-by: Thomas Schlichter Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/processor_idle.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 9d21cc7d440d..6cba4282588b 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1208,6 +1208,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) } /* Populate Updated C-state information */ + acpi_processor_get_power_info(pr); acpi_processor_setup_cpuidle_states(pr); /* Enable all cpuidle devices */ -- GitLab From 8f3933a1e549a54b4c1b743b40cfd196c8bf0035 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 25 Oct 2012 10:22:32 -0600 Subject: [PATCH 1556/1799] ioat: Fix DMA memory sync direction correct flag commit ac4989874af56435c308bdde9ad9c837a26f8b23 upstream. ioat does DMA memory sync with DMA_TO_DEVICE direction on a buffer allocated for DMA_FROM_DEVICE dma, resulting in the following warning from dma debug. Fixed the dma_sync_single_for_device() call to use the correct direction. [ 226.288947] WARNING: at lib/dma-debug.c:990 check_sync+0x132/0x550() [ 226.288948] Hardware name: ProLiant DL380p Gen8 [ 226.288951] ioatdma 0000:00:04.0: DMA-API: device driver syncs DMA memory with different direction [device address=0x00000000ffff7000] [size=4096 bytes] [mapped with DMA_FROM_DEVICE] [synced with DMA_TO_DEVICE] [ 226.288953] Modules linked in: iTCO_wdt(+) sb_edac(+) ioatdma(+) microcode serio_raw pcspkr edac_core hpwdt(+) iTCO_vendor_support hpilo(+) dca acpi_power_meter ata_generic pata_acpi sd_mod crc_t10dif ata_piix libata hpsa tg3 netxen_nic(+) sunrpc dm_mirror dm_region_hash dm_log dm_mod [ 226.288967] Pid: 1055, comm: work_for_cpu Tainted: G W 3.3.0-0.20.el7.x86_64 #1 [ 226.288968] Call Trace: [ 226.288974] [] warn_slowpath_common+0x7f/0xc0 [ 226.288977] [] warn_slowpath_fmt+0x46/0x50 [ 226.288980] [] check_sync+0x132/0x550 [ 226.288983] [] debug_dma_sync_single_for_device+0x3f/0x50 [ 226.288988] [] ? wait_for_common+0x72/0x180 [ 226.288995] [] ioat_xor_val_self_test+0x3e5/0x832 [ioatdma] [ 226.288999] [] ? kfree+0x259/0x270 [ 226.289004] [] ioat3_dma_self_test+0x1b/0x20 [ioatdma] [ 226.289008] [] ioat_probe+0x2f8/0x348 [ioatdma] [ 226.289011] [] ioat3_dma_probe+0x1d5/0x2aa [ioatdma] [ 226.289016] [] ioat_pci_probe+0x139/0x17c [ioatdma] [ 226.289020] [] local_pci_probe+0x5c/0xd0 [ 226.289023] [] ? destroy_work_on_stack+0x20/0x20 [ 226.289025] [] do_work_for_cpu+0x18/0x30 [ 226.289029] [] kthread+0xb7/0xc0 [ 226.289033] [] kernel_thread_helper+0x4/0x10 [ 226.289036] [] ? _raw_spin_unlock_irq+0x30/0x50 [ 226.289038] [] ? retint_restore_args+0x13/0x13 [ 226.289041] [] ? kthread_worker_fn+0x1a0/0x1a0 [ 226.289044] [] ? gs_change+0x13/0x13 [ 226.289045] ---[ end trace e1618afc7a606089 ]--- [ 226.289047] Mapped at: [ 226.289048] [] debug_dma_map_page+0x87/0x150 [ 226.289050] [] dma_map_page.constprop.18+0x70/0xb34 [ioatdma] [ 226.289054] [] ioat_xor_val_self_test+0x1d8/0x832 [ioatdma] [ 226.289058] [] ioat3_dma_self_test+0x1b/0x20 [ioatdma] [ 226.289061] [] ioat_probe+0x2f8/0x348 [ioatdma] Signed-off-by: Shuah Khan Signed-off-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/ioat/dma_v3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index f7f1dc62c15c..ed0e8b796a93 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -951,7 +951,7 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) goto free_resources; } } - dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_TO_DEVICE); + dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); /* skip validate if the capability is not present */ if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask)) -- GitLab From 4ab913dd103e474d4ea6b7e88307a738728c4592 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 27 Jan 2013 20:51:45 -0800 Subject: [PATCH 1557/1799] Linux 3.4.28 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f139ce7b942a..8ccebbadf367 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 27 +SUBLEVEL = 28 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From e3b308abd9a496f300b1552d8d09eb7c6b934478 Mon Sep 17 00:00:00 2001 From: Olivier Sobrie Date: Fri, 18 Jan 2013 09:32:39 +0100 Subject: [PATCH 1558/1799] can: c_can: fix invalid error codes commit 6ea45886865c1abb01bb861f7f6bdd5d0f398cb3 upstream. Errors in CAN protocol (location) are reported in data[3] of the can frame instead of data[2]. Signed-off-by: Olivier Sobrie Cc: Bhupesh Sharma Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/c_can/c_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 86cd532c78f9..21a3d77ea7e2 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -914,7 +914,7 @@ static int c_can_handle_bus_err(struct net_device *dev, break; case LEC_ACK_ERROR: netdev_dbg(dev, "ack error\n"); - cf->data[2] |= (CAN_ERR_PROT_LOC_ACK | + cf->data[3] |= (CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL); break; case LEC_BIT1_ERROR: @@ -927,7 +927,7 @@ static int c_can_handle_bus_err(struct net_device *dev, break; case LEC_CRC_ERROR: netdev_dbg(dev, "CRC error\n"); - cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL); break; default: -- GitLab From 1c539392d87f6e89bfbdab14438710826373a31b Mon Sep 17 00:00:00 2001 From: Olivier Sobrie Date: Fri, 18 Jan 2013 09:32:40 +0100 Subject: [PATCH 1559/1799] can: ti_hecc: fix invalid error codes commit 71088c4bd9b8f8cbffb0e66f2abc14297e4b2ca8 upstream. Errors in CAN protocol (location) are reported in data[3] of the can frame instead of data[2]. Signed-off-by: Olivier Sobrie Cc: Anant Gole Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/ti_hecc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 5ec27008ab4e..19000aa86805 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -746,12 +746,12 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, } if (err_status & HECC_CANES_CRCE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE); - cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL; } if (err_status & HECC_CANES_ACKE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE); - cf->data[2] |= CAN_ERR_PROT_LOC_ACK | + cf->data[3] |= CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL; } } -- GitLab From 83829ab554f01ee5fcef4880b0a90cc14350b936 Mon Sep 17 00:00:00 2001 From: Olivier Sobrie Date: Fri, 18 Jan 2013 09:32:41 +0100 Subject: [PATCH 1560/1799] can: pch_can: fix invalid error codes commit ee50e135aeb048b90fab662e661c58b67341830b upstream. Errors in CAN protocol (location) are reported in data[3] of the can frame instead of data[2]. Signed-off-by: Olivier Sobrie Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/pch_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index 2bb215e00eb1..ab13a57ae3bb 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -560,7 +560,7 @@ static void pch_can_error(struct net_device *ndev, u32 status) stats->rx_errors++; break; case PCH_CRC_ERR: - cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL; priv->can.can_stats.bus_error++; stats->rx_errors++; -- GitLab From bad73b66c3862db14a5362113df7680f4ef84200 Mon Sep 17 00:00:00 2001 From: Cong Ding Date: Tue, 22 Jan 2013 19:20:58 -0500 Subject: [PATCH 1561/1799] fs/cifs/cifs_dfs_ref.c: fix potential memory leakage commit 10b8c7dff5d3633b69e77f57d404dab54ead3787 upstream. When it goes to error through line 144, the memory allocated to *devname is not freed, and the caller doesn't free it either in line 250. So we free the memroy of *devname in function cifs_compose_mount_options() when it goes to error. Signed-off-by: Cong Ding Reviewed-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/cifs_dfs_ref.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 6873bb634a97..22631445a4ac 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -226,6 +226,8 @@ char *cifs_compose_mount_options(const char *sb_mountdata, compose_mount_options_err: kfree(mountdata); mountdata = ERR_PTR(rc); + kfree(*devname); + *devname = NULL; goto compose_mount_options_out; } -- GitLab From 96b3ce5cd4186b58085c03412416e9d540e90183 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 19 Jan 2013 11:05:57 +0000 Subject: [PATCH 1562/1799] ARM: DMA: Fix struct page iterator in dma_cache_maint() to work with sparsemem commit 15653371c67c3fbe359ae37b720639dd4c7b42c5 upstream. Subhash Jadavani reported this partial backtrace: Now consider this call stack from MMC block driver (this is on the ARMv7 based board): [] (v7_dma_inv_range+0x30/0x48) from [] (dma_cache_maint_page+0x1c4/0x24c) [] (dma_cache_maint_page+0x1c4/0x24c) from [] (___dma_page_cpu_to_dev+0x14/0x1c) [] (___dma_page_cpu_to_dev+0x14/0x1c) from [] (dma_map_sg+0x3c/0x114) This is caused by incrementing the struct page pointer, and running off the end of the sparsemem page array. Fix this by incrementing by pfn instead, and convert the pfn to a struct page. Suggested-by: James Bottomley Tested-by: Subhash Jadavani Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/mm/dma-mapping.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index db23ae4aaaab..a3e4adf2c28b 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -503,25 +503,27 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset, size_t size, enum dma_data_direction dir, void (*op)(const void *, size_t, int)) { + unsigned long pfn; + size_t left = size; + + pfn = page_to_pfn(page) + offset / PAGE_SIZE; + offset %= PAGE_SIZE; + /* * A single sg entry may refer to multiple physically contiguous * pages. But we still need to process highmem pages individually. * If highmem is not configured then the bulk of this loop gets * optimized out. */ - size_t left = size; do { size_t len = left; void *vaddr; + page = pfn_to_page(pfn); + if (PageHighMem(page)) { - if (len + offset > PAGE_SIZE) { - if (offset >= PAGE_SIZE) { - page += offset / PAGE_SIZE; - offset %= PAGE_SIZE; - } + if (len + offset > PAGE_SIZE) len = PAGE_SIZE - offset; - } vaddr = kmap_high_get(page); if (vaddr) { vaddr += offset; @@ -538,7 +540,7 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset, op(vaddr, len, dir); } offset = 0; - page++; + pfn++; left -= len; } while (left); } -- GitLab From 399f41521ecb4dfb55bf86210864ce7c60157d8a Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 23 Dec 2012 18:07:49 +0000 Subject: [PATCH 1563/1799] ARM: at91: rm9200: remake the BGA as default version commit 36224d0fe0f34cdde66a381708853ebadeac799c upstream. Make BGA as the default version as we are supposed to just have to specify when we use the PQFP version. Issue was existing since commit: 3e90772 (ARM: at91: fix at91rm9200 soc subtype handling). Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-at91/setup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 582142e049a8..55293a78cfac 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -104,6 +104,8 @@ static void __init soc_detect(u32 dbgu_base) switch (socid) { case ARCH_ID_AT91RM9200: at91_soc_initdata.type = AT91_SOC_RM9200; + if (at91_soc_initdata.subtype == AT91_SOC_SUBTYPE_NONE) + at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA; at91_boot_soc = at91rm9200_soc; break; -- GitLab From 112ae50d212e65816b9de8ea0010a430569d2fc6 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 14 Jan 2013 19:50:42 +0100 Subject: [PATCH 1564/1799] ARM: 7627/1: Predicate preempt logic on PREEMP_COUNT not PREEMPT alone commit 568dca15aa2a0f4ddee255894ec393a159f13147 upstream. Patrik Kluba reports that the preempt count becomes invalid due to the preempt_enable() call being unbalanced with a preempt_disable() call in the vfp assembly routines. This happens because preempt_enable() and preempt_disable() update preempt counts under PREEMPT_COUNT=y but the vfp assembly routines do so under PREEMPT=y. In a configuration where PREEMPT=n and DEBUG_ATOMIC_SLEEP=y, PREEMPT_COUNT=y and so the preempt_enable() call in VFP_bounce() keeps subtracting from the preempt count until it goes negative. Fix this by always using PREEMPT_COUNT to decided when to update preempt counts in the ARM assembly code. Signed-off-by: Stephen Boyd Reported-by: Patrik Kluba Tested-by: Patrik Kluba Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/vfp/entry.S | 6 +++--- arch/arm/vfp/vfphw.S | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S index cc926c985981..323ce1a62bbf 100644 --- a/arch/arm/vfp/entry.S +++ b/arch/arm/vfp/entry.S @@ -22,7 +22,7 @@ @ IRQs disabled. @ ENTRY(do_vfp) -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT ldr r4, [r10, #TI_PREEMPT] @ get preempt count add r11, r4, #1 @ increment it str r11, [r10, #TI_PREEMPT] @@ -35,7 +35,7 @@ ENTRY(do_vfp) ENDPROC(do_vfp) ENTRY(vfp_null_entry) -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count sub r11, r4, #1 @ decrement it @@ -53,7 +53,7 @@ ENDPROC(vfp_null_entry) __INIT ENTRY(vfp_testing_entry) -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count sub r11, r4, #1 @ decrement it diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index 3a0efaad6090..6ff903e50199 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -167,7 +167,7 @@ vfp_hw_state_valid: @ else it's one 32-bit instruction, so @ always subtract 4 from the following @ instruction address. -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count sub r11, r4, #1 @ decrement it @@ -191,7 +191,7 @@ look_for_VFP_exceptions: @ not recognised by VFP DBGSTR "not VFP" -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count sub r11, r4, #1 @ decrement it -- GitLab From dec3b6a0b8a4b1503617c45b351aedbd63adab58 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 11 Dec 2012 08:51:19 +0100 Subject: [PATCH 1565/1799] Bluetooth: Fix sending HCI commands after reset commit dbccd791a3fbbdac12c33834b73beff3984988e9 upstream. After sending reset command wait for its command complete event before sending next command. Some chips sends CC event for command received before reset if reset was send before chip replied with CC. This is also required by specification that host shall not send additional HCI commands before receiving CC for reset. < HCI Command: Reset (0x03|0x0003) plen 0 [hci0] 18.404612 > HCI Event: Command Complete (0x0e) plen 4 [hci0] 18.405850 Write Extended Inquiry Response (0x03|0x0052) ncmd 1 Status: Success (0x00) < HCI Command: Read Local Supported Features (0x04|0x0003) plen 0 [hci0] 18.406079 > HCI Event: Command Complete (0x0e) plen 4 [hci0] 18.407864 Reset (0x03|0x0003) ncmd 1 Status: Success (0x00) < HCI Command: Read Local Supported Features (0x04|0x0003) plen 0 [hci0] 18.408062 > HCI Event: Command Complete (0x0e) plen 12 [hci0] 18.408835 Signed-off-by: Szymon Janc Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 25edda03645e..ef45e10c44f2 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2366,7 +2366,7 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk if (ev->opcode != HCI_OP_NOP) del_timer(&hdev->cmd_timer); - if (ev->ncmd) { + if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { atomic_set(&hdev->cmd_cnt, 1); if (!skb_queue_empty(&hdev->cmd_q)) queue_work(hdev->workqueue, &hdev->cmd_work); -- GitLab From d4ffc500fcf28db4bc6e358e318b37bb884e421b Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Mon, 21 Jan 2013 15:50:03 -0500 Subject: [PATCH 1566/1799] drm/radeon: fix cursor corruption on DCE6 and newer commit e521a29014794d139cca46396d1af8faf1295a26 upstream. Aruba and newer gpu does not need the avivo cursor work around, quite the opposite this work around lead to corruption. agd5f: check DCE6 rather than ARUBA since the issue is DCE version specific rather than family specific. Signed-off-by: Jerome Glisse Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_cursor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 711e95ad39bf..8fb6f41bd1f2 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -238,7 +238,8 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, y = 0; } - if (ASIC_IS_AVIVO(rdev)) { + /* fixed on DCE6 and newer */ + if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) { int i = 0; struct drm_crtc *crtc_p; -- GitLab From 592306fd6bde5d73b2586ab163b4c78953d182ac Mon Sep 17 00:00:00 2001 From: xueminsu Date: Tue, 22 Jan 2013 22:16:53 +0800 Subject: [PATCH 1567/1799] radeon_display: Use pointer return error codes commit b2f4b03f8a378cd626d2ea67d19e7470c050a098 upstream. drm_mode_addfb() expects fb_create return error code instead of NULL. Signed-off-by: xueminsu Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 173b97b2819b..1f50727d210e 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1136,7 +1136,7 @@ radeon_user_framebuffer_create(struct drm_device *dev, if (ret) { kfree(radeon_fb); drm_gem_object_unreference_unlocked(obj); - return NULL; + return ERR_PTR(ret); } return &radeon_fb->base; -- GitLab From 6f92e64724f5ffbfd114b33ece087b00c7400ce5 Mon Sep 17 00:00:00 2001 From: Suravee Suthikulpanit Date: Thu, 24 Jan 2013 13:17:53 -0600 Subject: [PATCH 1568/1799] IOMMU, AMD Family15h Model10-1Fh erratum 746 Workaround commit 318fe782539c4150d1b8e4e6c9dc3a896512cb8a upstream. The IOMMU may stop processing page translations due to a perceived lack of credits for writing upstream peripheral page service request (PPR) or event logs. If the L2B miscellaneous clock gating feature is enabled the IOMMU does not properly register credits after the log request has completed, leading to a potential system hang. BIOSes are supposed to disable L2B micellaneous clock gating by setting L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b. This patch corrects that for those which do not enable this workaround. Signed-off-by: Suravee Suthikulpanit Acked-by: Borislav Petkov Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/amd_iommu_init.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index c04ddca7f12f..ef0ae93500f4 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1001,6 +1001,38 @@ static void __init free_iommu_all(void) } } +/* + * Family15h Model 10h-1fh erratum 746 (IOMMU Logging May Stall Translations) + * Workaround: + * BIOS should disable L2B micellaneous clock gating by setting + * L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b + */ +static void __init amd_iommu_erratum_746_workaround(struct amd_iommu *iommu) +{ + u32 value; + + if ((boot_cpu_data.x86 != 0x15) || + (boot_cpu_data.x86_model < 0x10) || + (boot_cpu_data.x86_model > 0x1f)) + return; + + pci_write_config_dword(iommu->dev, 0xf0, 0x90); + pci_read_config_dword(iommu->dev, 0xf4, &value); + + if (value & BIT(2)) + return; + + /* Select NB indirect register 0x90 and enable writing */ + pci_write_config_dword(iommu->dev, 0xf0, 0x90 | (1 << 8)); + + pci_write_config_dword(iommu->dev, 0xf4, value | 0x4); + pr_info("AMD-Vi: Applying erratum 746 workaround for IOMMU at %s\n", + dev_name(&iommu->dev->dev)); + + /* Clear the enable writing bit */ + pci_write_config_dword(iommu->dev, 0xf0, 0x90); +} + /* * This function clues the initialization function for one IOMMU * together and also allocates the command buffer and programs the @@ -1062,6 +1094,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) amd_iommu_np_cache = true; + amd_iommu_erratum_746_workaround(iommu); + return pci_enable_device(iommu->dev); } -- GitLab From dc28035ca92964adadd7cc1ea286a32b4f194257 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 23 Jan 2013 13:56:18 +0100 Subject: [PATCH 1569/1799] xfs: Fix possible use-after-free with AIO commit 4b05d09c18d9aa62d2e7fb4b057f54e5a38963f5 upstream. Running AIO is pinning inode in memory using file reference. Once AIO is completed using aio_complete(), file reference is put and inode can be freed from memory. So we have to be sure that calling aio_complete() is the last thing we do with the inode. Signed-off-by: Jan Kara CC: xfs@oss.sgi.com CC: Ben Myers Reviewed-by: Ben Myers Signed-off-by: Ben Myers Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_aops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 0dbb9e70fe21..7a978c7be842 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -89,11 +89,11 @@ xfs_destroy_ioend( } if (ioend->io_iocb) { + inode_dio_done(ioend->io_inode); if (ioend->io_isasync) { aio_complete(ioend->io_iocb, ioend->io_error ? ioend->io_error : ioend->io_result, 0); } - inode_dio_done(ioend->io_inode); } mempool_free(ioend, xfs_ioend_pool); -- GitLab From 68171ce1042bad67397b0408ea04c8f386adee73 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Mon, 21 Jan 2013 21:04:10 -0800 Subject: [PATCH 1570/1799] mwifiex: fix typo in PCIe adapter NULL check commit 83f0c6d1f502bd75bb4a9e31e8d64e59c6894ad1 upstream. Add missing "!" as we are supposed to check "!card->adapter" in PCIe suspend handler. Signed-off-by: Avinash Patil Signed-off-by: Bing Zhao Reviewed-by: Sergey V. Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mwifiex/pcie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 5867facd415d..6ca3d8a3e0e3 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c @@ -158,7 +158,7 @@ static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state) if (pdev) { card = (struct pcie_service_card *) pci_get_drvdata(pdev); - if (!card || card->adapter) { + if (!card || !card->adapter) { pr_err("Card or adapter structure is not valid\n"); return 0; } -- GitLab From 8c69e052e2330794fce15b7f299c6c797aed8b7d Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 16 Jan 2013 11:45:15 +0100 Subject: [PATCH 1571/1799] iwlegacy: fix IBSS cleanup commit fa4cffcba9e13798ed7c6b8526b91b1631ecb53e upstream. We do not correctly change interface type when switching from IBSS mode to STA mode, that results in microcode errors. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=886946 Reported-by: Jaroslav Skarvada Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlegacy/common.c | 35 +++++++++++--------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 4bc27112cbe2..2ab6b968c5f1 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -3957,17 +3957,21 @@ il_connection_init_rx_config(struct il_priv *il) memset(&il->staging, 0, sizeof(il->staging)); - if (!il->vif) { + switch (il->iw_mode) { + case NL80211_IFTYPE_UNSPECIFIED: il->staging.dev_type = RXON_DEV_TYPE_ESS; - } else if (il->vif->type == NL80211_IFTYPE_STATION) { + break; + case NL80211_IFTYPE_STATION: il->staging.dev_type = RXON_DEV_TYPE_ESS; il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; - } else if (il->vif->type == NL80211_IFTYPE_ADHOC) { + break; + case NL80211_IFTYPE_ADHOC: il->staging.dev_type = RXON_DEV_TYPE_IBSS; il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; il->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; - } else { + break; + default: IL_ERR("Unsupported interface type %d\n", il->vif->type); return; } @@ -4550,8 +4554,7 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) EXPORT_SYMBOL(il_mac_add_interface); static void -il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, - bool mode_change) +il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif) { lockdep_assert_held(&il->mutex); @@ -4560,9 +4563,7 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, il_force_scan_end(il); } - if (!mode_change) - il_set_mode(il); - + il_set_mode(il); } void @@ -4575,8 +4576,8 @@ il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) WARN_ON(il->vif != vif); il->vif = NULL; - - il_teardown_interface(il, vif, false); + il->iw_mode = NL80211_IFTYPE_UNSPECIFIED; + il_teardown_interface(il, vif); memset(il->bssid, 0, ETH_ALEN); D_MAC80211("leave\n"); @@ -4685,18 +4686,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } /* success */ - il_teardown_interface(il, vif, true); vif->type = newtype; vif->p2p = false; - err = il_set_mode(il); - WARN_ON(err); - /* - * We've switched internally, but submitting to the - * device may have failed for some reason. Mask this - * error, because otherwise mac80211 will not switch - * (and set the interface type back) and we'll be - * out of sync with it. - */ + il->iw_mode = newtype; + il_teardown_interface(il, vif); err = 0; out: -- GitLab From df2f07099760702c9f3664230263b6be3142b7d7 Mon Sep 17 00:00:00 2001 From: Piotr Haber Date: Thu, 10 Jan 2013 11:20:48 +0100 Subject: [PATCH 1572/1799] brcmsmac: increase timer reference count for new timers only commit a1fe52801a992e590cdaee2fb47a94bac9b5da90 upstream. On hardware reintialization reference count of already existing timers would be increased again. This leads to problems on module unloading. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Hante Meuleman Reviewed-by: Arend van Spriel Signed-off-by: Piotr Haber Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 569ab8abd2a1..27f37c7379d6 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -1400,9 +1400,10 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) #endif t->ms = ms; t->periodic = (bool) periodic; - t->set = true; - - atomic_inc(&t->wl->callbacks); + if (!t->set) { + t->set = true; + atomic_inc(&t->wl->callbacks); + } ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); } -- GitLab From e4fcbe5297a8c6e512c68a77c660a8cdd7d315e4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 11 Jan 2013 14:34:25 +0100 Subject: [PATCH 1573/1799] mac80211: fix FT roaming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1626e0fa740dec8665a973cf2349405cdfeb46dc upstream. During FT roaming, wpa_supplicant attempts to set the key before association. This used to be rejected, but as a side effect of my commit 66e67e418908442389d3a9e ("mac80211: redesign auth/assoc") the key was accepted causing hardware crypto to not be used for it as the station isn't added to the driver yet. It would be possible to accept the key and then add it to the driver when the station has been added. However, this may run into issues with drivers using the state- based station adding if they accept the key only after association like it used to be. For now, revert to the behaviour from before the auth and assoc change. Reported-by: Cédric Debarge Tested-by: Cédric Debarge Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/cfg.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 677d65929780..944334869596 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -151,7 +151,17 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, sta = sta_info_get(sdata, mac_addr); else sta = sta_info_get_bss(sdata, mac_addr); - if (!sta) { + /* + * The ASSOC test makes sure the driver is ready to + * receive the key. When wpa_supplicant has roamed + * using FT, it attempts to set the key before + * association has completed, this rejects that attempt + * so it will set the key again after assocation. + * + * TODO: accept the key if we have a station entry and + * add it to the device after the station. + */ + if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { ieee80211_key_free(sdata->local, key); err = -ENOENT; goto out_unlock; -- GitLab From 657273897cd2f9b7964ac704c6e58fbe8295c64d Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 9 Jan 2013 16:07:48 +0530 Subject: [PATCH 1574/1799] ath9k_htc: Fix memory leak commit 0981c3b24ef664f5611008a6e6d0622fac6d892b upstream. SKBs that are allocated in the HTC layer do not have callbacks registered and hence ended up not being freed, Fix this by freeing them properly in the TX completion routine. Reported-by: Larry Finger Signed-off-by: Sujith Manoharan Tested-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/htc_hst.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index c25226a32ddc..ec86d981abc8 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -342,6 +342,8 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv, skb, htc_hdr->endpoint_id, txok); + } else { + kfree_skb(skb); } } -- GitLab From fb259496950eaa9fa104ec6e570595ed21d66b07 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 9 Jan 2013 16:16:52 +0100 Subject: [PATCH 1575/1799] ath9k: do not link receive buffers during flush commit a3dc48e82bb146ef11cf75676c8410c1df29b0c4 upstream. On AR9300 the rx FIFO needs to be empty during reset to ensure that no further DMA activity is generated, otherwise it might lead to memory corruption issues. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/recv.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 90b8527154e3..039bac7e0c66 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -778,6 +778,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, return NULL; } + list_del(&bf->list); if (!bf->bf_mpdu) return bf; @@ -1966,14 +1967,15 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) sc->rx.frag = NULL; } requeue: + list_add_tail(&bf->list, &sc->rx.rxbuf); + if (flush) + continue; + if (edma) { - list_add_tail(&bf->list, &sc->rx.rxbuf); ath_rx_edma_buf_link(sc, qtype); } else { - list_move_tail(&bf->list, &sc->rx.rxbuf); ath_rx_buf_link(sc, bf); - if (!flush) - ath9k_hw_rxena(ah); + ath9k_hw_rxena(ah); } } while (1); -- GitLab From 82f9455a53ee8c02320c6a3b3c74975b804b9df0 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 9 Jan 2013 16:16:53 +0100 Subject: [PATCH 1576/1799] ath9k: fix double-free bug on beacon generate failure commit 1adb2e2b5f85023d17eb4f95386a57029df27c88 upstream. When the next beacon is sent, the ath_buf from the previous run is reused. If getting a new beacon from mac80211 fails, bf->bf_mpdu is not reset, yet the skb is freed, leading to a double-free on the next beacon tx attempt, resulting in a system crash. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/beacon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 5eb53c98d75e..2e4243fcadc9 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -154,6 +154,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); bf->bf_buf_addr = 0; + bf->bf_mpdu = NULL; } /* Get a new beacon from mac80211 */ -- GitLab From d065f12437292348564406a267c35857fe65bafc Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 29 Nov 2012 17:04:23 +0100 Subject: [PATCH 1577/1799] ALSA: usb-audio: fix invalid length check for RME and other UAC 2 devices commit d56268fb108c7c21e19933588ca4d94652585183 upstream. Commit 23caaf19b11e (ALSA: usb-mixer: Add support for Audio Class v2.0) forgot to adjust the length check for UAC 2.0 feature unit descriptors. This would make the code abort on encountering a feature unit without per-channel controls, and thus prevented the driver to work with any device having such a unit, such as the RME Babyface or Fireface UCX. Reported-by: Florian Hanisch Tested-by: Matthew Robbetts Tested-by: Michael Beer Cc: Daniel Mack Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/mixer.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 29ae209344d4..15b0712b9ad5 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1239,16 +1239,23 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void } channels = (hdr->bLength - 7) / csize - 1; bmaControls = hdr->bmaControls; + if (hdr->bLength < 7 + csize) { + snd_printk(KERN_ERR "usbaudio: unit %u: " + "invalid UAC_FEATURE_UNIT descriptor\n", + unitid); + return -EINVAL; + } } else { struct uac2_feature_unit_descriptor *ftr = _ftr; csize = 4; channels = (hdr->bLength - 6) / 4 - 1; bmaControls = ftr->bmaControls; - } - - if (hdr->bLength < 7 || !csize || hdr->bLength < 7 + csize) { - snd_printk(KERN_ERR "usbaudio: unit %u: invalid UAC_FEATURE_UNIT descriptor\n", unitid); - return -EINVAL; + if (hdr->bLength < 6 + csize) { + snd_printk(KERN_ERR "usbaudio: unit %u: " + "invalid UAC_FEATURE_UNIT descriptor\n", + unitid); + return -EINVAL; + } } /* parse the source unit */ -- GitLab From 4184c93021628f144a422ce1c280b3dc69b6ed12 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 23 Jan 2013 18:16:24 +0100 Subject: [PATCH 1578/1799] ALSA: hda - Add a fixup for Packard-Bell desktop with ALC880 commit 0712eea349d8e2b6d0e44b94a752d999319027fb upstream. A Packard-Bell desktop machine gives no proper pin configuration from BIOS. It's almost equivalent with the 6stack+fp standard config, just take the existing fixup. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=901846 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 7f2a10901ae4..f7f877626d88 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4741,6 +4741,7 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB), SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), + SND_PCI_QUIRK(0x1631, 0xe011, "PB 13201056", ALC880_FIXUP_6ST), SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734), SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU), SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734), -- GitLab From ecf7defcc50e33fd80e8ba34f140360606530d6b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 26 Jan 2013 10:49:24 +0300 Subject: [PATCH 1579/1799] EDAC: Test correct variable in ->store function commit 8024c4c0b1057d1cd811fc9c3f88f81de9729fcd upstream. We're testing for ->show but calling ->store(). Signed-off-by: Dan Carpenter Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman --- drivers/edac/edac_pci_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index 97f5064e3992..686ac03de130 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -257,7 +257,7 @@ static ssize_t edac_pci_dev_store(struct kobject *kobj, struct edac_pci_dev_attribute *edac_pci_dev; edac_pci_dev = (struct edac_pci_dev_attribute *)attr; - if (edac_pci_dev->show) + if (edac_pci_dev->store) return edac_pci_dev->store(edac_pci_dev->value, buffer, count); return -EIO; } -- GitLab From 99141c253f45822edfab14fa34bfa47f56d803ad Mon Sep 17 00:00:00 2001 From: Chris Rattray Date: Tue, 15 Jan 2013 13:22:36 +0000 Subject: [PATCH 1580/1799] ASoC: wm2200: correct mixer values and text commit a80cc734282805e15b5e023751a4d02f7ffbcc91 upstream. Signed-off-by: Chris Rattray Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm2200.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 86b84a18ba26..8e0cf146a68c 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -897,8 +897,6 @@ static const char *wm2200_mixer_texts[] = { "EQR", "LHPF1", "LHPF2", - "LHPF3", - "LHPF4", "DSP1.1", "DSP1.2", "DSP1.3", @@ -931,7 +929,6 @@ static int wm2200_mixer_values[] = { 0x25, 0x50, /* EQ */ 0x51, - 0x52, 0x60, /* LHPF1 */ 0x61, /* LHPF2 */ 0x68, /* DSP1 */ -- GitLab From 5a6d60801c24f6966cf73894258134778ddccde5 Mon Sep 17 00:00:00 2001 From: Anderson Lizardo Date: Sun, 6 Jan 2013 18:28:53 -0400 Subject: [PATCH 1581/1799] Bluetooth: Fix incorrect strncpy() in hidp_setup_hid() commit 0a9ab9bdb3e891762553f667066190c1d22ad62b upstream. The length parameter should be sizeof(req->name) - 1 because there is no guarantee that string provided by userspace will contain the trailing '\0'. Can be easily reproduced by manually setting req->name to 128 non-zero bytes prior to ioctl(HIDPCONNADD) and checking the device name setup on input subsystem: $ cat /sys/devices/pnp0/00\:04/tty/ttyS0/hci0/hci0\:1/input8/name AAAAAA[...]AAAAAAAAf0:af:f0:af:f0:af ("f0:af:f0:af:f0:af" is the device bluetooth address, taken from "phys" field in struct hid_device due to overflow.) Signed-off-by: Anderson Lizardo Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hidp/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index d478be11d562..7a0d9840866d 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -949,7 +949,7 @@ static int hidp_setup_hid(struct hidp_session *session, hid->version = req->version; hid->country = req->country; - strncpy(hid->name, req->name, 128); + strncpy(hid->name, req->name, sizeof(req->name) - 1); strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64); strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64); -- GitLab From 4b56ffb0c322d955c7fe6bae60711479b7ef6519 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 20 Jan 2013 23:50:13 +0100 Subject: [PATCH 1582/1799] iommu/intel: disable DMAR for g4x integrated gfx commit 9452618e7462181ed9755236803b6719298a13ce upstream. DMAR support on g4x/gm45 integrated gpus seems to be totally busted. So don't bother, but instead disable it by default to allow distros to unconditionally enable DMAR support. v2: Actually wire up the right quirk entry, spotted by Adam Jackson. Note that according to intel marketing materials only g45 and gm45 support DMAR/VT-d. So we have reports for all relevant gen4 pci ids by now. Still, keep all the other gen4 ids in the quirk table in case the marketing stuff confused me again, which would not be the first time. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=51921 Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=538163 Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=538163 Cc: Adam Jackson Cc: David Woodhouse Cc: stable@vger.kernel.org Acked-By: David Woodhouse Tested-by: stathis Tested-by: Mihai Moldovan Signed-off-by: Daniel Vetter Signed-off-by: Mihai Moldovan Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel-iommu.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index be6660696c9c..5d71873c6f65 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4193,6 +4193,21 @@ static struct iommu_ops intel_iommu_ops = { .pgsize_bitmap = INTEL_IOMMU_PGSIZES, }; +static void __devinit quirk_iommu_g4x_gfx(struct pci_dev *dev) +{ + /* G4x/GM45 integrated gfx dmar support is totally busted. */ + printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n"); + dmar_map_gfx = 0; +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx); + static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) { /* @@ -4201,12 +4216,6 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) */ printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n"); rwbf_quirk = 1; - - /* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */ - if (dev->revision == 0x07) { - printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n"); - dmar_map_gfx = 0; - } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); -- GitLab From 5a099d740ffdff7b217f23d7d871c4fb0c24a24b Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 20 Dec 2012 14:41:18 +0100 Subject: [PATCH 1583/1799] mac80211: synchronize scan off/on-channel and PS states commit aacde9ee45225f7e0b90960f479aef83c66bfdc0 upstream. Since: commit b23b025fe246f3acc2988eb6d400df34c27cb8ae Author: Ben Greear Date: Fri Feb 4 11:54:17 2011 -0800 mac80211: Optimize scans on current operating channel. we do not disable PS while going back to operational channel (on ieee80211_scan_state_suspend) and deffer that until scan finish. But since we are allowed to send frames, we can send a frame to AP without PM bit set, so disable PS on AP side. Then when we switch to off-channel (in ieee80211_scan_state_resume) we do not enable PS. Hence we are off-channel with PS disabled, frames are not buffered by AP. To fix remove offchannel_ps_disable argument and always enable PS when going off-channel and disable it when going on-channel, like it was before. Cc: stable@vger.kernel.org # 2.6.39+ Signed-off-by: Stanislaw Gruszka Tested-by: Seth Forshee Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ieee80211_i.h | 6 ++---- net/mac80211/offchannel.c | 17 ++++++----------- net/mac80211/scan.c | 15 +++++---------- net/mac80211/work.c | 4 ++-- 4 files changed, 15 insertions(+), 27 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f8b5e75be8cb..05160dbeaf44 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1264,10 +1264,8 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); void ieee80211_sched_scan_stopped_work(struct work_struct *work); /* off-channel helpers */ -void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, - bool offchannel_ps_enable); -void ieee80211_offchannel_return(struct ieee80211_local *local, - bool offchannel_ps_disable); +void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local); +void ieee80211_offchannel_return(struct ieee80211_local *local); void ieee80211_hw_roc_setup(struct ieee80211_local *local); /* interface handling */ diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 935aa4b6deee..c22f0748f4f6 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -103,8 +103,7 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) ieee80211_sta_reset_conn_monitor(sdata); } -void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, - bool offchannel_ps_enable) +void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; @@ -129,8 +128,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { netif_tx_stop_all_queues(sdata->dev); - if (offchannel_ps_enable && - (sdata->vif.type == NL80211_IFTYPE_STATION) && + if (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.associated) ieee80211_offchannel_ps_enable(sdata, true); } @@ -138,8 +136,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, mutex_unlock(&local->iflist_mtx); } -void ieee80211_offchannel_return(struct ieee80211_local *local, - bool offchannel_ps_disable) +void ieee80211_offchannel_return(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; @@ -152,11 +149,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, continue; /* Tell AP we're back */ - if (offchannel_ps_disable && - sdata->vif.type == NL80211_IFTYPE_STATION) { - if (sdata->u.mgd.associated) - ieee80211_offchannel_ps_disable(sdata); - } + if (sdata->vif.type == NL80211_IFTYPE_STATION && + sdata->u.mgd.associated) + ieee80211_offchannel_ps_disable(sdata); if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { /* diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index e95d494f36e0..bcc57f93adc4 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -329,7 +329,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, if (!was_hw_scan) { ieee80211_configure_filter(local); drv_sw_scan_complete(local); - ieee80211_offchannel_return(local, true); + ieee80211_offchannel_return(local); } ieee80211_recalc_idle(local); @@ -374,7 +374,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) local->next_scan_state = SCAN_DECISION; local->scan_channel_idx = 0; - ieee80211_offchannel_stop_vifs(local, true); + ieee80211_offchannel_stop_vifs(local); ieee80211_configure_filter(local); @@ -629,12 +629,8 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, local->scan_channel = NULL; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - /* - * Re-enable vifs and beaconing. Leave PS - * in off-channel state..will put that back - * on-channel at the end of scanning. - */ - ieee80211_offchannel_return(local, false); + /* disable PS */ + ieee80211_offchannel_return(local); *next_delay = HZ / 5; /* afterwards, resume scan & go to next channel */ @@ -644,8 +640,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, static void ieee80211_scan_state_resume(struct ieee80211_local *local, unsigned long *next_delay) { - /* PS already is in off-channel mode */ - ieee80211_offchannel_stop_vifs(local, false); + ieee80211_offchannel_stop_vifs(local); if (local->ops->flush) { drv_flush(local, false); diff --git a/net/mac80211/work.c b/net/mac80211/work.c index c6e230efa049..a74f53894d69 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -148,7 +148,7 @@ static void ieee80211_work_work(struct work_struct *work) } if (!started && !local->tmp_channel) { - ieee80211_offchannel_stop_vifs(local, true); + ieee80211_offchannel_stop_vifs(local); local->tmp_channel = wk->chan; local->tmp_channel_type = wk->chan_type; @@ -220,7 +220,7 @@ static void ieee80211_work_work(struct work_struct *work) local->tmp_channel = NULL; ieee80211_hw_config(local, 0); - ieee80211_offchannel_return(local, true); + ieee80211_offchannel_return(local); /* give connection some time to breathe */ run_again(local, jiffies + HZ/2); -- GitLab From 64fdede97a7c38889dd9b9016aac3e2afc23412b Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 22 Jan 2013 00:17:06 -0500 Subject: [PATCH 1584/1799] NFS: Don't silently fail setattr() requests on mountpoints commit ab225417825963b6dc66be7ea80f94ac1378dfdf upstream. Ensure that any setattr and getattr requests for junctions and/or mountpoints are sent to the server. Ever since commit 0ec26fd0698 (vfs: automount should ignore LOOKUP_FOLLOW), we have silently dropped any setattr requests to a server-side mountpoint. For referrals, we have silently dropped both getattr and setattr requests. This patch restores the original behaviour for setattr on mountpoints, and tries to do the same for referrals, provided that we have a filehandle... Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/namespace.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 2257d1f33e3c..43275167649a 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -253,11 +253,31 @@ struct vfsmount *nfs_d_automount(struct path *path) return mnt; } +static int +nfs_namespace_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +{ + if (NFS_FH(dentry->d_inode)->size != 0) + return nfs_getattr(mnt, dentry, stat); + generic_fillattr(dentry->d_inode, stat); + return 0; +} + +static int +nfs_namespace_setattr(struct dentry *dentry, struct iattr *attr) +{ + if (NFS_FH(dentry->d_inode)->size != 0) + return nfs_setattr(dentry, attr); + return -EACCES; +} + const struct inode_operations nfs_mountpoint_inode_operations = { .getattr = nfs_getattr, + .setattr = nfs_setattr, }; const struct inode_operations nfs_referral_inode_operations = { + .getattr = nfs_namespace_getattr, + .setattr = nfs_namespace_setattr, }; static void nfs_expire_automounts(struct work_struct *work) -- GitLab From 846c314fd6124b5bd3a3db2624818f29616874a1 Mon Sep 17 00:00:00 2001 From: Wang YanQing Date: Sat, 26 Jan 2013 15:53:57 +0800 Subject: [PATCH 1585/1799] smp: Fix SMP function call empty cpu mask race commit f44310b98ddb7f0d06550d73ed67df5865e3eda5 upstream. I get the following warning every day with v3.7, once or twice a day: [ 2235.186027] WARNING: at /mnt/sda7/kernel/linux/arch/x86/kernel/apic/ipi.c:109 default_send_IPI_mask_logical+0x2f/0xb8() As explained by Linus as well: | | Once we've done the "list_add_rcu()" to add it to the | queue, we can have (another) IPI to the target CPU that can | now see it and clear the mask. | | So by the time we get to actually send the IPI, the mask might | have been cleared by another IPI. | This patch also fixes a system hang problem, if the data->cpumask gets cleared after passing this point: if (WARN_ONCE(!mask, "empty IPI mask")) return; then the problem in commit 83d349f35e1a ("x86: don't send an IPI to the empty set of CPU's") will happen again. Signed-off-by: Wang YanQing Acked-by: Linus Torvalds Acked-by: Jan Beulich Cc: Paul E. McKenney Cc: Andrew Morton Cc: peterz@infradead.org Cc: mina86@mina86.org Cc: srivatsa.bhat@linux.vnet.ibm.com Link: http://lkml.kernel.org/r/20130126075357.GA3205@udknight [ Tidied up the changelog and the comment in the code. ] Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/smp.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kernel/smp.c b/kernel/smp.c index 2f8b10ecf759..d5f3238ec458 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -31,6 +31,7 @@ struct call_function_data { struct call_single_data csd; atomic_t refs; cpumask_var_t cpumask; + cpumask_var_t cpumask_ipi; }; static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data); @@ -54,6 +55,9 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL, cpu_to_node(cpu))) return notifier_from_errno(-ENOMEM); + if (!zalloc_cpumask_var_node(&cfd->cpumask_ipi, GFP_KERNEL, + cpu_to_node(cpu))) + return notifier_from_errno(-ENOMEM); break; #ifdef CONFIG_HOTPLUG_CPU @@ -63,6 +67,7 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) case CPU_DEAD: case CPU_DEAD_FROZEN: free_cpumask_var(cfd->cpumask); + free_cpumask_var(cfd->cpumask_ipi); break; #endif }; @@ -524,6 +529,12 @@ void smp_call_function_many(const struct cpumask *mask, return; } + /* + * After we put an entry into the list, data->cpumask + * may be cleared again when another CPU sends another IPI for + * a SMP function call, so data->cpumask will be zero. + */ + cpumask_copy(data->cpumask_ipi, data->cpumask); raw_spin_lock_irqsave(&call_function.lock, flags); /* * Place entry at the _HEAD_ of the list, so that any cpu still @@ -547,7 +558,7 @@ void smp_call_function_many(const struct cpumask *mask, smp_mb(); /* Send a message to all CPUs in the map */ - arch_send_call_function_ipi_mask(data->cpumask); + arch_send_call_function_ipi_mask(data->cpumask_ipi); /* Optionally wait for the CPUs to complete */ if (wait) -- GitLab From 4031dfce34e8e8355c649f950a9ec7ccad20beee Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 15 Nov 2012 13:06:22 +0000 Subject: [PATCH 1586/1799] x86/msr: Add capabilities check commit c903f0456bc69176912dee6dd25c6a66ee1aed00 upstream. At the moment the MSR driver only relies upon file system checks. This means that anything as root with any capability set can write to MSRs. Historically that wasn't very interesting but on modern processors the MSRs are such that writing to them provides several ways to execute arbitary code in kernel space. Sample code and documentation on doing this is circulating and MSR attacks are used on Windows 64bit rootkits already. In the Linux case you still need to be able to open the device file so the impact is fairly limited and reduces the security of some capability and security model based systems down towards that of a generic "root owns the box" setup. Therefore they should require CAP_SYS_RAWIO to prevent an elevation of capabilities. The impact of this is fairly minimal on most setups because they don't have heavy use of capabilities. Those using SELinux, SMACK or AppArmor rules might want to consider if their rulesets on the MSR driver could be tighter. Signed-off-by: Alan Cox Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/msr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index eb113693f043..8563b64e18cf 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -174,6 +174,9 @@ static int msr_open(struct inode *inode, struct file *file) unsigned int cpu; struct cpuinfo_x86 *c; + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + cpu = iminor(file->f_path.dentry->d_inode); if (cpu >= nr_cpu_ids || !cpu_online(cpu)) return -ENXIO; /* No such CPU */ -- GitLab From 956b0310a4f4cb0777d1e8a11a23950ec111a13b Mon Sep 17 00:00:00 2001 From: Nathan Zimmer Date: Tue, 8 Jan 2013 09:02:43 -0600 Subject: [PATCH 1587/1799] efi, x86: Pass a proper identity mapping in efi_call_phys_prelog commit b8f2c21db390273c3eaf0e5308faeaeb1e233840 upstream. Update efi_call_phys_prelog to install an identity mapping of all available memory. This corrects a bug on very large systems with more then 512 GB in which bios would not be able to access addresses above not in the mapping. The result is a crash that looks much like this. BUG: unable to handle kernel paging request at 000000effd870020 IP: [<0000000078bce331>] 0x78bce330 PGD 0 Oops: 0000 [#1] SMP Modules linked in: CPU 0 Pid: 0, comm: swapper/0 Tainted: G W 3.8.0-rc1-next-20121224-medusa_ntz+ #2 Intel Corp. Stoutland Platform RIP: 0010:[<0000000078bce331>] [<0000000078bce331>] 0x78bce330 RSP: 0000:ffffffff81601d28 EFLAGS: 00010006 RAX: 0000000078b80e18 RBX: 0000000000000004 RCX: 0000000000000004 RDX: 0000000078bcf958 RSI: 0000000000002400 RDI: 8000000000000000 RBP: 0000000078bcf760 R08: 000000effd870000 R09: 0000000000000000 R10: 0000000000000000 R11: 00000000000000c3 R12: 0000000000000030 R13: 000000effd870000 R14: 0000000000000000 R15: ffff88effd870000 FS: 0000000000000000(0000) GS:ffff88effe400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000000effd870020 CR3: 000000000160c000 CR4: 00000000000006b0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper/0 (pid: 0, threadinfo ffffffff81600000, task ffffffff81614400) Stack: 0000000078b80d18 0000000000000004 0000000078bced7b ffff880078b81fff 0000000000000000 0000000000000082 0000000078bce3a8 0000000000002400 0000000060000202 0000000078b80da0 0000000078bce45d ffffffff8107cb5a Call Trace: [] ? on_each_cpu+0x77/0x83 [] ? change_page_attr_set_clr+0x32f/0x3ed [] ? efi_call4+0x46/0x80 [] ? efi_enter_virtual_mode+0x1f5/0x305 [] ? start_kernel+0x34a/0x3d2 [] ? repair_env_string+0x60/0x60 [] ? x86_64_start_reservations+0xba/0xc1 [] ? early_idt_handlers+0x120/0x120 [] ? x86_64_start_kernel+0x154/0x163 Code: Bad RIP value. RIP [<0000000078bce331>] 0x78bce330 RSP CR2: 000000effd870020 ---[ end trace ead828934fef5eab ]--- Signed-off-by: Nathan Zimmer Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Robin Holt Signed-off-by: Matt Fleming Signed-off-by: Greg Kroah-Hartman --- arch/x86/platform/efi/efi_64.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index ac3aa54e2654..0fba86da5895 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -38,7 +38,7 @@ #include #include -static pgd_t save_pgd __initdata; +static pgd_t *save_pgd __initdata; static unsigned long efi_flags __initdata; static void __init early_code_mapping_set_exec(int executable) @@ -61,12 +61,20 @@ static void __init early_code_mapping_set_exec(int executable) void __init efi_call_phys_prelog(void) { unsigned long vaddress; + int pgd; + int n_pgds; early_code_mapping_set_exec(1); local_irq_save(efi_flags); - vaddress = (unsigned long)__va(0x0UL); - save_pgd = *pgd_offset_k(0x0UL); - set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress)); + + n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); + save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL); + + for (pgd = 0; pgd < n_pgds; pgd++) { + save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE); + vaddress = (unsigned long)__va(pgd * PGDIR_SIZE); + set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); + } __flush_tlb_all(); } @@ -75,7 +83,11 @@ void __init efi_call_phys_epilog(void) /* * After the lock is released, the original page table is restored. */ - set_pgd(pgd_offset_k(0x0UL), save_pgd); + int pgd; + int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); + for (pgd = 0; pgd < n_pgds; pgd++) + set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]); + kfree(save_pgd); __flush_tlb_all(); local_irq_restore(efi_flags); early_code_mapping_set_exec(0); -- GitLab From 40913e0adeb733053017293b0a5d6e096e47e4a1 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 25 Jan 2013 10:07:25 +0000 Subject: [PATCH 1588/1799] x86, efi: Set runtime_version to the EFI spec revision commit 712ba9e9afc4b3d3d6fa81565ca36fe518915c01 upstream. efi.runtime_version is erroneously being set to the value of the vendor's firmware revision instead of that of the implemented EFI specification. We can't deduce which EFI functions are available based on the revision of the vendor's firmware since the version scheme is likely to be unique to each vendor. What we really need to know is the revision of the implemented EFI specification, which is available in the EFI System Table header. Signed-off-by: Matt Fleming Cc: Seiji Aguchi Cc: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- arch/x86/platform/efi/efi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 72d88992f384..6825327d00a7 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -900,7 +900,7 @@ void __init efi_enter_virtual_mode(void) * * Call EFI services through wrapper functions. */ - efi.runtime_version = efi_systab.fw_revision; + efi.runtime_version = efi_systab.hdr.revision; efi.get_time = virt_efi_get_time; efi.set_time = virt_efi_set_time; efi.get_wakeup_time = virt_efi_get_wakeup_time; -- GitLab From ae2bac5c25d3f073d307338d9a84a1fe454c283b Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 13 Jan 2013 20:56:41 -0800 Subject: [PATCH 1589/1799] x86/Sandy Bridge: Sandy Bridge workaround depends on CONFIG_PCI commit e43b3cec711a61edf047adf6204d542f3a659ef8 upstream. early_pci_allowed() and read_pci_config_16() are only available if CONFIG_PCI is defined. Signed-off-by: H. Peter Anvin Cc: Jesse Barnes Signed-off-by: Abdallah Chatila --- arch/x86/kernel/setup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index d289ee73a248..b71e4a533ccd 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -622,6 +622,7 @@ static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; static bool __init snb_gfx_workaround_needed(void) { +#ifdef CONFIG_PCI int i; u16 vendor, devid; static const u16 snb_ids[] = { @@ -646,6 +647,7 @@ static bool __init snb_gfx_workaround_needed(void) for (i = 0; i < ARRAY_SIZE(snb_ids); i++) if (devid == snb_ids[i]) return true; +#endif return false; } -- GitLab From 9767a2421ad0f125bda9a8a1bed0c76bece8125c Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 24 Jan 2013 21:57:14 -0500 Subject: [PATCH 1590/1799] target: fix regression with dev_link_magic in target_fabric_port_link This is to fix a regression that only affect the stable (not for the mainline) that the stable commit fdf9d86 was incorrectly placed dev->dev_link_magic check before the *dev assignment in target_fabric_port_link() due to fuzzy automatically context adjustment during the back-porting. Reported-by: Chris Boot Signed-off-by: Nicholas Bellinger Signed-off-by: CAI Qian Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_fabric_configfs.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index b009b89d2fb4..817ba7c849e7 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -752,12 +752,6 @@ static int target_fabric_port_link( struct target_fabric_configfs *tf; int ret; - if (dev->dev_link_magic != SE_DEV_LINK_MAGIC) { - pr_err("Bad dev->dev_link_magic, not a valid se_dev_ci pointer:" - " %p to struct se_device: %p\n", se_dev_ci, dev); - return -EFAULT; - } - tpg_ci = &lun_ci->ci_parent->ci_group->cg_item; se_tpg = container_of(to_config_group(tpg_ci), struct se_portal_group, tpg_group); @@ -775,6 +769,11 @@ static int target_fabric_port_link( ret = -ENODEV; goto out; } + if (dev->dev_link_magic != SE_DEV_LINK_MAGIC) { + pr_err("Bad dev->dev_link_magic, not a valid se_dev_ci pointer:" + " %p to struct se_device: %p\n", se_dev_ci, dev); + return -EFAULT; + } lun_p = core_dev_add_lun(se_tpg, dev->se_hba, dev, lun->unpacked_lun); -- GitLab From 398cc33fbceda864a91433b2a76bb510a640021a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 3 Feb 2013 18:24:52 -0600 Subject: [PATCH 1591/1799] Linux 3.4.29 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 8ccebbadf367..23bcb1a6604d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 28 +SUBLEVEL = 29 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From b0cc9fb10c1b7240b229b40391f8da2a987995bd Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Fri, 25 Jan 2013 16:54:20 +0200 Subject: [PATCH 1592/1799] digsig: Fix memory leakage in digsig_verify_rsa() commit 7810cc1e7721220f1ed2a23ca95113d6434f6dcd upstream. digsig_verify_rsa() does not free kmalloc'ed buffer returned by mpi_get_buffer(). Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: Dmitry Kasatkin Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman --- lib/digsig.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/digsig.c b/lib/digsig.c index 8c0e62975c88..dc2be7ed1765 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -162,6 +162,8 @@ static int digsig_verify_rsa(struct key *key, memset(out1, 0, head); memcpy(out1 + head, p, l); + kfree(p); + err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len); if (err) goto err; -- GitLab From 36509fceeabafd1a6e95e48ae75efe020fa59937 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 31 Jan 2013 09:00:52 -0500 Subject: [PATCH 1593/1799] drm/radeon/evergreen+: wait for the MC to settle after MC blackout commit ed39fadd6df01095378e499fac3674883f16b853 upstream. Some chips seem to need a little delay after blacking out the MC before the requests actually stop. May fix: https://bugs.freedesktop.org/show_bug.cgi?id=56139 https://bugs.freedesktop.org/show_bug.cgi?id=57567 Signed-off-by: Alex Deucher 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 4a1d8f3457cc..e664e0414c6f 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1179,6 +1179,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav blackout &= ~BLACKOUT_MODE_MASK; WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); } + /* wait for the MC to settle */ + udelay(100); } void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) -- GitLab From b5d3ef25ca19150e30b0d3c0969349951134684b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sun, 27 Jan 2013 21:57:51 -0500 Subject: [PATCH 1594/1799] drm/radeon: add WAIT_UNTIL to the non-VM safe regs list for cayman/TN commit 674a16f2b4724880d07389abbb95abf320b924aa upstream. Newer versions of mesa emit this. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/reg_srcs/cayman | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 0f656b111c15..a072fa8c46b0 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,6 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x00008040 WAIT_UNTIL 0x000084FC CP_STRMOUT_CNTL 0x000085F0 CP_COHER_CNTL 0x000085F4 CP_COHER_SIZE -- GitLab From b5dc90fe1300df803e7c5b1922c759e135116251 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 29 Jan 2013 16:36:47 -0500 Subject: [PATCH 1595/1799] drm/radeon: add quirk for RV100 board commit 9200ee4941a6e5d1ec5df88982243686882dff3f upstream. vbios says external TMDS while the board is actually internal TMDS. fixes: https://bugs.freedesktop.org/show_bug.cgi?id=60037 Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_combios.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 2cad9fde92fc..a2470d96deb6 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -2338,6 +2338,14 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) 1), ATOM_DEVICE_CRT1_SUPPORT); } + /* RV100 board with external TDMS bit mis-set. + * Actually uses internal TMDS, clear the bit. + */ + if (dev->pdev->device == 0x5159 && + dev->pdev->subsystem_vendor == 0x1014 && + dev->pdev->subsystem_device == 0x029A) { + tmp &= ~(1 << 4); + } if ((tmp >> 4) & 0x1) { devices |= ATOM_DEVICE_DFP2_SUPPORT; radeon_add_legacy_encoder(dev, -- GitLab From c7d3c1787d491f55849d587e519a0bfe14d5f716 Mon Sep 17 00:00:00 2001 From: Christopher Staite Date: Sat, 26 Jan 2013 11:10:58 -0500 Subject: [PATCH 1596/1799] drm/radeon: fix MC blackout on evergreen+ commit bb588820ef421c6098dca1fec29c3b347f1c8c19 upstream. Force the crtc mem requests on/off immediately rather than waiting for the double buffered updates to kick in. Seems we miss the update in certain conditions. Also handle the DCE6 case. Signed-off-by: Christopher Staite Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index e664e0414c6f..c62132cecaf8 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1147,14 +1147,18 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { radeon_wait_for_vblank(rdev, i); tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); } } else { tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { radeon_wait_for_vblank(rdev, i); tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); } } /* wait for the next frame */ @@ -1214,11 +1218,15 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s if (ASIC_IS_DCE6(rdev)) { tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); } else { tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); } /* wait for the next frame */ frame_count = radeon_get_vblank_counter(rdev, i); -- GitLab From dcf73edd833be6d4999a7d8f6cc6941c9e475ce4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 30 Jan 2013 14:24:09 -0500 Subject: [PATCH 1597/1799] drm/radeon: prevent crash in the ring space allocation commit fd5d93a0015ce1a7db881382022b2fcdfdc61760 upstream. If the requested number of DWs on the ring is larger than the size of the ring itself, return an error. In testing with large VM updates, we've seen crashes when we try and allocate more space on the ring than the total size of the ring without checking. This prevents the crash but for large VM updates or bo moves of very large buffers, we will need to break the transaction down into multiple batches. I have patches to use IBs for the next kernel. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_ring.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index cc33b3d7c33b..33eff8bcabeb 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -311,6 +311,9 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi { int r; + /* make sure we aren't trying to allocate more space than there is on the ring */ + if (ndw > (ring->ring_size / 4)) + return -ENOMEM; /* Align requested size with padding so unlock_commit can * pad safely */ ndw = (ndw + ring->align_mask) & ~ring->align_mask; -- GitLab From 8f69eeaecbb7d741e943f7972627bbd1ca294ab6 Mon Sep 17 00:00:00 2001 From: liu chuansheng Date: Thu, 31 Jan 2013 22:13:00 +0800 Subject: [PATCH 1598/1799] drm/radeon: Calling object_unrefer() when creating fb failure commit f2d68cf4daa4de97d400d94836b907e35228e54f upstream. When kzalloc() failed in radeon_user_framebuffer_create(), need to call object_unreference() to match the object_reference(). Signed-off-by: liu chuansheng Signed-off-by: xueminsu Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_display.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 1f50727d210e..00d9cac69f93 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1129,8 +1129,10 @@ radeon_user_framebuffer_create(struct drm_device *dev, } radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL); - if (radeon_fb == NULL) + if (radeon_fb == NULL) { + drm_gem_object_unreference_unlocked(obj); return ERR_PTR(-ENOMEM); + } ret = radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj); if (ret) { -- GitLab From 11151f33ae2b29f8346f5ac1250c1879e3348cbc Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 30 Jan 2013 07:55:53 +0000 Subject: [PATCH 1599/1799] x86-64: Replace left over sti/cli in ia32 audit exit code commit 40a1ef95da85843696fc3ebe5fce39b0db32669f upstream. For some reason they didn't get replaced so far by their paravirt equivalents, resulting in code to be run with interrupts disabled that doesn't expect so (causing, in the observed case, a BUG_ON() to trigger) when syscall auditing is enabled. David (Cc-ed) came up with an identical fix, so likely this can be taken to count as an ack from him. Reported-by: Peter Moody Signed-off-by: Jan Beulich Cc: David Vrabel Cc: Konrad Rzeszutek Wilk Link: http://lkml.kernel.org/r/5108E01902000078000BA9C5@nat28.tlf.novell.com Signed-off-by: Ingo Molnar Cc: Konrad Rzeszutek Wilk Cc: David Vrabel Tested-by: Peter Moody Signed-off-by: Greg Kroah-Hartman --- arch/x86/ia32/ia32entry.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index e3e734005e19..66c4cae439c9 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -205,7 +205,7 @@ sysexit_from_sys_call: testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) jnz ia32_ret_from_sys_call TRACE_IRQS_ON - sti + ENABLE_INTERRUPTS(CLBR_NONE) movl %eax,%esi /* second arg, syscall return value */ cmpl $-MAX_ERRNO,%eax /* is it an error ? */ jbe 1f @@ -215,7 +215,7 @@ sysexit_from_sys_call: call __audit_syscall_exit movq RAX-ARGOFFSET(%rsp),%rax /* reload syscall return value */ movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi - cli + DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF testl %edi,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) jz \exit -- GitLab From 89960feebaf4f9a53f93a0ce6888207e4a808799 Mon Sep 17 00:00:00 2001 From: Shawn Bohrer Date: Mon, 14 Jan 2013 11:55:31 -0600 Subject: [PATCH 1600/1799] sched/rt: Use root_domain of rt_rq not current processor commit aa7f67304d1a03180f463258aa6f15a8b434e77d upstream. When the system has multiple domains do_sched_rt_period_timer() can run on any CPU and may iterate over all rt_rq in cpu_online_mask. This means when balance_runtime() is run for a given rt_rq that rt_rq may be in a different rd than the current processor. Thus if we use smp_processor_id() to get rd in do_balance_runtime() we may borrow runtime from a rt_rq that is not part of our rd. This changes do_balance_runtime to get the rd from the passed in rt_rq ensuring that we borrow runtime only from the correct rd for the given rt_rq. This fixes a BUG at kernel/sched/rt.c:687! in __disable_runtime when we try reclaim runtime lent to other rt_rq but runtime has been lent to a rt_rq in another rd. Signed-off-by: Shawn Bohrer Acked-by: Steven Rostedt Acked-by: Mike Galbraith Cc: peterz@infradead.org Link: http://lkml.kernel.org/r/1358186131-29494-1-git-send-email-sbohrer@rgmadvisors.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched/rt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 44af55e6d5d0..ead0336007be 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -560,7 +560,7 @@ static inline struct rt_bandwidth *sched_rt_bandwidth(struct rt_rq *rt_rq) static int do_balance_runtime(struct rt_rq *rt_rq) { struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq); - struct root_domain *rd = cpu_rq(smp_processor_id())->rd; + struct root_domain *rd = rq_of_rt_rq(rt_rq)->rd; int i, weight, more = 0; u64 rt_period; -- GitLab From 0b0a57362b8d1585f6909333fc667c73bae8205c Mon Sep 17 00:00:00 2001 From: Vyacheslav Dubeyko Date: Mon, 4 Feb 2013 14:28:41 -0800 Subject: [PATCH 1601/1799] nilfs2: fix fix very long mount time issue commit a9bae189542e71f91e61a4428adf6e5a7dfe8063 upstream. There exists a situation when GC can work in background alone without any other filesystem activity during significant time. The nilfs_clean_segments() method calls nilfs_segctor_construct() that updates superblocks in the case of NILFS_SC_SUPER_ROOT and THE_NILFS_DISCONTINUED flags are set. But when GC is working alone the nilfs_clean_segments() is called with unset THE_NILFS_DISCONTINUED flag. As a result, the update of superblocks doesn't occurred all this time and in the case of SPOR superblocks keep very old values of last super root placement. SYMPTOMS: Trying to mount a NILFS2 volume after SPOR in such environment ends with very long mounting time (it can achieve about several hours in some cases). REPRODUCING PATH: 1. It needs to use external USB HDD, disable automount and doesn't make any additional filesystem activity on the NILFS2 volume. 2. Generate temporary file with size about 100 - 500 GB (for example, dd if=/dev/zero of= bs=1073741824 count=200). The size of file defines duration of GC working. 3. Then it needs to delete file. 4. Start GC manually by means of command "nilfs-clean -p 0". When you start GC by means of such way then, at the end, superblocks is updated by once. So, for simulation of SPOR, it needs to wait sometime (15 - 40 minutes) and simply switch off USB HDD manually. 5. Switch on USB HDD again and try to mount NILFS2 volume. As a result, NILFS2 volume will mount during very long time. REPRODUCIBILITY: 100% FIX: This patch adds checking that superblocks need to update and set THE_NILFS_DISCONTINUED flag before nilfs_clean_segments() call. Reported-by: Sergey Alexandrov Signed-off-by: Vyacheslav Dubeyko Tested-by: Vyacheslav Dubeyko Acked-by: Ryusuke Konishi Tested-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/nilfs2/ioctl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 6fe98ed58545..372949338915 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -666,8 +666,11 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, if (ret < 0) printk(KERN_ERR "NILFS: GC failed during preparation: " "cannot read source blocks: err=%d\n", ret); - else + else { + if (nilfs_sb_need_update(nilfs)) + set_nilfs_discontinued(nilfs); ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); + } nilfs_remove_all_gcinodes(nilfs); clear_nilfs_gc_running(nilfs); -- GitLab From 1a9277bba9cfcfac12b204dcf72b0cb019b3b65d Mon Sep 17 00:00:00 2001 From: Jan Luebbe Date: Mon, 4 Feb 2013 14:28:53 -0800 Subject: [PATCH 1602/1799] drivers/rtc/rtc-isl1208.c: call rtc_update_irq() from the alarm irq handler commit 72fca4a4b32dc778b5b885c3498700e42b610d49 upstream. Previously the alarm event was not propagated into the RTC subsystem. By adding a call to rtc_update_irq, this fixes a timeout problem with the hwclock utility. Signed-off-by: Jan Luebbe Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-isl1208.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index dd2aeee6c66a..8f8c8ae3523a 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -494,6 +494,7 @@ isl1208_rtc_interrupt(int irq, void *data) { unsigned long timeout = jiffies + msecs_to_jiffies(1000); struct i2c_client *client = data; + struct rtc_device *rtc = i2c_get_clientdata(client); int handled = 0, sr, err; /* @@ -516,6 +517,8 @@ isl1208_rtc_interrupt(int irq, void *data) if (sr & ISL1208_REG_SR_ALM) { dev_dbg(&client->dev, "alarm!\n"); + rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF); + /* Clear the alarm */ sr &= ~ISL1208_REG_SR_ALM; sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr); -- GitLab From 649d7a793033f428bc85430109069dab35fe8782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Kub=C3=A1nek?= Date: Fri, 1 Feb 2013 17:24:04 +0100 Subject: [PATCH 1603/1799] USB: ftdi_sio: add Zolix FTDI PID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 0ba3b2ccc72b3df5c305d61f59d93ab0f0e87991 upstream. Add support for Zolix Omni 1509 monochromator custom USB-RS232 converter. Signed-off-by: Petr Kubánek 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 3fbf39d66a7a..47a9ebc3ff29 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -676,6 +676,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) }, { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index fa5d56038276..a8915f3da73d 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -147,6 +147,11 @@ #define XSENS_CONVERTER_6_PID 0xD38E #define XSENS_CONVERTER_7_PID 0xD38F +/** + * Zolix (www.zolix.com.cb) product ids + */ +#define FTDI_OMNI1509 0xD491 /* Omni1509 embedded USB-serial */ + /* * NDI (www.ndigital.com) product ids */ -- GitLab From 66a76eb58058527e579bf82aad0a926bac7fcb09 Mon Sep 17 00:00:00 2001 From: Sven Killig Date: Fri, 1 Feb 2013 23:43:06 +0100 Subject: [PATCH 1604/1799] USB: ftdi_sio: add PID/VID entries for ELV WS 300 PC II commit c249f911406efcc7456cb4af79396726bf7b8c57 upstream. Add PID/VID entries for ELV WS 300 PC II weather station Signed-off-by: Sven Killig Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 47a9ebc3ff29..77469442b3fa 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -590,6 +590,7 @@ static struct usb_device_id id_table_combined [] = { /* * ELV devices: */ + { USB_DEVICE(FTDI_ELV_VID, FTDI_ELV_WS300_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index a8915f3da73d..9d359e189a64 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -209,7 +209,7 @@ /* * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). - * All of these devices use FTDI's vendor ID (0x0403). + * Almost all of these devices use FTDI's vendor ID (0x0403). * Further IDs taken from ELV Windows .inf file. * * The previously included PID for the UO 100 module was incorrect. @@ -217,6 +217,8 @@ * * Armin Laeuger originally sent the PID for the UM 100 module. */ +#define FTDI_ELV_VID 0x1B1F /* ELV AG */ +#define FTDI_ELV_WS300_PID 0xC006 /* eQ3 WS 300 PC II */ #define FTDI_ELV_USR_PID 0xE000 /* ELV Universal-Sound-Recorder */ #define FTDI_ELV_MSM1_PID 0xE001 /* ELV Mini-Sound-Modul */ #define FTDI_ELV_KL100_PID 0xE002 /* ELV Kfz-Leistungsmesser KL 100 */ -- GitLab From de4399132e911ca24bd642c7a0f659a0d6a35169 Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Mon, 28 Jan 2013 16:47:10 +0100 Subject: [PATCH 1605/1799] USB: option: add support for Telit LE920 commit 03eb466f276ceef9dcf023dc5474db02af68aad9 upstream. Add PID and special handling for Telit LE920 Signed-off-by: Daniele Palmas Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 0778cd098521..d7d8792d8bec 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -242,6 +242,7 @@ static void option_instat_callback(struct urb *urb); #define TELIT_PRODUCT_CC864_DUAL 0x1005 #define TELIT_PRODUCT_CC864_SINGLE 0x1006 #define TELIT_PRODUCT_DE910_DUAL 0x1010 +#define TELIT_PRODUCT_LE920 0x1200 /* ZTE PRODUCTS */ #define ZTE_VENDOR_ID 0x19d2 @@ -534,6 +535,11 @@ static const struct option_blacklist_info zte_1255_blacklist = { .reserved = BIT(3) | BIT(4), }; +static const struct option_blacklist_info telit_le920_blacklist = { + .sendsetup = BIT(0), + .reserved = BIT(1) | BIT(5), +}; + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -784,6 +790,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), + .driver_info = (kernel_ulong_t)&telit_le920_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, -- GitLab From fdc3c54a639e9acdd5b391283b1e613d1c99de16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 1 Feb 2013 12:06:51 +0100 Subject: [PATCH 1606/1799] USB: option: add Changhong CH690 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d4fa681541aa7bf8570d03426dd7ba663a71c467 upstream. New device with 3 serial interfaces: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend) Sub=ff Prot=ff If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend) Sub=ff Prot=ff If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend) Sub=ff Prot=ff If#= 3 Alt= 0 #EPs= 2 Cls=08(stor) Sub=06 Prot=50 Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- 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 d7d8792d8bec..6c077a174bfd 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -454,6 +454,10 @@ static void option_instat_callback(struct urb *urb); #define TPLINK_VENDOR_ID 0x2357 #define TPLINK_PRODUCT_MA180 0x0201 +/* Changhong products */ +#define CHANGHONG_VENDOR_ID 0x2077 +#define CHANGHONG_PRODUCT_CH690 0x7001 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -1326,6 +1330,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- GitLab From 18591ae05a4bc4f505ae5a7d6e58962900226443 Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Mon, 28 Jan 2013 16:48:54 +0100 Subject: [PATCH 1607/1799] USB: qcserial: add Telit Gobi QDL device commit 78796ae17eacedcdcaaeb03ba73d2e532a4c8f83 upstream. Add VID and PID for Telit Gobi QDL device Signed-off-by: Daniele Palmas Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcserial.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 50b5371719f2..d46277d33073 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -55,6 +55,7 @@ static const struct usb_device_id id_table[] = { {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ + {DEVICE_G1K(0x1bc7, 0x900e)}, /* Telit Gobi QDL device */ /* Gobi 2000 devices */ {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */ -- GitLab From f4cc7a1602ed1bb673cf86b6ccc10f72e1cfaae4 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 25 Jan 2013 17:17:43 -0500 Subject: [PATCH 1608/1799] USB: EHCI: fix timer bug affecting port resume commit ee74290b7853db9d5fd64db70e5c175241c59fba upstream. This patch (as1652) fixes a long-standing bug in ehci-hcd. The driver relies on status polls to know when to stop port-resume signalling. It uses the root-hub status timer to schedule these status polls. But when the driver for the root hub is resumed, the timer is rescheduled to go off immediately -- before the port is ready. When this happens the timer does not get re-enabled, which prevents the port resume from finishing until some other event occurs. The symptom is that when a new device is plugged in, it doesn't get recognized or enumerated until lsusb is run or something else happens. The solution is to re-enable the root-hub status timer after every status poll while a port resume is in progress. This bug hasn't surfaced before now because we never used to try to suspend the root hub in the middle of a port resume (except by coincidence). Signed-off-by: Alan Stern Reported-and-tested-by: Norbert Preining Tested-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 38fe07623152..3cb52a938031 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -612,7 +612,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) status = STS_PCD; } } - /* FIXME autosuspend idle root hubs */ + + /* If a resume is in progress, make sure it can finish */ + if (ehci->resuming_ports) + mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25)); + spin_unlock_irqrestore (&ehci->lock, flags); return status ? retval : 0; } -- GitLab From 5b70af1c0b0088151a1e7a8917527e190ddd76d7 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 30 Jan 2013 16:36:40 -0500 Subject: [PATCH 1609/1799] USB: EHCI: fix bug in scheduling periodic split transfers commit 3e619d04159be54b3daa0b7036b0ce9e067f4b5d upstream. This patch (as1654) fixes a very old bug in ehci-hcd, connected with scheduling of periodic split transfers. The calculations for full/low-speed bus usage are all carried out after the correction for bit-stuffing has been applied, but the values in the max_tt_usecs array assume it hasn't been. The array should allow for allocation of up to 90% of the bus capacity, which is 900 us, not 780 us. The symptom caused by this bug is that any isochronous transfer to a full-speed device with a maxpacket size larger than about 980 bytes is always rejected with a -ENOSPC error. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index a60679cbbf85..14d2d71163ff 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -236,7 +236,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) } static const unsigned char -max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; +max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 }; /* carryover low/fullspeed bandwidth that crosses uframe boundries */ static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) -- GitLab From 7ad8ac9444d54af92c61c2fa7d02cbf96c990bc5 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Thu, 24 Jan 2013 10:31:28 +0800 Subject: [PATCH 1610/1799] usb: Using correct way to clear usb3.0 device's remote wakeup feature. commit 54a3ac0c9e5b7213daa358ce74d154352657353a upstream. Usb3.0 device defines function remote wakeup which is only for interface recipient rather than device recipient. This is different with usb2.0 device's remote wakeup feature which is defined for device recipient. According usb3.0 spec 9.4.5, the function remote wakeup can be modified by the SetFeature() requests using the FUNCTION_SUSPEND feature selector. This patch is to use correct way to disable usb3.0 device's function remote wakeup after suspend error and resuming. This should be backported to kernels as old as 3.4, that contain the commit 623bef9e03a60adc623b09673297ca7a1cdfb367 "USB/xhci: Enable remote wakeup for USB3 devices." Signed-off-by: Lan Tianyu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 70 ++++++++++++++++++++++++++++++----------- include/linux/usb/ch9.h | 6 ++++ 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index ef8f790d6172..67dda0dbf81b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2463,6 +2463,23 @@ static int check_port_resume_type(struct usb_device *udev, } #ifdef CONFIG_USB_SUSPEND +/* + * usb_disable_function_remotewakeup - disable usb3.0 + * device's function remote wakeup + * @udev: target device + * + * Assume there's only one function on the USB 3.0 + * device and disable remote wake for the first + * interface. FIXME if the interface association + * descriptor shows there's more than one function. + */ +static int usb_disable_function_remotewakeup(struct usb_device *udev) +{ + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); +} /* * usb_port_suspend - suspend a usb device's upstream port @@ -2569,12 +2586,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", port1, status); /* paranoia: "should not happen" */ - if (udev->do_remote_wakeup) - (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); + if (udev->do_remote_wakeup) { + if (!hub_is_superspeed(hub->hdev)) { + (void) usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, + USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else + (void) usb_disable_function_remotewakeup(udev); + + } /* Try to enable USB2 hardware LPM again */ if (udev->usb2_hw_lpm_capable == 1) @@ -2661,20 +2685,30 @@ static int finish_port_resume(struct usb_device *udev) * udev->reset_resume */ } else if (udev->actconfig && !udev->reset_resume) { - le16_to_cpus(&devstatus); - if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { - status = usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, + if (!hub_is_superspeed(udev->parent)) { + le16_to_cpus(&devstatus); + if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) + status = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); - if (status) - dev_dbg(&udev->dev, - "disable remote wakeup, status %d\n", - status); + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, + &devstatus); + le16_to_cpus(&devstatus); + if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP + | USB_INTRF_STAT_FUNC_RW)) + status = + usb_disable_function_remotewakeup(udev); } + + if (status) + dev_dbg(&udev->dev, + "disable remote wakeup, status %d\n", + status); status = 0; } return status; diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index af21f3115919..091fdb7b9d5f 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -150,6 +150,12 @@ #define USB_INTRF_FUNC_SUSPEND_LP (1 << (8 + 0)) #define USB_INTRF_FUNC_SUSPEND_RW (1 << (8 + 1)) +/* + * Interface status, Figure 9-5 USB 3.0 spec + */ +#define USB_INTRF_STAT_FUNC_RW_CAP 1 +#define USB_INTRF_STAT_FUNC_RW 2 + #define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ /* Bit array elements as returned by the USB_REQ_GET_STATUS request. */ -- GitLab From fae3bb5e23fef7eee49545341601a407c090cf88 Mon Sep 17 00:00:00 2001 From: fangxiaozhi Date: Mon, 4 Feb 2013 15:14:46 +0800 Subject: [PATCH 1611/1799] USB: storage: Define a new macro for USB storage match rules commit 07c7be3d87e5cdaf5f94c271c516456364ef286c upstream. 1. Define a new macro for USB storage match rules: matching with Vendor ID and interface descriptors. Signed-off-by: fangxiaozhi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/usb.c | 12 ++++++++++++ drivers/usb/storage/usual-tables.c | 15 +++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 2653e73db623..e73cf5630f8f 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -120,6 +120,17 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks"); .useTransport = use_transport, \ } +#define UNUSUAL_VENDOR_INTF(idVendor, cl, sc, pr, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + static struct us_unusual_dev us_unusual_dev_list[] = { # include "unusual_devs.h" { } /* Terminating entry */ @@ -131,6 +142,7 @@ static struct us_unusual_dev for_dynamic_ids = #undef UNUSUAL_DEV #undef COMPLIANT_DEV #undef USUAL_DEV +#undef UNUSUAL_VENDOR_INTF #ifdef CONFIG_LOCKDEP diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index b96927914f89..a9b5f2e29189 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -46,6 +46,20 @@ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ .driver_info = ((useType)<<24) } +/* Define the device is matched with Vendor ID and interface descriptors */ +#define UNUSUAL_VENDOR_INTF(id_vendor, cl, sc, pr, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ \ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \ + | USB_DEVICE_ID_MATCH_VENDOR, \ + .idVendor = (id_vendor), \ + .bInterfaceClass = (cl), \ + .bInterfaceSubClass = (sc), \ + .bInterfaceProtocol = (pr), \ + .driver_info = (flags) \ +} + struct usb_device_id usb_storage_usb_ids[] = { # include "unusual_devs.h" { } /* Terminating entry */ @@ -57,6 +71,7 @@ MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids); #undef UNUSUAL_DEV #undef COMPLIANT_DEV #undef USUAL_DEV +#undef UNUSUAL_VENDOR_INTF /* -- GitLab From c42fc5a5c545964d97b3c0910ab7c30672155d04 Mon Sep 17 00:00:00 2001 From: fangxiaozhi Date: Mon, 4 Feb 2013 15:16:34 +0800 Subject: [PATCH 1612/1799] USB: storage: optimize to match the Huawei USB storage devices and support new switch command commit 200e0d994d9d1919b28c87f1a5fb99a8e13b8a0f upstream. 1. Optimize the match rules with new macro for Huawei USB storage devices, to avoid to load USB storage driver for the modem interface with Huawei devices. 2. Add to support new switch command for new Huawei USB dongles. Signed-off-by: fangxiaozhi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/initializers.c | 76 ++++++- drivers/usb/storage/initializers.h | 4 +- drivers/usb/storage/unusual_devs.h | 329 +---------------------------- 3 files changed, 78 insertions(+), 331 deletions(-) diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 105d900150c1..16b0bf055eeb 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c @@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us) return 0; } -/* This places the HUAWEI E220 devices in multi-port mode */ -int usb_stor_huawei_e220_init(struct us_data *us) +/* This places the HUAWEI usb dongles in multi-port mode */ +static int usb_stor_huawei_feature_init(struct us_data *us) { int result; @@ -104,3 +104,75 @@ int usb_stor_huawei_e220_init(struct us_data *us) US_DEBUGP("Huawei mode set result is %d\n", result); return 0; } + +/* + * It will send a scsi switch command called rewind' to huawei dongle. + * When the dongle receives this command at the first time, + * it will reboot immediately. After rebooted, it will ignore this command. + * So it is unnecessary to read its response. + */ +static int usb_stor_huawei_scsi_init(struct us_data *us) +{ + int result = 0; + int act_len = 0; + struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf; + char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN); + bcbw->Tag = 0; + bcbw->DataTransferLength = 0; + bcbw->Flags = bcbw->Lun = 0; + bcbw->Length = sizeof(rewind_cmd); + memset(bcbw->CDB, 0, sizeof(bcbw->CDB)); + memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd)); + + result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw, + US_BULK_CB_WRAP_LEN, &act_len); + US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result); + return result; +} + +/* + * It tries to find the supported Huawei USB dongles. + * In Huawei, they assign the following product IDs + * for all of their mobile broadband dongles, + * including the new dongles in the future. + * So if the product ID is not included in this list, + * it means it is not Huawei's mobile broadband dongles. + */ +static int usb_stor_huawei_dongles_pid(struct us_data *us) +{ + struct usb_interface_descriptor *idesc; + int idProduct; + + idesc = &us->pusb_intf->cur_altsetting->desc; + idProduct = us->pusb_dev->descriptor.idProduct; + /* The first port is CDROM, + * means the dongle in the single port mode, + * and a switch command is required to be sent. */ + if (idesc && idesc->bInterfaceNumber == 0) { + if ((idProduct == 0x1001) + || (idProduct == 0x1003) + || (idProduct == 0x1004) + || (idProduct >= 0x1401 && idProduct <= 0x1500) + || (idProduct >= 0x1505 && idProduct <= 0x1600) + || (idProduct >= 0x1c02 && idProduct <= 0x2202)) { + return 1; + } + } + return 0; +} + +int usb_stor_huawei_init(struct us_data *us) +{ + int result = 0; + + if (usb_stor_huawei_dongles_pid(us)) { + if (us->pusb_dev->descriptor.idProduct >= 0x1446) + result = usb_stor_huawei_scsi_init(us); + else + result = usb_stor_huawei_feature_init(us); + } + return result; +} diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h index 529327fbb06b..5376d4fc76f0 100644 --- a/drivers/usb/storage/initializers.h +++ b/drivers/usb/storage/initializers.h @@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us); * flash reader */ int usb_stor_ucr61s2b_init(struct us_data *us); -/* This places the HUAWEI E220 devices in multi-port mode */ -int usb_stor_huawei_e220_init(struct us_data *us); +/* This places the HUAWEI usb dongles in multi-port mode */ +int usb_stor_huawei_init(struct us_data *us); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 5ffa11640de4..27858f9a20e4 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1515,335 +1515,10 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100, /* Reported by fangxiaozhi * This brings the HUAWEI data card devices into multi-port mode */ -UNUSUAL_DEV( 0x12d1, 0x1001, 0x0000, 0x0000, +UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50, "HUAWEI MOBILE", "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1004, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1401, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1402, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1403, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1404, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1405, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1406, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1407, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1408, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1409, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x140A, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x140B, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x140C, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x140D, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x140E, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x140F, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1410, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1411, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1412, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1413, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1414, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1415, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1416, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1417, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1418, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1419, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x141A, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x141B, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x141C, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x141D, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x141E, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x141F, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1420, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1421, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1422, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1423, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1424, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1425, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1426, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1427, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1428, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1429, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x142A, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x142B, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x142C, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x142D, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x142E, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x142F, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1430, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1431, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1432, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1433, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1434, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1435, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1436, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1437, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1438, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1439, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x143A, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x143B, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x143C, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x143D, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x143E, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x143F, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init, 0), /* Reported by Vilius Bilinkevicius Date: Mon, 7 Jan 2013 22:39:31 -0500 Subject: [PATCH 1613/1799] drivers: xhci: fix incorrect bit test commit ba7b5c22d33136a5612ca5ef8d31564dcc501126 upstream. Fix incorrect bit test that originally showed up in 4ee823b83bc9851743fab756c76b27d6a1e2472b "USB/xHCI: Support device-initiated USB 3.0 resume." Use '&' instead of '&&'. This should be backported to kernels as old as 3.4. Signed-off-by: Nickolai Zeldovich 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 01361f929f1d..59cdde9d604c 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1698,7 +1698,7 @@ static void handle_port_status(struct xhci_hcd *xhci, faked_port_index + 1); if (slot_id && xhci->devs[slot_id]) xhci_ring_device(xhci, slot_id); - if (bus_state->port_remote_wakeup && (1 << faked_port_index)) { + if (bus_state->port_remote_wakeup & (1 << faked_port_index)) { bus_state->port_remote_wakeup &= ~(1 << faked_port_index); xhci_test_and_clear_bit(xhci, port_array, -- GitLab From 1757e241ae2c9758bd983250b94328bddeff8760 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 11 Jan 2013 11:19:07 -0800 Subject: [PATCH 1614/1799] xhci: Fix isoc TD encoding. commit 760973d2a74b93eb1697981f7448f0e62767cfc4 upstream. An isochronous TD is comprised of one isochronous TRB chained to zero or more normal TRBs. Only the isoc TRB has the TBC and TLBPC fields. The normal TRBs must set those fields to zeroes. The code was setting the TBC and TLBPC fields for both isoc and normal TRBs. Fix this. This should be backported to stable kernels as old as 3.0, that contain the commit b61d378f2da41c748aba6ca19d77e1e1c02bcea5 " xhci 1.0: Set transfer burst last packet count field." Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 59cdde9d604c..834929f64054 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3662,9 +3662,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, td = urb_priv->td[i]; for (j = 0; j < trbs_per_td; j++) { u32 remainder = 0; - field = TRB_TBC(burst_count) | TRB_TLBPC(residue); + field = 0; if (first_trb) { + field = TRB_TBC(burst_count) | + TRB_TLBPC(residue); /* Queue the isoc TRB */ field |= TRB_TYPE(TRB_ISOC); /* Assume URB_ISO_ASAP is set */ -- GitLab From d018dbbf6e7e3d588b09273c38ea57bc666d474c Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 11 Jan 2013 13:36:35 -0800 Subject: [PATCH 1615/1799] xhci: Fix TD size for isochronous URBs. commit f18f8ed2a9adc41c2d9294b85b6af115829d2af1 upstream. To calculate the TD size for a particular TRB in an isoc TD, we need know the endpoint's max packet size. Isochronous endpoints also encode the number of additional service opportunities in their wMaxPacketSize field. The TD size calculation did not mask off those bits before using the field. This resulted in incorrect TD size information for isochronous TRBs when an URB frame buffer crossed a 64KB boundary. For example: - an isoc endpoint has 2 additional service opportunites and a max packet size of 1020 bytes - a frame transfer buffer contains 3060 bytes - one frame buffer crosses a 64KB boundary, and must be split into one 1276 byte TRB, and one 1784 byte TRB. The TD size is is the number of packets that remain to be transferred for a TD after processing all the max packet sized packets in the current TRB and all previous TRBs. For this TD, the number of packets to be transferred is (3060 / 1020), or 3. The first TRB contains 1276 bytes, which means it contains one full packet, and a 256 byte remainder. After processing all the max packet-sized packets in the first TRB, the host will have 2 packets left to transfer. The old code would calculate the TD size for the first TRB as: total packet count = DIV_ROUND_UP (TD length / endpoint wMaxPacketSize) total packet count - (first TRB length / endpoint wMaxPacketSize) The math should have been: total packet count = DIV_ROUND_UP (3060 / 1020) = 3 3 - (1276 / 1020) = 2 Since the old code didn't mask off the additional service interval bits from the wMaxPacketSize field, the math ended up as total packet count = DIV_ROUND_UP (3060 / 5116) = 1 1 - (1276 / 5116) = 1 Fix this by masking off the number of additional service opportunities in the wMaxPacketSize field. This patch should be backported to stable kernels as old as 3.0, that contain the commit 4da6e6f247a2601ab9f1e63424e4d944ed4124f3 "xhci 1.0: Update TD size field format." It may not apply well to kernels older than 3.2 because of commit 29cc88979a8818cd8c5019426e945aed118b400e "USB: use usb_endpoint_maxp() instead of le16_to_cpu()". Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 834929f64054..8e2169496a99 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3106,7 +3106,7 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len, * running_total. */ packets_transferred = (running_total + trb_buff_len) / - usb_endpoint_maxp(&urb->ep->desc); + GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); if ((total_packet_count - packets_transferred) > 31) return 31 << 17; @@ -3640,7 +3640,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, td_len = urb->iso_frame_desc[i].length; td_remain_len = td_len; total_packet_count = DIV_ROUND_UP(td_len, - usb_endpoint_maxp(&urb->ep->desc)); + GET_MAX_PACKET( + usb_endpoint_maxp(&urb->ep->desc))); /* A zero-length transfer still involves at least one packet. */ if (total_packet_count == 0) total_packet_count++; -- GitLab From 235b62026c1f73decda124912930e322dc8ec57d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 17 Jan 2013 10:32:16 -0500 Subject: [PATCH 1616/1799] USB: XHCI: fix memory leak of URB-private data commit 48c3375c5f69b1c2ef3d1051a0009cb9bce0ce24 upstream. This patch (as1640) fixes a memory leak in xhci-hcd. The urb_priv data structure isn't always deallocated in the handle_tx_event() routine for non-control transfers. The patch adds a kfree() call so that all paths end up freeing the memory properly. This patch should be backported to kernels as old as 2.6.36, that contain the commit 8e51adccd4c4b9ffcd509d7f2afce0a906139f75 "USB: xHCI: Introduce urb_priv structure" Signed-off-by: Alan Stern Signed-off-by: Sarah Sharp Reported-and-tested-by: Martin Mokrejs Signed-off-by: Greg Kroah-Hartman --- 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 8e2169496a99..87ee86d6fbf5 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2587,6 +2587,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, (trb_comp_code != COMP_STALL && trb_comp_code != COMP_BABBLE)) xhci_urb_free_priv(xhci, urb_priv); + else + kfree(urb_priv); usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb); if ((urb->actual_length != urb->transfer_buffer_length && -- GitLab From b4e8be42e038f1b931a44bc93050f8a261b495a1 Mon Sep 17 00:00:00 2001 From: David Moore Date: Wed, 23 Jan 2013 22:19:49 -0800 Subject: [PATCH 1617/1799] usb: Prevent dead ports when xhci is not enabled commit 58b2939b4d5a030eaec469d29812ab8477ee7e76 upstream. When the xHCI driver is not available, actively switch the ports to EHCI mode since some BIOSes leave them in xHCI mode where they would otherwise appear dead. This was discovered on a Dell Optiplex 7010, but it's possible other systems could be affected. This should be backported to kernels as old as 3.0, that contain the commit 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support EHCI/xHCI port switching." Signed-off-by: David Moore Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index eb5563ac58bc..78933512c18b 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -780,6 +780,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) "defaulting to EHCI.\n"); dev_warn(&xhci_pdev->dev, "USB 3.0 devices will work at USB 2.0 speeds.\n"); + usb_disable_xhci_ports(xhci_pdev); return; } -- GitLab From c74d85ba3bdb907d23419c77e43a5d6800bafa84 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 11 Feb 2013 08:47:55 -0800 Subject: [PATCH 1618/1799] Linux 3.4.30 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 23bcb1a6604d..4941fd9876e6 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 29 +SUBLEVEL = 30 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 5f2ffd29fe0438dfb683a8f0ca0e451408e36970 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 27 Jan 2013 16:24:25 -0600 Subject: [PATCH 1619/1799] rtlwifi: Fix the usage of the wrong variable in usb.c commit 0a06ad8e3a1cb5311b7dbafde45410aa1bce9d40 upstream. In routine _rtl_rx_pre_process(), skb_dequeue() is called to get an skb; however, the wrong variable name is used in subsequent calls. Reported-by: Guenter Roeck Signed-off-by: Larry Finger Cc: Guenter Roeck Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 8fa144fa0c99..17cd028d2351 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -542,8 +542,8 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb) WARN_ON(skb_queue_empty(&rx_queue)); while (!skb_queue_empty(&rx_queue)) { _skb = skb_dequeue(&rx_queue); - _rtl_usb_rx_process_agg(hw, skb); - ieee80211_rx_irqsafe(hw, skb); + _rtl_usb_rx_process_agg(hw, _skb); + ieee80211_rx_irqsafe(hw, _skb); } } -- GitLab From 5327297d3596654ca58e8a79ec38fa48c8f83fc0 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 2 Feb 2013 15:55:00 -0600 Subject: [PATCH 1620/1799] rtlwifi: Fix scheduling while atomic bug commit a5ffbe0a1993a27072742ef7db6cf9839956fce9 upstream. Kernel commits 41affd5 and 6539306 changed the locking in rtl_lps_leave() from a spinlock to a mutex by doing the calls indirectly from a work queue to reduce the time that interrupts were disabled. This change was fine for most systems; however a scheduling while atomic bug was reported in https://bugzilla.redhat.com/show_bug.cgi?id=903881. The backtrace indicates that routine rtl_is_special(), which calls rtl_lps_leave() in three places was entered in atomic context. These direct calls are replaced by putting a request on the appropriate work queue. Signed-off-by: Larry Finger Reported-and-tested-by: Nathaniel Doherty Cc: Nathaniel Doherty Cc: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/base.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index e54488db0e10..18d9eb3ad7af 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -980,7 +980,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) is_tx ? "Tx" : "Rx"); if (is_tx) { - rtl_lps_leave(hw); + schedule_work(&rtlpriv-> + works.lps_leave_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } @@ -990,7 +991,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) } } else if (ETH_P_ARP == ether_type) { if (is_tx) { - rtl_lps_leave(hw); + schedule_work(&rtlpriv->works.lps_leave_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } @@ -1000,7 +1001,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); if (is_tx) { - rtl_lps_leave(hw); + schedule_work(&rtlpriv->works.lps_leave_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } -- GitLab From 0b2d4e113bf714732b041aa879945c4c5ae4b139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sjur=20Br=C3=A6ndeland?= Date: Tue, 22 Jan 2013 09:50:26 +1030 Subject: [PATCH 1621/1799] virtio_console: Don't access uninitialized data. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit aded024a12b32fc1ed9a80639681daae2d07ec25 upstream. Don't access uninitialized work-queue when removing device. The work queue is initialized only if the device multi-queue. So don't call cancel_work unless this is a multi-queue device. This fixes the following panic: Kernel panic - not syncing: BUG! Call Trace: 62031b28: [<6026085d>] panic+0x16b/0x2d3 62031b30: [<6004ef5e>] flush_work+0x0/0x1d7 62031b60: [<602606f2>] panic+0x0/0x2d3 62031b68: [<600333b0>] memcpy+0x0/0x140 62031b80: [<6002d58a>] unblock_signals+0x0/0x84 62031ba0: [<602609c5>] printk+0x0/0xa0 62031bd8: [<60264e51>] __mutex_unlock_slowpath+0x13d/0x148 62031c10: [<6004ef5e>] flush_work+0x0/0x1d7 62031c18: [<60050234>] try_to_grab_pending+0x0/0x17e 62031c38: [<6004e984>] get_work_gcwq+0x71/0x8f 62031c48: [<60050539>] __cancel_work_timer+0x5b/0x115 62031c78: [<628acc85>] unplug_port+0x0/0x191 [virtio_console] 62031c98: [<6005061c>] cancel_work_sync+0x12/0x14 62031ca8: [<628ace96>] virtcons_remove+0x80/0x15c [virtio_console] 62031ce8: [<628191de>] virtio_dev_remove+0x1e/0x7e [virtio] 62031d08: [<601cf242>] __device_release_driver+0x75/0xe4 62031d28: [<601cf2dd>] device_release_driver+0x2c/0x40 62031d48: [<601ce0dd>] driver_unbind+0x7d/0xc6 62031d88: [<601cd5d9>] drv_attr_store+0x27/0x29 62031d98: [<60115f61>] sysfs_write_file+0x100/0x14d 62031df8: [<600b737d>] vfs_write+0xcb/0x184 62031e08: [<600b58b8>] filp_close+0x88/0x94 62031e38: [<600b7686>] sys_write+0x59/0x88 62031e88: [<6001ced1>] handle_syscall+0x5d/0x80 62031ea8: [<60030a74>] userspace+0x405/0x531 62031f08: [<600d32cc>] sys_dup+0x0/0x5e 62031f28: [<601b11d6>] strcpy+0x0/0x18 62031f38: [<600be46c>] do_execve+0x10/0x12 62031f48: [<600184c7>] run_init_process+0x43/0x45 62031fd8: [<60019a91>] new_thread_handler+0xba/0xbc Signed-off-by: Sjur Brændeland Signed-off-by: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- drivers/char/virtio_console.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index cdf2f5451c76..f77e341631d7 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1808,7 +1808,8 @@ static void virtcons_remove(struct virtio_device *vdev) /* Disable interrupts for vqs */ vdev->config->reset(vdev); /* Finish up work that's lined up */ - cancel_work_sync(&portdev->control_work); + if (use_multiport(portdev)) + cancel_work_sync(&portdev->control_work); list_for_each_entry_safe(port, port2, &portdev->ports, list) unplug_port(port); -- GitLab From 7308f843f36c30dd1247989a45611760567ea44f Mon Sep 17 00:00:00 2001 From: T Makphaibulchoke Date: Thu, 4 Oct 2012 17:16:55 -0700 Subject: [PATCH 1622/1799] kernel/resource.c: fix stack overflow in __reserve_region_with_split() commit 4965f5667f36a95b41cda6638875bc992bd7d18b upstream. Using a recursive call add a non-conflicting region in __reserve_region_with_split() could result in a stack overflow in the case that the recursive calls are too deep. Convert the recursive calls to an iterative loop to avoid the problem. Tested on a machine containing 135 regions. The kernel no longer panicked with stack overflow. Also tested with code arbitrarily adding regions with no conflict, embedding two consecutive conflicts and embedding two non-consecutive conflicts. Signed-off-by: T Makphaibulchoke Reviewed-by: Ram Pai Cc: Paul Gortmaker Cc: Wei Yang Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- kernel/resource.c | 50 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/kernel/resource.c b/kernel/resource.c index 7e8ea66a8c01..bfe96b83497c 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -758,6 +758,7 @@ static void __init __reserve_region_with_split(struct resource *root, struct resource *parent = root; struct resource *conflict; struct resource *res = kzalloc(sizeof(*res), GFP_ATOMIC); + struct resource *next_res = NULL; if (!res) return; @@ -767,21 +768,46 @@ static void __init __reserve_region_with_split(struct resource *root, res->end = end; res->flags = IORESOURCE_BUSY; - conflict = __request_resource(parent, res); - if (!conflict) - return; + while (1) { - /* failed, split and try again */ - kfree(res); + conflict = __request_resource(parent, res); + if (!conflict) { + if (!next_res) + break; + res = next_res; + next_res = NULL; + continue; + } - /* conflict covered whole area */ - if (conflict->start <= start && conflict->end >= end) - return; + /* conflict covered whole area */ + if (conflict->start <= res->start && + conflict->end >= res->end) { + kfree(res); + WARN_ON(next_res); + break; + } + + /* failed, split and try again */ + if (conflict->start > res->start) { + end = res->end; + res->end = conflict->start - 1; + if (conflict->end < end) { + next_res = kzalloc(sizeof(*next_res), + GFP_ATOMIC); + if (!next_res) { + kfree(res); + break; + } + next_res->name = name; + next_res->start = conflict->end + 1; + next_res->end = end; + next_res->flags = IORESOURCE_BUSY; + } + } else { + res->start = conflict->end + 1; + } + } - if (conflict->start > start) - __reserve_region_with_split(root, start, conflict->start-1, name); - if (conflict->end < end) - __reserve_region_with_split(root, conflict->end+1, end, name); } void __init reserve_region_with_split(struct resource *root, -- GitLab From a256a4c2001293548f0851b66ea8f39b704bac72 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 29 Jan 2013 10:44:23 -0600 Subject: [PATCH 1623/1799] Bluetooth: Fix handling of unexpected SMP PDUs commit 8cf9fa1240229cbdd888236c0c43fcbad680cf00 upstream. The conn->smp_chan pointer can be NULL if SMP PDUs arrive at unexpected moments. To avoid NULL pointer dereferences the code should be checking for this and disconnect if an unexpected SMP PDU arrives. This patch fixes the issue by adding a check for conn->smp_chan for all other PDUs except pairing request and security request (which are are the first PDUs to come to initialize the SMP context). Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/smp.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 208edc0cc60f..605156f13899 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -852,6 +852,19 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) skb_pull(skb, sizeof(code)); + /* + * The SMP context must be initialized for all other PDUs except + * pairing and security requests. If we get any other PDU when + * not initialized simply disconnect (done if this function + * returns an error). + */ + if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ && + !conn->smp_chan) { + BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code); + kfree_skb(skb); + return -ENOTSUPP; + } + switch (code) { case SMP_CMD_PAIRING_REQ: reason = smp_cmd_pairing_req(conn, skb); -- GitLab From 739230186fa9d6999f88c53f0cb6d07ed4234fb0 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Wed, 14 Nov 2012 09:42:35 +0000 Subject: [PATCH 1624/1799] efi: Make 'efi_enabled' a function to query EFI facilities commit 83e68189745ad931c2afd45d8ee3303929233e7f upstream. Originally 'efi_enabled' indicated whether a kernel was booted from EFI firmware. Over time its semantics have changed, and it now indicates whether or not we are booted on an EFI machine with bit-native firmware, e.g. 64-bit kernel with 64-bit firmware. The immediate motivation for this patch is the bug report at, https://bugs.launchpad.net/ubuntu-cdimage/+bug/1040557 which details how running a platform driver on an EFI machine that is designed to run under BIOS can cause the machine to become bricked. Also, the following report, https://bugzilla.kernel.org/show_bug.cgi?id=47121 details how running said driver can also cause Machine Check Exceptions. Drivers need a new means of detecting whether they're running on an EFI machine, as sadly the expression, if (!efi_enabled) hasn't been a sufficient condition for quite some time. Users actually want to query 'efi_enabled' for different reasons - what they really want access to is the list of available EFI facilities. For instance, the x86 reboot code needs to know whether it can invoke the ResetSystem() function provided by the EFI runtime services, while the ACPI OSL code wants to know whether the EFI config tables were mapped successfully. There are also checks in some of the platform driver code to simply see if they're running on an EFI machine (which would make it a bad idea to do BIOS-y things). This patch is a prereq for the samsung-laptop fix patch. Signed-off-by: Matt Fleming Cc: David Airlie Cc: Corentin Chary Cc: Matthew Garrett Cc: Dave Jiang Cc: Olof Johansson Cc: Peter Jones Cc: Colin Ian King Cc: Steve Langasek Cc: Tony Luck Cc: Konrad Rzeszutek Wilk Cc: Rafael J. Wysocki Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/efi.h | 1 + arch/x86/kernel/reboot.c | 2 +- arch/x86/kernel/setup.c | 28 ++++++------- arch/x86/platform/efi/efi.c | 57 +++++++++++++++----------- drivers/acpi/osl.c | 2 +- drivers/firmware/dmi_scan.c | 2 +- drivers/firmware/efivars.c | 4 +- drivers/firmware/iscsi_ibft_find.c | 2 +- drivers/gpu/drm/radeon/radeon_device.c | 3 +- drivers/platform/x86/ibm_rtl.c | 2 +- drivers/scsi/isci/init.c | 2 +- include/linux/efi.h | 24 ++++++++--- init/main.c | 4 +- 13 files changed, 79 insertions(+), 54 deletions(-) diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 029189db84de..da37433e3628 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -94,6 +94,7 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, #endif /* CONFIG_X86_32 */ extern int add_efi_memmap; +extern unsigned long x86_efi_facility; extern void efi_set_executable(efi_memory_desc_t *md, bool executable); extern int efi_memblock_x86_reserve_range(void); extern void efi_call_phys_prelog(void); diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 3034ee5afb0f..df1b604c0c1f 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -619,7 +619,7 @@ static void native_machine_emergency_restart(void) break; case BOOT_EFI: - if (efi_enabled) + if (efi_enabled(EFI_RUNTIME_SERVICES)) efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD, diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index b71e4a533ccd..537dc033868d 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -818,15 +818,15 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_EFI if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, "EL32", 4)) { - efi_enabled = 1; - efi_64bit = false; + set_bit(EFI_BOOT, &x86_efi_facility); } else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, "EL64", 4)) { - efi_enabled = 1; - efi_64bit = true; + set_bit(EFI_BOOT, &x86_efi_facility); + set_bit(EFI_64BIT, &x86_efi_facility); } - if (efi_enabled && efi_memblock_x86_reserve_range()) - efi_enabled = 0; + + if (efi_enabled(EFI_BOOT)) + efi_memblock_x86_reserve_range(); #endif x86_init.oem.arch_setup(); @@ -899,7 +899,7 @@ void __init setup_arch(char **cmdline_p) finish_e820_parsing(); - if (efi_enabled) + if (efi_enabled(EFI_BOOT)) efi_init(); dmi_scan_machine(); @@ -982,7 +982,7 @@ void __init setup_arch(char **cmdline_p) * The EFI specification says that boot service code won't be called * after ExitBootServices(). This is, in fact, a lie. */ - if (efi_enabled) + if (efi_enabled(EFI_MEMMAP)) efi_reserve_boot_services(); /* preallocate 4k for mptable mpc */ @@ -1119,7 +1119,7 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) - if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY)) + if (!efi_enabled(EFI_BOOT) || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY)) conswitchp = &vga_con; #elif defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con; @@ -1136,14 +1136,14 @@ void __init setup_arch(char **cmdline_p) arch_init_ideal_nops(); #ifdef CONFIG_EFI - /* Once setup is done above, disable efi_enabled on mismatched - * firmware/kernel archtectures since there is no support for - * runtime services. + /* Once setup is done above, unmap the EFI memory map on + * mismatched firmware/kernel archtectures since there is no + * support for runtime services. */ - if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) { + if (efi_enabled(EFI_BOOT) && + IS_ENABLED(CONFIG_X86_64) != efi_enabled(EFI_64BIT)) { pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); efi_unmap_memmap(); - efi_enabled = 0; } #endif } diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 6825327d00a7..6fcd4ad9bb62 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -50,9 +50,6 @@ #define EFI_DEBUG 1 -int efi_enabled; -EXPORT_SYMBOL(efi_enabled); - struct efi __read_mostly efi = { .mps = EFI_INVALID_TABLE_ADDR, .acpi = EFI_INVALID_TABLE_ADDR, @@ -68,19 +65,28 @@ EXPORT_SYMBOL(efi); struct efi_memory_map memmap; -bool efi_64bit; - static struct efi efi_phys __initdata; static efi_system_table_t efi_systab __initdata; static inline bool efi_is_native(void) { - return IS_ENABLED(CONFIG_X86_64) == efi_64bit; + return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT); +} + +unsigned long x86_efi_facility; + +/* + * Returns 1 if 'facility' is enabled, 0 otherwise. + */ +int efi_enabled(int facility) +{ + return test_bit(facility, &x86_efi_facility) != 0; } +EXPORT_SYMBOL(efi_enabled); static int __init setup_noefi(char *arg) { - efi_enabled = 0; + clear_bit(EFI_BOOT, &x86_efi_facility); return 0; } early_param("noefi", setup_noefi); @@ -425,6 +431,7 @@ void __init efi_reserve_boot_services(void) void __init efi_unmap_memmap(void) { + clear_bit(EFI_MEMMAP, &x86_efi_facility); if (memmap.map) { early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); memmap.map = NULL; @@ -459,7 +466,7 @@ void __init efi_free_boot_services(void) static int __init efi_systab_init(void *phys) { - if (efi_64bit) { + if (efi_enabled(EFI_64BIT)) { efi_system_table_64_t *systab64; u64 tmp = 0; @@ -551,7 +558,7 @@ static int __init efi_config_init(u64 tables, int nr_tables) void *config_tables, *tablep; int i, sz; - if (efi_64bit) + if (efi_enabled(EFI_64BIT)) sz = sizeof(efi_config_table_64_t); else sz = sizeof(efi_config_table_32_t); @@ -571,7 +578,7 @@ static int __init efi_config_init(u64 tables, int nr_tables) efi_guid_t guid; unsigned long table; - if (efi_64bit) { + if (efi_enabled(EFI_64BIT)) { u64 table64; guid = ((efi_config_table_64_t *)tablep)->guid; table64 = ((efi_config_table_64_t *)tablep)->table; @@ -683,7 +690,6 @@ void __init efi_init(void) if (boot_params.efi_info.efi_systab_hi || boot_params.efi_info.efi_memmap_hi) { pr_info("Table located above 4GB, disabling EFI.\n"); - efi_enabled = 0; return; } efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; @@ -693,10 +699,10 @@ void __init efi_init(void) ((__u64)boot_params.efi_info.efi_systab_hi<<32)); #endif - if (efi_systab_init(efi_phys.systab)) { - efi_enabled = 0; + if (efi_systab_init(efi_phys.systab)) return; - } + + set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); /* * Show what we know for posterity @@ -714,10 +720,10 @@ void __init efi_init(void) efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); - if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) { - efi_enabled = 0; + if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) return; - } + + set_bit(EFI_CONFIG_TABLES, &x86_efi_facility); /* * Note: We currently don't support runtime services on an EFI @@ -726,15 +732,17 @@ void __init efi_init(void) if (!efi_is_native()) pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); - else if (efi_runtime_init()) { - efi_enabled = 0; - return; + else { + if (efi_runtime_init()) + return; + set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility); } - if (efi_memmap_init()) { - efi_enabled = 0; + if (efi_memmap_init()) return; - } + + set_bit(EFI_MEMMAP, &x86_efi_facility); + #ifdef CONFIG_X86_32 if (efi_is_native()) { x86_platform.get_wallclock = efi_get_time; @@ -943,6 +951,9 @@ u64 efi_mem_attributes(unsigned long phys_addr) efi_memory_desc_t *md; void *p; + if (!efi_enabled(EFI_MEMMAP)) + return 0; + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { md = p; if ((md->phys_addr <= phys_addr) && diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c3881b2eb8b2..f48720cf96ff 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -250,7 +250,7 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) return acpi_rsdp; #endif - if (efi_enabled) { + if (efi_enabled(EFI_CONFIG_TABLES)) { if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) return efi.acpi20; else if (efi.acpi != EFI_INVALID_TABLE_ADDR) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index fd3ae6290d71..982f1f5f5742 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -471,7 +471,7 @@ void __init dmi_scan_machine(void) char __iomem *p, *q; int rc; - if (efi_enabled) { + if (efi_enabled(EFI_CONFIG_TABLES)) { if (efi.smbios == EFI_INVALID_TABLE_ADDR) goto error; diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index d10c9873dd9a..bfd8f4392492 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -1224,7 +1224,7 @@ efivars_init(void) printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, EFIVARS_DATE); - if (!efi_enabled) + if (!efi_enabled(EFI_RUNTIME_SERVICES)) return 0; /* For now we'll register the efi directory at /sys/firmware/efi */ @@ -1262,7 +1262,7 @@ efivars_init(void) static void __exit efivars_exit(void) { - if (efi_enabled) { + if (efi_enabled(EFI_RUNTIME_SERVICES)) { unregister_efivars(&__efivars); kobject_put(efi_kobj); } diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c index 4da4eb9ae926..2224f1dc074b 100644 --- a/drivers/firmware/iscsi_ibft_find.c +++ b/drivers/firmware/iscsi_ibft_find.c @@ -99,7 +99,7 @@ unsigned long __init find_ibft_region(unsigned long *sizep) /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will * only use ACPI for this */ - if (!efi_enabled) + if (!efi_enabled(EFI_BOOT)) find_ibft_in_mem(); if (ibft_addr) { diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index de5e0b51dc63..68c89dbfd976 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -358,7 +358,8 @@ bool radeon_card_posted(struct radeon_device *rdev) { uint32_t reg; - if (efi_enabled && rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) + if (efi_enabled(EFI_BOOT) && + rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) return false; /* first check CRTCs */ diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c index 7481146a5b47..97c2be195efc 100644 --- a/drivers/platform/x86/ibm_rtl.c +++ b/drivers/platform/x86/ibm_rtl.c @@ -244,7 +244,7 @@ static int __init ibm_rtl_init(void) { if (force) pr_warn("module loaded by force\n"); /* first ensure that we are running on IBM HW */ - else if (efi_enabled || !dmi_check_system(ibm_rtl_dmi_table)) + else if (efi_enabled(EFI_BOOT) || !dmi_check_system(ibm_rtl_dmi_table)) return -ENODEV; /* Get the address for the Extended BIOS Data Area */ diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 4c150dffb1ab..5a1bd0ca2bb9 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -470,7 +470,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic return -ENOMEM; pci_set_drvdata(pdev, pci_info); - if (efi_enabled) + if (efi_enabled(EFI_RUNTIME_SERVICES)) orom = isci_get_efi_var(pdev); if (!orom) diff --git a/include/linux/efi.h b/include/linux/efi.h index 5782114f4838..eee8b0b190ea 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -539,18 +539,30 @@ extern int __init efi_setup_pcdp_console(char *); #endif /* - * We play games with efi_enabled so that the compiler will, if possible, remove - * EFI-related code altogether. + * We play games with efi_enabled so that the compiler will, if + * possible, remove EFI-related code altogether. */ +#define EFI_BOOT 0 /* Were we booted from EFI? */ +#define EFI_SYSTEM_TABLES 1 /* Can we use EFI system tables? */ +#define EFI_CONFIG_TABLES 2 /* Can we use EFI config tables? */ +#define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ +#define EFI_MEMMAP 4 /* Can we use EFI memory map? */ +#define EFI_64BIT 5 /* Is the firmware 64-bit? */ + #ifdef CONFIG_EFI # ifdef CONFIG_X86 - extern int efi_enabled; - extern bool efi_64bit; +extern int efi_enabled(int facility); # else -# define efi_enabled 1 +static inline int efi_enabled(int facility) +{ + return 1; +} # endif #else -# define efi_enabled 0 +static inline int efi_enabled(int facility) +{ + return 0; +} #endif /* diff --git a/init/main.c b/init/main.c index c2178d267c1a..02c138465780 100644 --- a/init/main.c +++ b/init/main.c @@ -602,7 +602,7 @@ asmlinkage void __init start_kernel(void) pidmap_init(); anon_vma_init(); #ifdef CONFIG_X86 - if (efi_enabled) + if (efi_enabled(EFI_RUNTIME_SERVICES)) efi_enter_virtual_mode(); #endif thread_info_cache_init(); @@ -630,7 +630,7 @@ asmlinkage void __init start_kernel(void) acpi_early_init(); /* before LAPIC and SMP init */ sfi_init_late(); - if (efi_enabled) + if (efi_enabled(EFI_RUNTIME_SERVICES)) efi_free_boot_services(); ftrace_init(); -- GitLab From 7f8d73f9e71d58187f42d26088578be5d2d70859 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 3 Jan 2013 09:02:37 +0000 Subject: [PATCH 1625/1799] samsung-laptop: Disable on EFI hardware commit e0094244e41c4d0c7ad69920681972fc45d8ce34 upstream. It has been reported that running this driver on some Samsung laptops with EFI can cause those machines to become bricked as detailed in the following report, https://bugs.launchpad.net/ubuntu-cdimage/+bug/1040557 There have also been reports of this driver causing Machine Check Exceptions on recent EFI-enabled Samsung laptops, https://bugzilla.kernel.org/show_bug.cgi?id=47121 So disable it if booting from EFI since this driver relies on grovelling around in the BIOS memory map which isn't going to work. Signed-off-by: Matt Fleming Cc: Corentin Chary Cc: Matthew Garrett Cc: Colin Ian King Cc: Steve Langasek Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/samsung-laptop.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index 1afbe5e0a348..de9f432cf22d 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -26,6 +26,7 @@ #include #include #include +#include #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) #include #endif @@ -1527,6 +1528,9 @@ static int __init samsung_init(void) struct samsung_laptop *samsung; int ret; + if (efi_enabled(EFI_BOOT)) + return -ENODEV; + quirks = &samsung_unknown; if (!force && !dmi_check_system(samsung_dmi_table)) return -ENODEV; -- GitLab From 0ad715758022062a34bccede6200803e26480c97 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Mon, 7 Jan 2013 21:17:00 +0000 Subject: [PATCH 1626/1799] net: prevent setting ttl=0 via IP_TTL [ Upstream commit c9be4a5c49cf51cc70a993f004c5bb30067a65ce ] A regression is introduced by the following commit: commit 4d52cfbef6266092d535237ba5a4b981458ab171 Author: Eric Dumazet Date: Tue Jun 2 00:42:16 2009 -0700 net: ipv4/ip_sockglue.c cleanups Pure cleanups but it is not a pure cleanup... - if (val != -1 && (val < 1 || val>255)) + if (val != -1 && (val < 0 || val > 255)) Since there is no reason provided to allow ttl=0, change it back. Reported-by: nitin padalia Cc: nitin padalia Cc: Eric Dumazet Cc: David S. Miller Signed-off-by: Cong Wang Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ip_sockglue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 59ef40abf500..374828487003 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -589,7 +589,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, case IP_TTL: if (optlen < 1) goto e_inval; - if (val != -1 && (val < 0 || val > 255)) + if (val != -1 && (val < 1 || val > 255)) goto e_inval; inet->uc_ttl = val; break; -- GitLab From 3b69055b43c57783a8bf99a8e40f773580e451a1 Mon Sep 17 00:00:00 2001 From: Romain Kuntz Date: Wed, 9 Jan 2013 15:02:26 +0100 Subject: [PATCH 1627/1799] ipv6: fix the noflags test in addrconf_get_prefix_route [ Upstream commit 85da53bf1c336bb07ac038fb951403ab0478d2c5 ] The tests on the flags in addrconf_get_prefix_route() does no make much sense: the 'noflags' parameter contains the set of flags that must not match with the route flags, so the test must be done against 'noflags', and not against 'flags'. Signed-off-by: Romain Kuntz Acked-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/addrconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 468a5ce6e9d2..81e0ad2442c7 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1736,7 +1736,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, continue; if ((rt->rt6i_flags & flags) != flags) continue; - if ((noflags != 0) && ((rt->rt6i_flags & flags) != 0)) + if ((rt->rt6i_flags & noflags) != 0) continue; dst_hold(&rt->dst); break; -- GitLab From 6320f430b95a00ef958d7e98655823bfb3c1b918 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 16 Jan 2013 09:55:57 -0800 Subject: [PATCH 1628/1799] MAINTAINERS: Stephen Hemminger email change [ Upstream commit adbbf69d1a54abf424e91875746a610dcc80017d ] I changed my email because the vyatta.com mail server is now redirected to brocade.com; and the Brocade mail system is not friendly to Linux desktop users. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index a60009da7280..c744d9c6e28a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2627,7 +2627,7 @@ S: Maintained F: drivers/net/ethernet/i825xx/eexpress.* ETHERNET BRIDGE -M: Stephen Hemminger +M: Stephen Hemminger L: bridge@lists.linux-foundation.org L: netdev@vger.kernel.org W: http://www.linuxfoundation.org/en/Net:Bridge @@ -4312,7 +4312,7 @@ S: Maintained MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2) M: Mirko Lindner -M: Stephen Hemminger +M: Stephen Hemminger L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/marvell/sk* @@ -4563,7 +4563,7 @@ S: Supported F: drivers/infiniband/hw/nes/ NETEM NETWORK EMULATOR -M: Stephen Hemminger +M: Stephen Hemminger L: netem@lists.linux-foundation.org S: Maintained F: net/sched/sch_netem.c -- GitLab From 07da6b22a219ba7907ad41118f0e77f4b8fae9a9 Mon Sep 17 00:00:00 2001 From: Romain KUNTZ Date: Wed, 16 Jan 2013 12:47:40 +0000 Subject: [PATCH 1629/1799] ipv6: fix header length calculation in ip6_append_data() [ Upstream commit 7efdba5bd9a2f3e2059beeb45c9fa55eefe1bced ] Commit 299b0767 (ipv6: Fix IPsec slowpath fragmentation problem) has introduced a error in the header length calculation that provokes corrupted packets when non-fragmentable extensions headers (Destination Option or Routing Header Type 2) are used. rt->rt6i_nfheader_len is the length of the non-fragmentable extension header, and it should be substracted to rt->dst.header_len, and not to exthdrlen, as it was done before commit 299b0767. This patch reverts to the original and correct behavior. It has been successfully tested with and without IPsec on packets that include non-fragmentable extensions headers. Signed-off-by: Romain Kuntz Acked-by: Steffen Klassert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ip6_output.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 13e5399b1cd9..ce661baa60cb 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1287,10 +1287,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, cork->length = 0; sk->sk_sndmsg_page = NULL; sk->sk_sndmsg_off = 0; - exthdrlen = (opt ? opt->opt_flen : 0) - rt->rt6i_nfheader_len; + exthdrlen = (opt ? opt->opt_flen : 0); length += exthdrlen; transhdrlen += exthdrlen; - dst_exthdrlen = rt->dst.header_len; + dst_exthdrlen = rt->dst.header_len - rt->rt6i_nfheader_len; } else { rt = (struct rt6_info *)cork->dst; fl6 = &inet->cork.fl.u.ip6; -- GitLab From f0adabb18a751ecff5da1e03d47b13dd9628b89b Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 16 Jan 2013 13:36:37 +0000 Subject: [PATCH 1630/1799] net: calxedaxgmac: throw away overrun frames [ Upstream commit d6fb3be544b46a7611a3373fcaa62b5b0be01888 ] The xgmac driver assumes 1 frame per descriptor. If a frame larger than the descriptor's buffer size is received, the frame will spill over into the next descriptor. So check for received frames that span more than one descriptor and discard them. This prevents a crash if we receive erroneous large packets. Signed-off-by: Rob Herring Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/calxeda/xgmac.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index 11f667f6131a..4ebbe6f609d0 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c @@ -547,6 +547,10 @@ static int desc_get_rx_status(struct xgmac_priv *priv, struct xgmac_dma_desc *p) return -1; } + /* All frames should fit into a single buffer */ + if (!(status & RXDESC_FIRST_SEG) || !(status & RXDESC_LAST_SEG)) + return -1; + /* Check if packet has checksum already */ if ((status & RXDESC_FRAME_TYPE) && (status & RXDESC_EXT_STATUS) && !(ext_status & RXDESC_IP_PAYLOAD_MASK)) -- GitLab From 70f85892c8a0e0eee5f4eeb5371b72e9b46744ab Mon Sep 17 00:00:00 2001 From: Yan Burman Date: Thu, 17 Jan 2013 05:30:42 +0000 Subject: [PATCH 1631/1799] net/mlx4_en: Fix bridged vSwitch configuration for non SRIOV mode [ Upstream commit 213815a1e6ae70b9648483b110bc5081795f99e8 ] Commit 5b4c4d36860e "mlx4_en: Allow communication between functions on same host" introduced a regression under which a bridge acting as vSwitch whose uplink is an mlx4 Ethernet device become non-operative in native (non sriov) mode. This happens since broadcast ARP requests sent by VMs were loopback-ed by the HW and hence the bridge learned VM source MACs on both the VM and the uplink ports. The fix is to place the DMAC in the send WQE only under SRIOV/eSwitch configuration or when the device is in selftest. Reviewed-by: Or Gerlitz Signed-off-by: Yan Burman Signed-off-by: Amir Vadai Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/mellanox/mlx4/en_tx.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 17968244c399..efa3a13f8b1d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -683,10 +683,15 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ring->tx_csum++; } - /* Copy dst mac address to wqe */ - ethh = (struct ethhdr *)skb->data; - tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); - tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); + if (mlx4_is_mfunc(mdev->dev) || priv->validate_loopback) { + /* Copy dst mac address to wqe. This allows loopback in eSwitch, + * so that VFs and PF can communicate with each other + */ + ethh = (struct ethhdr *)skb->data; + tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); + tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); + } + /* Handle LSO (TSO) packets */ if (lso_header_size) { /* Mark opcode as LSO */ -- GitLab From 37c1a8504945755e6e0f39449023e250eb2c2618 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Thu, 17 Jan 2013 05:30:43 +0000 Subject: [PATCH 1632/1799] net/mlx4_core: Set number of msix vectors under SRIOV mode to firmware defaults [ Upstream commit ca4c7b35f75492de7fbf5ee95be07481c348caee ] The lines if (mlx4_is_mfunc(dev)) { nreq = 2; } else { which hard code the number of requested msi-x vectors under multi-function mode to two can be removed completely, since the firmware sets num_eqs and reserved_eqs appropriately Thus, the code line: nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, nreq); is by itself sufficient and correct for all cases. Currently, for mfunc mode num_eqs = 32 and reserved_eqs = 28, hence four vectors will be enabled. This triples (one vector is used for the async events and commands EQ) the horse power provided for processing of incoming packets on netdev RSS scheme, IO initiators/targets commands processing flows, etc. Reviewed-by: Jack Morgenstein Signed-off-by: Amir Vadai Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/mellanox/mlx4/main.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 8bb05b46db86..1995cb05acf2 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1526,15 +1526,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) int i; if (msi_x) { - /* In multifunction mode each function gets 2 msi-X vectors - * one for data path completions anf the other for asynch events - * or command completions */ - if (mlx4_is_mfunc(dev)) { - nreq = 2; - } else { - nreq = min_t(int, dev->caps.num_eqs - - dev->caps.reserved_eqs, nreq); - } + nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, + nreq); entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); if (!entries) -- GitLab From 3a2593d54499ec5d2ac5682503ae1973bfcd3bcb Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Mon, 21 Jan 2013 11:57:21 +0000 Subject: [PATCH 1633/1799] isdn/gigaset: fix zero size border case in debug dump [ Upstream commit d721a1752ba544df8d7d36959038b26bc92bdf80 ] If subtracting 12 from l leaves zero we'd do a zero size allocation, leading to an oops later when we try to set the NUL terminator. Reported-by: Dan Carpenter Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/gigaset/capi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 579aa021a659..be22d5ee8e0d 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -264,6 +264,8 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag, CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, CAPIMSG_CONTROL(data)); l -= 12; + if (l <= 0) + return; dbgline = kmalloc(3 * l, GFP_ATOMIC); if (!dbgline) return; -- GitLab From 30a66dd405e36be6f470f4c383c16583b44812e1 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 22 Jan 2013 06:33:05 +0000 Subject: [PATCH 1634/1799] netxen: fix off by one bug in netxen_release_tx_buffer() [ Upstream commit a05948f296ce103989b28a2606e47d2e287c3c89 ] Christoph Paasch found netxen could trigger a BUG in its dismantle phase, in netxen_release_tx_buffer(), using full size TSO packets. cmd_buf->frag_count includes the skb->data part, so the loop must start at index 1 instead of 0, or else we can make an out of bound access to cmd_buff->frag_array[MAX_SKB_FRAGS + 2] Christoph provided the fixes in netxen_map_tx_skb() function. In case of a dma mapping error, its better to clear the dma fields so that we don't try to unmap them again in netxen_release_tx_buffer() Reported-by: Christoph Paasch Signed-off-by: Eric Dumazet Tested-by: Christoph Paasch Cc: Sony Chacko Cc: Rajesh Borundia Signed-off-by: Christoph Paasch Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c | 2 +- drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index 718b27440351..83538ccddebb 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c @@ -144,7 +144,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) buffrag->length, PCI_DMA_TODEVICE); buffrag->dma = 0ULL; } - for (j = 0; j < cmd_buf->frag_count; j++) { + for (j = 1; j < cmd_buf->frag_count; j++) { buffrag++; if (buffrag->dma) { pci_unmap_page(adapter->pdev, buffrag->dma, diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 22b399a9db90..7ee9c740085e 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1956,10 +1956,12 @@ netxen_map_tx_skb(struct pci_dev *pdev, while (--i >= 0) { nf = &pbuf->frag_array[i+1]; pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); + nf->dma = 0ULL; } nf = &pbuf->frag_array[0]; pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); + nf->dma = 0ULL; out_err: return -ENOMEM; -- GitLab From 646e28ceca9036d5b2e76f4b116bba0bc60081c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 21 Jan 2013 22:30:35 +0000 Subject: [PATCH 1635/1799] r8169: remove the obsolete and incorrect AMD workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 5d0feaff230c0abfe4a112e6f09f096ed99e0b2d ] This was introduced in commit 6dccd16 "r8169: merge with version 6.001.00 of Realtek's r8169 driver". I did not find the version 6.001.00 online, but in 6.002.00 or any later r8169 from Realtek this hunk is no longer present. Also commit 05af214 "r8169: fix Ethernet Hangup for RTL8110SC rev d" claims to have fixed this issue otherwise. The magic compare mask of 0xfffe000 is dubious as it masks parts of the Reserved part, and parts of the VLAN tag. But this does not make much sense as the VLAN tag parts are perfectly valid there. In matter of fact this seems to be triggered with any VLAN tagged packet as RxVlanTag bit is matched. I would suspect 0xfffe0000 was intended to test reserved part only. Finally, this hunk is evil as it can cause more packets to be handled than what was NAPI quota causing net/core/dev.c: net_rx_action(): WARN_ON_ONCE(work > weight) to trigger, and mess up the NAPI state causing device to hang. As result, any system using VLANs and having high receive traffic (so that NAPI poll budget limits rtl_rx) would result in device hang. Signed-off-by: Timo Teräs Acked-by: Francois Romieu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/realtek/r8169.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 06ee243d41a8..df49ce26c3e2 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -5450,13 +5450,6 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget tp->rx_stats.bytes += pkt_size; u64_stats_update_end(&tp->rx_stats.syncp); } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } } count = cur_rx - tp->cur_rx; -- GitLab From e38660420e8e12d7fd6b58069d985b6298aad176 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 25 Jan 2013 07:44:41 +0000 Subject: [PATCH 1636/1799] net: loopback: fix a dst refcounting issue [ Upstream commit 794ed393b707f01858f5ebe2ae5eabaf89d00022 ] Ben Greear reported crashes in ip_rcv_finish() on a stress test involving many macvlans. We tracked the bug to a dst use after free. ip_rcv_finish() was calling dst->input() and got garbage for dst->input value. It appears the bug is in loopback driver, lacking a skb_dst_force() before calling netif_rx(). As a result, a non refcounted dst, normally protected by a RCU read_lock section, was escaping this section and could be freed before the packet being processed. [] loopback_xmit+0x64/0x83 [] dev_hard_start_xmit+0x26c/0x35e [] dev_queue_xmit+0x2c4/0x37c [] ? dev_hard_start_xmit+0x35e/0x35e [] ? eth_header+0x28/0xb6 [] neigh_resolve_output+0x176/0x1a7 [] ip_finish_output2+0x297/0x30d [] ? ip_finish_output2+0x137/0x30d [] ip_finish_output+0x63/0x68 [] ip_output+0x61/0x67 [] dst_output+0x17/0x1b [] ip_local_out+0x1e/0x23 [] ip_queue_xmit+0x315/0x353 [] ? ip_send_unicast_reply+0x2cc/0x2cc [] tcp_transmit_skb+0x7ca/0x80b [] tcp_connect+0x53c/0x587 [] ? getnstimeofday+0x44/0x7d [] ? ktime_get_real+0x11/0x3e [] tcp_v4_connect+0x3c2/0x431 [] __inet_stream_connect+0x84/0x287 [] ? inet_stream_connect+0x22/0x49 [] ? _local_bh_enable_ip+0x84/0x9f [] ? local_bh_enable+0xd/0x11 [] ? lock_sock_nested+0x6e/0x79 [] ? inet_stream_connect+0x22/0x49 [] inet_stream_connect+0x33/0x49 [] sys_connect+0x75/0x98 This bug was introduced in linux-2.6.35, in commit 7fee226ad2397b (net: add a noref bit on skb dst) skb_dst_force() is enforced in dev_queue_xmit() for devices having a qdisc. Reported-by: Ben Greear Signed-off-by: Eric Dumazet Tested-by: Ben Greear Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/loopback.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 32eb94ece6c1..a3d4707505a4 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -77,6 +77,11 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, skb_orphan(skb); + /* Before queueing this packet to netif_rx(), + * make sure dst is refcounted. + */ + skb_dst_force(skb); + skb->protocol = eth_type_trans(skb, dev); /* it's OK to use per_cpu_ptr() because BHs are off */ -- GitLab From 6c1128b87d5814de27f8ddc445783a81914b194f Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 27 Jan 2013 21:14:08 +0000 Subject: [PATCH 1637/1799] pktgen: correctly handle failures when adding a device [ Upstream commit 604dfd6efc9b79bce432f2394791708d8e8f6efc ] The return value of pktgen_add_device() is not checked, so even if we fail to add some device, for example, non-exist one, we still see "OK:...". This patch fixes it. After this patch, I got: # echo "add_device non-exist" > /proc/net/pktgen/kpktgend_0 -bash: echo: write error: No such device # cat /proc/net/pktgen/kpktgend_0 Running: Stopped: Result: ERROR: can not add device non-exist # echo "add_device eth0" > /proc/net/pktgen/kpktgend_0 # cat /proc/net/pktgen/kpktgend_0 Running: Stopped: eth0 Result: OK: add_device=eth0 (Candidate for -stable) Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/pktgen.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 8dae76f481ee..114d8a9e8570 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -1802,10 +1802,13 @@ static ssize_t pktgen_thread_write(struct file *file, return -EFAULT; i += len; mutex_lock(&pktgen_thread_lock); - pktgen_add_device(t, f); + ret = pktgen_add_device(t, f); mutex_unlock(&pktgen_thread_lock); - ret = count; - sprintf(pg_result, "OK: add_device=%s", f); + if (!ret) { + ret = count; + sprintf(pg_result, "OK: add_device=%s", f); + } else + sprintf(pg_result, "ERROR: can not add device %s", f); goto out; } -- GitLab From 909978d73590b07c3a050a569cc3bd44b1f9355c Mon Sep 17 00:00:00 2001 From: Marcelo Ricardo Leitner Date: Tue, 29 Jan 2013 22:26:08 +0000 Subject: [PATCH 1638/1799] ipv6: do not create neighbor entries for local delivery [ Upstream commit bd30e947207e2ea0ff2c08f5b4a03025ddce48d3 ] They will be created at output, if ever needed. This avoids creating empty neighbor entries when TPROXYing/Forwarding packets for addresses that are not even directly reachable. Note that IPv4 already handles it this way. No neighbor entries are created for local input. Tested by myself and customer. Signed-off-by: Jiri Pirko Signed-off-by: Marcelo Ricardo Leitner Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/route.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b84cba195509..493490f052a0 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -846,7 +846,8 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, dst_hold(&rt->dst); read_unlock_bh(&table->tb6_lock); - if (!dst_get_neighbour_noref_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) + if (!dst_get_neighbour_noref_raw(&rt->dst) && + !(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_LOCAL))) nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); else if (!(rt->dst.flags & DST_HOST)) nrt = rt6_alloc_clone(rt, &fl6->daddr); -- GitLab From d78378096e74b2fd0b42b74156ba0ae0567ea226 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 29 Jan 2013 22:58:04 -0500 Subject: [PATCH 1639/1799] via-rhine: Fix bugs in NAPI support. [ Upstream commit 559bcac35facfed49ab4f408e162971612dcfdf3 ] 1) rhine_tx() should use dev_kfree_skb() not dev_kfree_skb_irq() 2) rhine_slow_event_task's NAPI triggering logic is racey, it should just hit the interrupt mask register. This is the same as commit 7dbb491878a2c51d372a8890fa45a8ff80358af1 ("r8169: avoid NAPI scheduling delay.") made to fix the same problem in the r8169 driver. From Francois Romieu. Reported-by: Jamie Gloudon Tested-by: Jamie Gloudon Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/via/via-rhine.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index fcfa01f7ceb6..4c76db4f0589 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -1802,7 +1802,7 @@ static void rhine_tx(struct net_device *dev) rp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); } - dev_kfree_skb_irq(rp->tx_skbuff[entry]); + dev_kfree_skb(rp->tx_skbuff[entry]); rp->tx_skbuff[entry] = NULL; entry = (++rp->dirty_tx) % TX_RING_SIZE; } @@ -2011,11 +2011,7 @@ static void rhine_slow_event_task(struct work_struct *work) if (intr_status & IntrPCIErr) netif_warn(rp, hw, dev, "PCI error\n"); - napi_disable(&rp->napi); - rhine_irq_disable(rp); - /* Slow and safe. Consider __napi_schedule as a replacement ? */ - napi_enable(&rp->napi); - napi_schedule(&rp->napi); + iowrite16(RHINE_EVENT & 0xffff, rp->base + IntrEnable); out_unlock: mutex_unlock(&rp->task_lock); -- GitLab From f60f85403b3a5b566ba0eaf174930f6a626d33ad Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Fri, 1 Feb 2013 07:21:41 +0000 Subject: [PATCH 1640/1799] packet: fix leakage of tx_ring memory [ Upstream commit 9665d5d62487e8e7b1f546c00e11107155384b9a ] When releasing a packet socket, the routine packet_set_ring() is reused to free rings instead of allocating them. But when calling it for the first time, it fills req->tp_block_nr with the value of rb->pg_vec_len which in the second invocation makes it bail out since req->tp_block_nr is greater zero but req->tp_block_size is zero. This patch solves the problem by passing a zeroed auto-variable to packet_set_ring() upon each invocation from packet_release(). As far as I can tell, this issue exists even since 69e3c75 (net: TX_RING and packet mmap), i.e. the original inclusion of TX ring support into af_packet, but applies only to sockets with both RX and TX ring allocated, which is probably why this was unnoticed all the time. Signed-off-by: Phil Sutter Cc: Johann Baudy Cc: Daniel Borkmann Acked-by: Daniel Borkmann Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/packet/af_packet.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 078fdffcd556..38ca5e07d520 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2450,13 +2450,15 @@ static int packet_release(struct socket *sock) packet_flush_mclist(sk); - memset(&req_u, 0, sizeof(req_u)); - - if (po->rx_ring.pg_vec) + if (po->rx_ring.pg_vec) { + memset(&req_u, 0, sizeof(req_u)); packet_set_ring(sk, &req_u, 1, 0); + } - if (po->tx_ring.pg_vec) + if (po->tx_ring.pg_vec) { + memset(&req_u, 0, sizeof(req_u)); packet_set_ring(sk, &req_u, 1, 1); + } fanout_release(sk); -- GitLab From b4129dae20d6e106cb197008d9adf617e1affa89 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 8 Feb 2013 00:19:11 +0000 Subject: [PATCH 1641/1799] atm/iphase: rename fregt_t -> ffreg_t [ Upstream commit ab54ee80aa7585f9666ff4dd665441d7ce41f1e8 ] We have conflicting type qualifiers for "freg_t" in s390's ptrace.h and the iphase atm device driver, which causes the compile error below. Unfortunately the s390 typedef can't be renamed, since it's a user visible api, nor can I change the include order in s390 code to avoid the conflict. So simply rename the iphase typedef to a new name. Fixes this compile error: In file included from drivers/atm/iphase.c:66:0: drivers/atm/iphase.h:639:25: error: conflicting type qualifiers for 'freg_t' In file included from next/arch/s390/include/asm/ptrace.h:9:0, from next/arch/s390/include/asm/lowcore.h:12, from next/arch/s390/include/asm/thread_info.h:30, from include/linux/thread_info.h:54, from include/linux/preempt.h:9, from include/linux/spinlock.h:50, from include/linux/seqlock.h:29, from include/linux/time.h:5, from include/linux/stat.h:18, from include/linux/module.h:10, from drivers/atm/iphase.c:43: next/arch/s390/include/uapi/asm/ptrace.h:197:3: note: previous declaration of 'freg_t' was here Signed-off-by: Heiko Carstens Acked-by: chas williams - CONTRACTOR Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/atm/iphase.h | 146 +++++++++++++++++++++---------------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h index 6a0955e6d4fc..53ecac5a2161 100644 --- a/drivers/atm/iphase.h +++ b/drivers/atm/iphase.h @@ -636,82 +636,82 @@ struct rx_buf_desc { #define SEG_BASE IPHASE5575_FRAG_CONTROL_REG_BASE #define REASS_BASE IPHASE5575_REASS_CONTROL_REG_BASE -typedef volatile u_int freg_t; +typedef volatile u_int ffreg_t; typedef u_int rreg_t; typedef struct _ffredn_t { - freg_t idlehead_high; /* Idle cell header (high) */ - freg_t idlehead_low; /* Idle cell header (low) */ - freg_t maxrate; /* Maximum rate */ - freg_t stparms; /* Traffic Management Parameters */ - freg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */ - freg_t rm_type; /* */ - u_int filler5[0x17 - 0x06]; - freg_t cmd_reg; /* Command register */ - u_int filler18[0x20 - 0x18]; - freg_t cbr_base; /* CBR Pointer Base */ - freg_t vbr_base; /* VBR Pointer Base */ - freg_t abr_base; /* ABR Pointer Base */ - freg_t ubr_base; /* UBR Pointer Base */ - u_int filler24; - freg_t vbrwq_base; /* VBR Wait Queue Base */ - freg_t abrwq_base; /* ABR Wait Queue Base */ - freg_t ubrwq_base; /* UBR Wait Queue Base */ - freg_t vct_base; /* Main VC Table Base */ - freg_t vcte_base; /* Extended Main VC Table Base */ - u_int filler2a[0x2C - 0x2A]; - freg_t cbr_tab_beg; /* CBR Table Begin */ - freg_t cbr_tab_end; /* CBR Table End */ - freg_t cbr_pointer; /* CBR Pointer */ - u_int filler2f[0x30 - 0x2F]; - freg_t prq_st_adr; /* Packet Ready Queue Start Address */ - freg_t prq_ed_adr; /* Packet Ready Queue End Address */ - freg_t prq_rd_ptr; /* Packet Ready Queue read pointer */ - freg_t prq_wr_ptr; /* Packet Ready Queue write pointer */ - freg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/ - freg_t tcq_ed_adr; /* Transmit Complete Queue End Address */ - freg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */ - freg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/ - u_int filler38[0x40 - 0x38]; - freg_t queue_base; /* Base address for PRQ and TCQ */ - freg_t desc_base; /* Base address of descriptor table */ - u_int filler42[0x45 - 0x42]; - freg_t mode_reg_0; /* Mode register 0 */ - freg_t mode_reg_1; /* Mode register 1 */ - freg_t intr_status_reg;/* Interrupt Status register */ - freg_t mask_reg; /* Mask Register */ - freg_t cell_ctr_high1; /* Total cell transfer count (high) */ - freg_t cell_ctr_lo1; /* Total cell transfer count (low) */ - freg_t state_reg; /* Status register */ - u_int filler4c[0x58 - 0x4c]; - freg_t curr_desc_num; /* Contains the current descriptor num */ - freg_t next_desc; /* Next descriptor */ - freg_t next_vc; /* Next VC */ - u_int filler5b[0x5d - 0x5b]; - freg_t present_slot_cnt;/* Present slot count */ - u_int filler5e[0x6a - 0x5e]; - freg_t new_desc_num; /* New descriptor number */ - freg_t new_vc; /* New VC */ - freg_t sched_tbl_ptr; /* Schedule table pointer */ - freg_t vbrwq_wptr; /* VBR wait queue write pointer */ - freg_t vbrwq_rptr; /* VBR wait queue read pointer */ - freg_t abrwq_wptr; /* ABR wait queue write pointer */ - freg_t abrwq_rptr; /* ABR wait queue read pointer */ - freg_t ubrwq_wptr; /* UBR wait queue write pointer */ - freg_t ubrwq_rptr; /* UBR wait queue read pointer */ - freg_t cbr_vc; /* CBR VC */ - freg_t vbr_sb_vc; /* VBR SB VC */ - freg_t abr_sb_vc; /* ABR SB VC */ - freg_t ubr_sb_vc; /* UBR SB VC */ - freg_t vbr_next_link; /* VBR next link */ - freg_t abr_next_link; /* ABR next link */ - freg_t ubr_next_link; /* UBR next link */ - u_int filler7a[0x7c-0x7a]; - freg_t out_rate_head; /* Out of rate head */ - u_int filler7d[0xca-0x7d]; /* pad out to full address space */ - freg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */ - freg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */ - u_int fillercc[0x100-0xcc]; /* pad out to full address space */ + ffreg_t idlehead_high; /* Idle cell header (high) */ + ffreg_t idlehead_low; /* Idle cell header (low) */ + ffreg_t maxrate; /* Maximum rate */ + ffreg_t stparms; /* Traffic Management Parameters */ + ffreg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */ + ffreg_t rm_type; /* */ + u_int filler5[0x17 - 0x06]; + ffreg_t cmd_reg; /* Command register */ + u_int filler18[0x20 - 0x18]; + ffreg_t cbr_base; /* CBR Pointer Base */ + ffreg_t vbr_base; /* VBR Pointer Base */ + ffreg_t abr_base; /* ABR Pointer Base */ + ffreg_t ubr_base; /* UBR Pointer Base */ + u_int filler24; + ffreg_t vbrwq_base; /* VBR Wait Queue Base */ + ffreg_t abrwq_base; /* ABR Wait Queue Base */ + ffreg_t ubrwq_base; /* UBR Wait Queue Base */ + ffreg_t vct_base; /* Main VC Table Base */ + ffreg_t vcte_base; /* Extended Main VC Table Base */ + u_int filler2a[0x2C - 0x2A]; + ffreg_t cbr_tab_beg; /* CBR Table Begin */ + ffreg_t cbr_tab_end; /* CBR Table End */ + ffreg_t cbr_pointer; /* CBR Pointer */ + u_int filler2f[0x30 - 0x2F]; + ffreg_t prq_st_adr; /* Packet Ready Queue Start Address */ + ffreg_t prq_ed_adr; /* Packet Ready Queue End Address */ + ffreg_t prq_rd_ptr; /* Packet Ready Queue read pointer */ + ffreg_t prq_wr_ptr; /* Packet Ready Queue write pointer */ + ffreg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/ + ffreg_t tcq_ed_adr; /* Transmit Complete Queue End Address */ + ffreg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */ + ffreg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/ + u_int filler38[0x40 - 0x38]; + ffreg_t queue_base; /* Base address for PRQ and TCQ */ + ffreg_t desc_base; /* Base address of descriptor table */ + u_int filler42[0x45 - 0x42]; + ffreg_t mode_reg_0; /* Mode register 0 */ + ffreg_t mode_reg_1; /* Mode register 1 */ + ffreg_t intr_status_reg;/* Interrupt Status register */ + ffreg_t mask_reg; /* Mask Register */ + ffreg_t cell_ctr_high1; /* Total cell transfer count (high) */ + ffreg_t cell_ctr_lo1; /* Total cell transfer count (low) */ + ffreg_t state_reg; /* Status register */ + u_int filler4c[0x58 - 0x4c]; + ffreg_t curr_desc_num; /* Contains the current descriptor num */ + ffreg_t next_desc; /* Next descriptor */ + ffreg_t next_vc; /* Next VC */ + u_int filler5b[0x5d - 0x5b]; + ffreg_t present_slot_cnt;/* Present slot count */ + u_int filler5e[0x6a - 0x5e]; + ffreg_t new_desc_num; /* New descriptor number */ + ffreg_t new_vc; /* New VC */ + ffreg_t sched_tbl_ptr; /* Schedule table pointer */ + ffreg_t vbrwq_wptr; /* VBR wait queue write pointer */ + ffreg_t vbrwq_rptr; /* VBR wait queue read pointer */ + ffreg_t abrwq_wptr; /* ABR wait queue write pointer */ + ffreg_t abrwq_rptr; /* ABR wait queue read pointer */ + ffreg_t ubrwq_wptr; /* UBR wait queue write pointer */ + ffreg_t ubrwq_rptr; /* UBR wait queue read pointer */ + ffreg_t cbr_vc; /* CBR VC */ + ffreg_t vbr_sb_vc; /* VBR SB VC */ + ffreg_t abr_sb_vc; /* ABR SB VC */ + ffreg_t ubr_sb_vc; /* UBR SB VC */ + ffreg_t vbr_next_link; /* VBR next link */ + ffreg_t abr_next_link; /* ABR next link */ + ffreg_t ubr_next_link; /* UBR next link */ + u_int filler7a[0x7c-0x7a]; + ffreg_t out_rate_head; /* Out of rate head */ + u_int filler7d[0xca-0x7d]; /* pad out to full address space */ + ffreg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */ + ffreg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */ + u_int fillercc[0x100-0xcc]; /* pad out to full address space */ } ffredn_t; typedef struct _rfredn_t { -- GitLab From 4c921d0ed5d49a93613530f4dd405fc2db3ccb84 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 17 Jan 2013 11:15:08 +0000 Subject: [PATCH 1642/1799] sctp: refactor sctp_outq_teardown to insure proper re-initalization [ Upstream commit 2f94aabd9f6c925d77aecb3ff020f1cc12ed8f86 ] Jamie Parsons reported a problem recently, in which the re-initalization of an association (The duplicate init case), resulted in a loss of receive window space. He tracked down the root cause to sctp_outq_teardown, which discarded all the data on an outq during a re-initalization of the corresponding association, but never reset the outq->outstanding_data field to zero. I wrote, and he tested this fix, which does a proper full re-initalization of the outq, fixing this problem, and hopefully future proofing us from simmilar issues down the road. Signed-off-by: Neil Horman Reported-by: Jamie Parsons Tested-by: Jamie Parsons CC: Jamie Parsons CC: Vlad Yasevich CC: "David S. Miller" CC: netdev@vger.kernel.org Acked-by: Vlad Yasevich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/outqueue.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index cfeb1d4a1ee6..96eb168a1f47 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -223,7 +223,7 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q) /* Free the outqueue structure and any related pending chunks. */ -void sctp_outq_teardown(struct sctp_outq *q) +static void __sctp_outq_teardown(struct sctp_outq *q) { struct sctp_transport *transport; struct list_head *lchunk, *temp; @@ -276,8 +276,6 @@ void sctp_outq_teardown(struct sctp_outq *q) sctp_chunk_free(chunk); } - q->error = 0; - /* Throw away any leftover control chunks. */ list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) { list_del_init(&chunk->list); @@ -285,11 +283,17 @@ void sctp_outq_teardown(struct sctp_outq *q) } } +void sctp_outq_teardown(struct sctp_outq *q) +{ + __sctp_outq_teardown(q); + sctp_outq_init(q->asoc, q); +} + /* Free the outqueue structure and any related pending chunks. */ void sctp_outq_free(struct sctp_outq *q) { /* Throw away leftover chunks. */ - sctp_outq_teardown(q); + __sctp_outq_teardown(q); /* If we were kmalloc()'d, free the memory. */ if (q->malloced) -- GitLab From 8a501d87edf7190e8fe1741d9312dfcb6361c538 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 8 Feb 2013 03:04:34 +0000 Subject: [PATCH 1643/1799] net: sctp: sctp_setsockopt_auth_key: use kzfree instead of kfree [ Upstream commit 6ba542a291a5e558603ac51cda9bded347ce7627 ] In sctp_setsockopt_auth_key, we create a temporary copy of the user passed shared auth key for the endpoint or association and after internal setup, we free it right away. Since it's sensitive data, we should zero out the key before returning the memory back to the allocator. Thus, use kzfree instead of kfree, just as we do in sctp_auth_key_put(). Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 74053554a859..9fd05edef190 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3375,7 +3375,7 @@ static int sctp_setsockopt_auth_key(struct sock *sk, ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey); out: - kfree(authkey); + kzfree(authkey); return ret; } -- GitLab From d6f5498856f31246818bbe4ebfa710ce92730a37 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 8 Feb 2013 03:04:35 +0000 Subject: [PATCH 1644/1799] net: sctp: sctp_endpoint_free: zero out secret key data [ Upstream commit b5c37fe6e24eec194bb29d22fdd55d73bcc709bf ] On sctp_endpoint_destroy, previously used sensitive keying material should be zeroed out before the memory is returned, as we already do with e.g. auth keys when released. Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sctp/endpointola.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 68a385d7c3bd..58cd035dcd20 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -248,6 +248,8 @@ void sctp_endpoint_free(struct sctp_endpoint *ep) /* Final destructor for endpoint. */ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) { + int i; + SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return); /* Free up the HMAC transform. */ @@ -270,6 +272,9 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) sctp_inq_free(&ep->base.inqueue); sctp_bind_addr_free(&ep->base.bind_addr); + for (i = 0; i < SCTP_HOW_MANY_SECRETS; ++i) + memset(&ep->secret_key[i], 0, SCTP_SECRET_SIZE); + /* Remove and free the port */ if (sctp_sk(ep->base.sk)->bind_hash) sctp_put_port(ep->base.sk); -- GitLab From be7254fc6c92c016a6768cc30596198c61043ff5 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 6 Feb 2013 23:41:35 +0000 Subject: [PATCH 1645/1799] xen/netback: shutdown the ring if it contains garbage. [ Upstream commit 48856286b64e4b66ec62b94e504d0b29c1ade664 ] A buggy or malicious frontend should not be able to confuse netback. If we spot anything which is not as it should be then shutdown the device and don't try to continue with the ring in a potentially hostile state. Well behaved and non-hostile frontends will not be penalised. As well as making the existing checks for such errors fatal also add a new check that ensures that there isn't an insane number of requests on the ring (i.e. more than would fit in the ring). If the ring contains garbage then previously is was possible to loop over this insane number, getting an error each time and therefore not generating any more pending requests and therefore not exiting the loop in xen_netbk_tx_build_gops for an externded period. Also turn various netdev_dbg calls which no precipitate a fatal error into netdev_err, they are rate limited because the device is shutdown afterwards. This fixes at least one known DoS/softlockup of the backend domain. Signed-off-by: Ian Campbell Reviewed-by: Konrad Rzeszutek Wilk Acked-by: Jan Beulich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/xen-netback/common.h | 3 ++ drivers/net/xen-netback/interface.c | 23 ++++++----- drivers/net/xen-netback/netback.c | 62 +++++++++++++++++++++-------- 3 files changed, 62 insertions(+), 26 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 94b79c3338c4..9d7f1723dd8f 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -151,6 +151,9 @@ void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb); /* Notify xenvif that ring now has space to send an skb to the frontend */ void xenvif_notify_tx_completion(struct xenvif *vif); +/* Prevent the device from generating any further traffic. */ +void xenvif_carrier_off(struct xenvif *vif); + /* Returns number of ring slots required to send an skb to the frontend */ unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index b7d41f8c338a..b8c5193bd420 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -343,17 +343,22 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, return err; } -void xenvif_disconnect(struct xenvif *vif) +void xenvif_carrier_off(struct xenvif *vif) { struct net_device *dev = vif->dev; - if (netif_carrier_ok(dev)) { - rtnl_lock(); - netif_carrier_off(dev); /* discard queued packets */ - if (netif_running(dev)) - xenvif_down(vif); - rtnl_unlock(); - xenvif_put(vif); - } + + rtnl_lock(); + netif_carrier_off(dev); /* discard queued packets */ + if (netif_running(dev)) + xenvif_down(vif); + rtnl_unlock(); + xenvif_put(vif); +} + +void xenvif_disconnect(struct xenvif *vif) +{ + if (netif_carrier_ok(vif->dev)) + xenvif_carrier_off(vif); atomic_dec(&vif->refcnt); wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 2596401308a8..770c7e1beba9 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -860,6 +860,13 @@ static void netbk_tx_err(struct xenvif *vif, xenvif_put(vif); } +static void netbk_fatal_tx_err(struct xenvif *vif) +{ + netdev_err(vif->dev, "fatal error; disabling device\n"); + xenvif_carrier_off(vif); + xenvif_put(vif); +} + static int netbk_count_requests(struct xenvif *vif, struct xen_netif_tx_request *first, struct xen_netif_tx_request *txp, @@ -873,19 +880,22 @@ static int netbk_count_requests(struct xenvif *vif, do { if (frags >= work_to_do) { - netdev_dbg(vif->dev, "Need more frags\n"); + netdev_err(vif->dev, "Need more frags\n"); + netbk_fatal_tx_err(vif); return -frags; } if (unlikely(frags >= MAX_SKB_FRAGS)) { - netdev_dbg(vif->dev, "Too many frags\n"); + netdev_err(vif->dev, "Too many frags\n"); + netbk_fatal_tx_err(vif); return -frags; } memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags), sizeof(*txp)); if (txp->size > first->size) { - netdev_dbg(vif->dev, "Frags galore\n"); + netdev_err(vif->dev, "Frag is bigger than frame.\n"); + netbk_fatal_tx_err(vif); return -frags; } @@ -893,8 +903,9 @@ static int netbk_count_requests(struct xenvif *vif, frags++; if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { - netdev_dbg(vif->dev, "txp->offset: %x, size: %u\n", + netdev_err(vif->dev, "txp->offset: %x, size: %u\n", txp->offset, txp->size); + netbk_fatal_tx_err(vif); return -frags; } } while ((txp++)->flags & XEN_NETTXF_more_data); @@ -1067,7 +1078,8 @@ static int xen_netbk_get_extras(struct xenvif *vif, do { if (unlikely(work_to_do-- <= 0)) { - netdev_dbg(vif->dev, "Missing extra info\n"); + netdev_err(vif->dev, "Missing extra info\n"); + netbk_fatal_tx_err(vif); return -EBADR; } @@ -1076,8 +1088,9 @@ static int xen_netbk_get_extras(struct xenvif *vif, if (unlikely(!extra.type || extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { vif->tx.req_cons = ++cons; - netdev_dbg(vif->dev, + netdev_err(vif->dev, "Invalid extra type: %d\n", extra.type); + netbk_fatal_tx_err(vif); return -EINVAL; } @@ -1093,13 +1106,15 @@ static int netbk_set_skb_gso(struct xenvif *vif, struct xen_netif_extra_info *gso) { if (!gso->u.gso.size) { - netdev_dbg(vif->dev, "GSO size must not be zero.\n"); + netdev_err(vif->dev, "GSO size must not be zero.\n"); + netbk_fatal_tx_err(vif); return -EINVAL; } /* Currently only TCPv4 S.O. is supported. */ if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { - netdev_dbg(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); + netdev_err(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); + netbk_fatal_tx_err(vif); return -EINVAL; } @@ -1236,9 +1251,25 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) /* Get a netif from the list with work to do. */ vif = poll_net_schedule_list(netbk); + /* This can sometimes happen because the test of + * list_empty(net_schedule_list) at the top of the + * loop is unlocked. Just go back and have another + * look. + */ if (!vif) continue; + if (vif->tx.sring->req_prod - vif->tx.req_cons > + XEN_NETIF_TX_RING_SIZE) { + netdev_err(vif->dev, + "Impossible number of requests. " + "req_prod %d, req_cons %d, size %ld\n", + vif->tx.sring->req_prod, vif->tx.req_cons, + XEN_NETIF_TX_RING_SIZE); + netbk_fatal_tx_err(vif); + continue; + } + RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do); if (!work_to_do) { xenvif_put(vif); @@ -1266,17 +1297,14 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) work_to_do = xen_netbk_get_extras(vif, extras, work_to_do); idx = vif->tx.req_cons; - if (unlikely(work_to_do < 0)) { - netbk_tx_err(vif, &txreq, idx); + if (unlikely(work_to_do < 0)) continue; - } } ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do); - if (unlikely(ret < 0)) { - netbk_tx_err(vif, &txreq, idx - ret); + if (unlikely(ret < 0)) continue; - } + idx += ret; if (unlikely(txreq.size < ETH_HLEN)) { @@ -1288,11 +1316,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) /* No crossing a page as the payload mustn't fragment. */ if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { - netdev_dbg(vif->dev, + netdev_err(vif->dev, "txreq.offset: %x, size: %u, end: %lu\n", txreq.offset, txreq.size, (txreq.offset&~PAGE_MASK) + txreq.size); - netbk_tx_err(vif, &txreq, idx); + netbk_fatal_tx_err(vif); continue; } @@ -1320,8 +1348,8 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; if (netbk_set_skb_gso(vif, skb, gso)) { + /* Failure in netbk_set_skb_gso is fatal. */ kfree_skb(skb); - netbk_tx_err(vif, &txreq, idx); continue; } } -- GitLab From 33eb2607ebfcb68bc9ae8ab029f916f1f4ee5097 Mon Sep 17 00:00:00 2001 From: Matthew Daley Date: Wed, 6 Feb 2013 23:41:36 +0000 Subject: [PATCH 1646/1799] xen/netback: don't leak pages on failure in xen_netbk_tx_check_gop. [ Upstream commit 7d5145d8eb2b9791533ffe4dc003b129b9696c48 ] Signed-off-by: Matthew Daley Reviewed-by: Konrad Rzeszutek Wilk Acked-by: Ian Campbell Acked-by: Jan Beulich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/xen-netback/netback.c | 38 +++++++++++-------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 770c7e1beba9..c71a73198b0f 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -146,7 +146,8 @@ void xen_netbk_remove_xenvif(struct xenvif *vif) atomic_dec(&netbk->netfront_count); } -static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx); +static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, + u8 status); static void make_tx_response(struct xenvif *vif, struct xen_netif_tx_request *txp, s8 st); @@ -979,30 +980,20 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, { struct gnttab_copy *gop = *gopp; u16 pending_idx = *((u16 *)skb->data); - struct pending_tx_info *pending_tx_info = netbk->pending_tx_info; - struct xenvif *vif = pending_tx_info[pending_idx].vif; - struct xen_netif_tx_request *txp; struct skb_shared_info *shinfo = skb_shinfo(skb); int nr_frags = shinfo->nr_frags; int i, err, start; /* Check status of header. */ err = gop->status; - if (unlikely(err)) { - pending_ring_idx_t index; - index = pending_index(netbk->pending_prod++); - txp = &pending_tx_info[pending_idx].req; - make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); - netbk->pending_ring[index] = pending_idx; - xenvif_put(vif); - } + if (unlikely(err)) + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); /* Skip first skb fragment if it is on same page as header fragment. */ start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx); for (i = start; i < nr_frags; i++) { int j, newerr; - pending_ring_idx_t index; pending_idx = frag_get_pending_idx(&shinfo->frags[i]); @@ -1011,16 +1002,12 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, if (likely(!newerr)) { /* Had a previous error? Invalidate this fragment. */ if (unlikely(err)) - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); continue; } /* Error on this fragment: respond to client with an error. */ - txp = &netbk->pending_tx_info[pending_idx].req; - make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); - index = pending_index(netbk->pending_prod++); - netbk->pending_ring[index] = pending_idx; - xenvif_put(vif); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); /* Not the first error? Preceding frags already invalidated. */ if (err) @@ -1028,10 +1015,10 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, /* First error: invalidate header and preceding fragments. */ pending_idx = *((u16 *)skb->data); - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); for (j = start; j < i; j++) { pending_idx = frag_get_pending_idx(&shinfo->frags[j]); - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); } /* Remember the error: invalidate all subsequent fragments. */ @@ -1065,7 +1052,7 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb) /* Take an extra reference to offset xen_netbk_idx_release */ get_page(netbk->mmap_pages[pending_idx]); - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); } } @@ -1448,7 +1435,7 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk) txp->size -= data_len; } else { /* Schedule a response immediately. */ - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); } if (txp->flags & XEN_NETTXF_csum_blank) @@ -1503,7 +1490,8 @@ static void xen_netbk_tx_action(struct xen_netbk *netbk) } -static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) +static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, + u8 status) { struct xenvif *vif; struct pending_tx_info *pending_tx_info; @@ -1517,7 +1505,7 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) vif = pending_tx_info->vif; - make_tx_response(vif, &pending_tx_info->req, XEN_NETIF_RSP_OKAY); + make_tx_response(vif, &pending_tx_info->req, status); index = pending_index(netbk->pending_prod++); netbk->pending_ring[index] = pending_idx; -- GitLab From 90ffc8f3315b0d296fea07fbc6fef87155f81f45 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 6 Feb 2013 23:41:37 +0000 Subject: [PATCH 1647/1799] xen/netback: free already allocated memory on failure in xen_netbk_get_requests [ Upstream commit 4cc7c1cb7b11b6f3515bd9075527576a1eecc4aa ] Signed-off-by: Ian Campbell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/xen-netback/netback.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index c71a73198b0f..4c41f5ea4004 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -950,7 +950,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, pending_idx = netbk->pending_ring[index]; page = xen_netbk_alloc_page(netbk, skb, pending_idx); if (!page) - return NULL; + goto err; gop->source.u.ref = txp->gref; gop->source.domid = vif->domid; @@ -972,6 +972,17 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, } return gop; +err: + /* Unwind, freeing all pages and sending error responses. */ + while (i-- > start) { + xen_netbk_idx_release(netbk, frag_get_pending_idx(&frags[i]), + XEN_NETIF_RSP_ERROR); + } + /* The head too, if necessary. */ + if (start) + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); + + return NULL; } static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, -- GitLab From 42671f1e6fd8922b071bd3fd3e0cfad7226c654d Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 6 Feb 2013 23:41:38 +0000 Subject: [PATCH 1648/1799] netback: correct netbk_tx_err to handle wrap around. [ Upstream commit b9149729ebdcfce63f853aa54a404c6a8f6ebbf3 ] Signed-off-by: Ian Campbell Acked-by: Jan Beulich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/xen-netback/netback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 4c41f5ea4004..e2793d06e5d1 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -852,7 +852,7 @@ static void netbk_tx_err(struct xenvif *vif, do { make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); - if (cons >= end) + if (cons == end) break; txp = RING_GET_REQUEST(&vif->tx, cons++); } while (1); -- GitLab From 2813296332187d222b96363fe29f10929f7a5228 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 3 Feb 2013 09:13:05 +0000 Subject: [PATCH 1649/1799] tcp: frto should not set snd_cwnd to 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 2e5f421211ff76c17130b4597bc06df4eeead24f ] Commit 9dc274151a548 (tcp: fix ABC in tcp_slow_start()) uncovered a bug in FRTO code : tcp_process_frto() is setting snd_cwnd to 0 if the number of in flight packets is 0. As Neal pointed out, if no packet is in flight we lost our chance to disambiguate whether a loss timeout was spurious. We should assume it was a proper loss. Reported-by: Pasi Kärkkäinen Signed-off-by: Neal Cardwell Signed-off-by: Eric Dumazet Cc: Ilpo Järvinen Cc: Yuchung Cheng Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_input.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0e0b6d0e9a61..d8c308f74d58 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3619,7 +3619,8 @@ static int tcp_process_frto(struct sock *sk, int flag) ((tp->frto_counter >= 2) && (flag & FLAG_RETRANS_DATA_ACKED))) tp->undo_marker = 0; - if (!before(tp->snd_una, tp->frto_highmark)) { + if (!before(tp->snd_una, tp->frto_highmark) || + !tcp_packets_in_flight(tp)) { tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), flag); return 1; } -- GitLab From f641de91169472dc398fbd971cef380ad8d0f787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Mon, 4 Feb 2013 02:14:25 +0000 Subject: [PATCH 1650/1799] tcp: fix for zero packets_in_flight was too broad MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 6731d2095bd4aef18027c72ef845ab1087c3ba63 ] There are transients during normal FRTO procedure during which the packets_in_flight can go to zero between write_queue state updates and firing the resulting segments out. As FRTO processing occurs during that window the check must be more precise to not match "spuriously" :-). More specificly, e.g., when packets_in_flight is zero but FLAG_DATA_ACKED is true the problematic branch that set cwnd into zero would not be taken and new segments might be sent out later. Signed-off-by: Ilpo Järvinen Tested-by: Eric Dumazet Acked-by: Neal Cardwell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_input.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index d8c308f74d58..57b20b9dc114 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3619,8 +3619,7 @@ static int tcp_process_frto(struct sock *sk, int flag) ((tp->frto_counter >= 2) && (flag & FLAG_RETRANS_DATA_ACKED))) tp->undo_marker = 0; - if (!before(tp->snd_una, tp->frto_highmark) || - !tcp_packets_in_flight(tp)) { + if (!before(tp->snd_una, tp->frto_highmark)) { tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), flag); return 1; } @@ -3640,6 +3639,11 @@ static int tcp_process_frto(struct sock *sk, int flag) } } else { if (!(flag & FLAG_DATA_ACKED) && (tp->frto_counter == 1)) { + if (!tcp_packets_in_flight(tp)) { + tcp_enter_frto_loss(sk, 2, flag); + return true; + } + /* Prevent sending of new data. */ tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)); -- GitLab From 94fab0a18e9cbec420c58c7b12b93acf1663c3fd Mon Sep 17 00:00:00 2001 From: Sarveshwar Bandi Date: Wed, 10 Oct 2012 01:15:01 +0000 Subject: [PATCH 1651/1799] bridge: Pull ip header into skb->data before looking into ip header. [ Upstream commit 6caab7b0544e83e6c160b5e80f5a4a7dd69545c7 ] If lower layer driver leaves the ip header in the skb fragment, it needs to be first pulled into skb->data before inspecting ip header length or ip version number. Signed-off-by: Sarveshwar Bandi Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bridge/br_netfilter.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index d7f49b63ab0f..e54ef82fdad7 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -254,6 +254,9 @@ static int br_parse_ip_options(struct sk_buff *skb) struct net_device *dev = skb->dev; u32 len; + if (!pskb_may_pull(skb, sizeof(struct iphdr))) + goto inhdr_error; + iph = ip_hdr(skb); opt = &(IPCB(skb)->opt); -- GitLab From a10a3daa591e6ea2619da1e0418af2a30aa77ac5 Mon Sep 17 00:00:00 2001 From: Nithin Nayak Sujir Date: Mon, 14 Jan 2013 17:10:59 +0000 Subject: [PATCH 1652/1799] tg3: Avoid null pointer dereference in tg3_interrupt in netconsole mode [ Upstream commit 9c13cb8bb477a83b9a3c9e5a5478a4e21294a760 ] When netconsole is enabled, logging messages generated during tg3_open can result in a null pointer dereference for the uninitialized tg3 status block. Use the irq_sync flag to disable polling in the early stages. irq_sync is cleared when the driver is enabling interrupts after all initialization is completed. Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/broadcom/tg3.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 689d2a1935bd..42e621a2d24e 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -6574,6 +6574,9 @@ static void tg3_poll_controller(struct net_device *dev) int i; struct tg3 *tp = netdev_priv(dev); + if (tg3_irq_sync(tp)) + return; + for (i = 0; i < tp->irq_cnt; i++) tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]); } @@ -15529,6 +15532,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->pm_cap = pm_cap; tp->rx_mode = TG3_DEF_RX_MODE; tp->tx_mode = TG3_DEF_TX_MODE; + tp->irq_sync = 1; if (tg3_debug > 0) tp->msg_enable = tg3_debug; -- GitLab From eac7b44eb80d3e1fa3310ad2dc57e10c2fc970fd Mon Sep 17 00:00:00 2001 From: Nithin Nayak Sujir Date: Mon, 14 Jan 2013 17:11:00 +0000 Subject: [PATCH 1653/1799] tg3: Fix crc errors on jumbo frame receive [ Upstream commit daf3ec688e057f6060fb9bb0819feac7a8bbf45c ] TG3_PHY_AUXCTL_SMDSP_ENABLE/DISABLE macros do a blind write to the phy auxiliary control register and overwrite the EXT_PKT_LEN (bit 14) resulting in intermittent crc errors on jumbo frames with some link partners. Change the code to do a read/modify/write. Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/broadcom/tg3.c | 58 +++++++++++++++++------------ 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 42e621a2d24e..e143d8c0be5b 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -1136,14 +1136,26 @@ static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set) return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg); } -#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \ - tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ - MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \ - MII_TG3_AUXCTL_ACTL_TX_6DB) +static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable) +{ + u32 val; + int err; + + err = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val); -#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \ - tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ - MII_TG3_AUXCTL_ACTL_TX_6DB); + if (err) + return err; + if (enable) + + val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA; + else + val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA; + + err = tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, + val | MII_TG3_AUXCTL_ACTL_TX_6DB); + + return err; +} static int tg3_bmcr_reset(struct tg3 *tp) { @@ -2076,7 +2088,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) otp = tp->phy_otp; - if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) + if (tg3_phy_toggle_auxctl_smdsp(tp, true)) return; phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); @@ -2101,7 +2113,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT); tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) @@ -2137,9 +2149,9 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) if (!tp->setlpicnt) { if (current_link_up == 1 && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } val = tr32(TG3_CPMU_EEE_MODE); @@ -2155,11 +2167,11 @@ static void tg3_phy_eee_enable(struct tg3 *tp) (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || tg3_flag(tp, 57765_CLASS)) && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { val = MII_TG3_DSP_TAP26_ALNOKO | MII_TG3_DSP_TAP26_RMRXSTO; tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } val = tr32(TG3_CPMU_EEE_MODE); @@ -2303,7 +2315,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_CTRL1000, CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER); - err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + err = tg3_phy_toggle_auxctl_smdsp(tp, true); if (err) return err; @@ -2324,7 +2336,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); tg3_writephy(tp, MII_CTRL1000, phy9_orig); @@ -2413,10 +2425,10 @@ static int tg3_phy_reset(struct tg3 *tp) out: if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, 0x201f, 0x2aaa); tg3_phydsp_write(tp, 0x000a, 0x0323); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) { @@ -2425,14 +2437,14 @@ static int tg3_phy_reset(struct tg3 *tp) } if (tp->phy_flags & TG3_PHYFLG_BER_BUG) { - if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, 0x000a, 0x310b); tg3_phydsp_write(tp, 0x201f, 0x9506); tg3_phydsp_write(tp, 0x401f, 0x14e2); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) { - if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) { tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); @@ -2441,7 +2453,7 @@ static int tg3_phy_reset(struct tg3 *tp) } else tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } } @@ -3858,7 +3870,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) tw32(TG3_CPMU_EEE_MODE, tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); - err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + err = tg3_phy_toggle_auxctl_smdsp(tp, true); if (!err) { u32 err2; @@ -3891,7 +3903,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) MII_TG3_DSP_CH34TP2_HIBW01); } - err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + err2 = tg3_phy_toggle_auxctl_smdsp(tp, false); if (!err) err = err2; } -- GitLab From 495f02922e05a6858005dc6b9e07eeed026cf9a0 Mon Sep 17 00:00:00 2001 From: Somnath Kotur Date: Tue, 26 Jun 2012 22:32:10 +0000 Subject: [PATCH 1654/1799] be2net: Fix to trim skb for padded vlan packets to workaround an ASIC Bug commit 93040ae5cc8dcc893eca4a4366dc8415af278edf upstream. Fixed spelling error in a comment as pointed out by DaveM. Also refactored existing code a bit to provide placeholders for another ASIC Bug workaround that will be checked-in soon after this. Signed-off-by: Somnath Kotur Signed-off-by: David S. Miller Cc: Jacek Luczak Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/emulex/benet/be.h | 5 ++ drivers/net/ethernet/emulex/benet/be_main.c | 56 +++++++++++++++------ 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 9576ac002c23..dcb02c219ddf 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -536,6 +536,11 @@ static inline void be_check_sriov_fn_type(struct be_adapter *adapter) adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; } +static inline bool is_ipv4_pkt(struct sk_buff *skb) +{ + return skb->protocol == ntohs(ETH_P_IP) && ip_hdr(skb)->version == 4; +} + static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac) { u32 addr; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 1bbf6b3eca9c..ef1f9400b967 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -571,6 +571,11 @@ static inline u16 be_get_tx_vlan_tag(struct be_adapter *adapter, return vlan_tag; } +static int be_vlan_tag_chk(struct be_adapter *adapter, struct sk_buff *skb) +{ + return vlan_tx_tag_present(skb) || adapter->pvid; +} + static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, struct sk_buff *skb, u32 wrb_cnt, u32 len) { @@ -698,33 +703,56 @@ static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq, return 0; } +static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter, + struct sk_buff *skb) +{ + u16 vlan_tag = 0; + + skb = skb_share_check(skb, GFP_ATOMIC); + if (unlikely(!skb)) + return skb; + + if (vlan_tx_tag_present(skb)) { + vlan_tag = be_get_tx_vlan_tag(adapter, skb); + __vlan_put_tag(skb, vlan_tag); + skb->vlan_tci = 0; + } + + return skb; +} + static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)]; struct be_queue_info *txq = &txo->q; + struct iphdr *ip = NULL; u32 wrb_cnt = 0, copied = 0; - u32 start = txq->head; + u32 start = txq->head, eth_hdr_len; bool dummy_wrb, stopped = false; - /* For vlan tagged pkts, BE - * 1) calculates checksum even when CSO is not requested - * 2) calculates checksum wrongly for padded pkt less than - * 60 bytes long. - * As a workaround disable TX vlan offloading in such cases. + eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ? + VLAN_ETH_HLEN : ETH_HLEN; + + /* HW has a bug which considers padding bytes as legal + * and modifies the IPv4 hdr's 'tot_len' field */ - if (unlikely(vlan_tx_tag_present(skb) && - (skb->ip_summed != CHECKSUM_PARTIAL || skb->len <= 60))) { - skb = skb_share_check(skb, GFP_ATOMIC); - if (unlikely(!skb)) - goto tx_drop; + if (skb->len <= 60 && be_vlan_tag_chk(adapter, skb) && + is_ipv4_pkt(skb)) { + ip = (struct iphdr *)ip_hdr(skb); + pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len)); + } - skb = __vlan_put_tag(skb, be_get_tx_vlan_tag(adapter, skb)); + /* HW has a bug wherein it will calculate CSUM for VLAN + * pkts even though it is disabled. + * Manually insert VLAN in pkt. + */ + if (skb->ip_summed != CHECKSUM_PARTIAL && + be_vlan_tag_chk(adapter, skb)) { + skb = be_insert_vlan_in_pkt(adapter, skb); if (unlikely(!skb)) goto tx_drop; - - skb->vlan_tci = 0; } wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb); -- GitLab From 72a274602416d7c5dc04641832af8d0710a548dd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 14 Feb 2013 10:52:45 -0800 Subject: [PATCH 1655/1799] Linux 3.4.31 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4941fd9876e6..930db766a3fd 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 30 +SUBLEVEL = 31 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 18051b4221f2d593d8f98913cf7095dfec269706 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 29 Jan 2013 09:16:28 +0100 Subject: [PATCH 1656/1799] s390/timer: avoid overflow when programming clock comparator commit d911e03d097bdc01363df5d81c43f69432eb785c upstream. Since ed4f209 "s390/time: fix sched_clock() overflow" a new helper function is used to avoid overflows when converting TOD format values to nanosecond values. The kvm interrupt code formerly however only worked by accident because of an overflow. It tried to program a timer that would expire in more than ~29 years. Because of the old TOD-to-nanoseconds overflow bug the real expiry value however was much smaller, but now it isn't anymore. This however triggers yet another bug in the function that programs the clock comparator s390_next_ktime(): if the absolute "expires" value is after 2042 this will result in an overflow and the programmed value is lower than the current TOD value which immediatly triggers a clock comparator (= timer) interrupt. Since the timer isn't expired it will be programmed immediately again and so on... the result is a dead system. To fix this simply program the maximum possible value if an overflow is detected. Reported-by: Christian Borntraeger Tested-by: Christian Borntraeger Signed-off-by: Heiko Carstens Signed-off-by: Greg Kroah-Hartman --- arch/s390/kernel/time.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index c5531dbc8b2f..747ab28d0e64 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -121,6 +121,9 @@ static int s390_next_ktime(ktime_t expires, nsecs = ktime_to_ns(ktime_add(timespec_to_ktime(ts), expires)); do_div(nsecs, 125); S390_lowcore.clock_comparator = sched_clock_base_cc + (nsecs << 9); + /* Program the maximum value if we have an overflow (== year 2042) */ + if (unlikely(S390_lowcore.clock_comparator < sched_clock_base_cc)) + S390_lowcore.clock_comparator = -1ULL; set_clock_comparator(S390_lowcore.clock_comparator); return 0; } -- GitLab From e2ef6aad8a81c730bba92b2a44d758cabd7d9053 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 7 Feb 2013 09:44:13 -0800 Subject: [PATCH 1657/1799] x86: Do not leak kernel page mapping locations commit e575a86fdc50d013bf3ad3aa81d9100e8e6cc60d upstream. Without this patch, it is trivial to determine kernel page mappings by examining the error code reported to dmesg[1]. Instead, declare the entire kernel memory space as a violation of a present page. Additionally, since show_unhandled_signals is enabled by default, switch branch hinting to the more realistic expectation, and unobfuscate the setting of the PF_PROT bit to improve readability. [1] http://vulnfactory.org/blog/2013/02/06/a-linux-memory-trick/ Reported-by: Dan Rosenberg Suggested-by: Brad Spengler Signed-off-by: Kees Cook Acked-by: H. Peter Anvin Cc: Paul E. McKenney Cc: Frederic Weisbecker Cc: Eric W. Biederman Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20130207174413.GA12485@www.outflux.net Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/fault.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 3ecfd1aaf214..e922e01868fb 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -747,13 +747,15 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, return; } #endif + /* Kernel addresses are always protection faults: */ + if (address >= TASK_SIZE) + error_code |= PF_PROT; - if (unlikely(show_unhandled_signals)) + if (likely(show_unhandled_signals)) show_signal_msg(regs, error_code, address, tsk); - /* Kernel addresses are always protection faults: */ tsk->thread.cr2 = address; - tsk->thread.error_code = error_code | (address >= TASK_SIZE); + tsk->thread.error_code = error_code; tsk->thread.trap_nr = X86_TRAP_PF; force_sig_info_fault(SIGSEGV, si_code, address, tsk, 0); -- GitLab From 65f55391cf03b2e4bcfec63b08b8db032b4d6f3a Mon Sep 17 00:00:00 2001 From: Stoney Wang Date: Thu, 7 Feb 2013 10:53:02 -0800 Subject: [PATCH 1658/1799] x86/apic: Work around boot failure on HP ProLiant DL980 G7 Server systems commit cb214ede7657db458fd0b2a25ea0b28dbf900ebc upstream. When a HP ProLiant DL980 G7 Server boots a regular kernel, there will be intermittent lost interrupts which could result in a hang or (in extreme cases) data loss. The reason is that this system only supports x2apic physical mode, while the kernel boots with a logical-cluster default setting. This bug can be worked around by specifying the "x2apic_phys" or "nox2apic" boot option, but we want to handle this system without requiring manual workarounds. The BIOS sets ACPI_FADT_APIC_PHYSICAL in FADT table. As all apicids are smaller than 255, BIOS need to pass the control to the OS with xapic mode, according to x2apic-spec, chapter 2.9. Current code handle x2apic when BIOS pass with xapic mode enabled: When user specifies x2apic_phys, or FADT indicates PHYSICAL: 1. During madt oem check, apic driver is set with xapic logical or xapic phys driver at first. 2. enable_IR_x2apic() will enable x2apic_mode. 3. if user specifies x2apic_phys on the boot line, x2apic_phys_probe() will install the correct x2apic phys driver and use x2apic phys mode. Otherwise it will skip the driver will let x2apic_cluster_probe to take over to install x2apic cluster driver (wrong one) even though FADT indicates PHYSICAL, because x2apic_phys_probe does not check FADT PHYSICAL. Add checking x2apic_fadt_phys in x2apic_phys_probe() to fix the problem. Signed-off-by: Stoney Wang [ updated the changelog and simplified the code ] Signed-off-by: Yinghai Lu Link: http://lkml.kernel.org/r/1360263182-16226-1-git-send-email-yinghai@kernel.org Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/x2apic_phys.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index 991e315f4227..db31a2cfc9a9 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -20,18 +20,19 @@ static int set_x2apic_phys_mode(char *arg) } early_param("x2apic_phys", set_x2apic_phys_mode); -static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static bool x2apic_fadt_phys(void) { - if (x2apic_phys) - return x2apic_enabled(); - else if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) && - (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL) && - x2apic_enabled()) { + if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) && + (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) { printk(KERN_DEBUG "System requires x2apic physical mode\n"); - return 1; + return true; } - else - return 0; + return false; +} + +static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + return x2apic_enabled() && (x2apic_phys || x2apic_fadt_phys()); } static void @@ -114,7 +115,7 @@ static void init_x2apic_ldr(void) static int x2apic_phys_probe(void) { - if (x2apic_mode && x2apic_phys) + if (x2apic_mode && (x2apic_phys || x2apic_fadt_phys())) return 1; return apic == &apic_x2apic_phys; -- GitLab From 44f80d63b26469593b633bc40049538683e70311 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 11 Feb 2013 14:52:36 +0000 Subject: [PATCH 1659/1799] x86/mm: Check if PUD is large when validating a kernel address commit 0ee364eb316348ddf3e0dfcd986f5f13f528f821 upstream. A user reported the following oops when a backup process reads /proc/kcore: BUG: unable to handle kernel paging request at ffffbb00ff33b000 IP: [] kern_addr_valid+0xbe/0x110 [...] Call Trace: [] read_kcore+0x17a/0x370 [] proc_reg_read+0x77/0xc0 [] vfs_read+0xc7/0x130 [] sys_read+0x53/0xa0 [] system_call_fastpath+0x16/0x1b Investigation determined that the bug triggered when reading system RAM at the 4G mark. On this system, that was the first address using 1G pages for the virt->phys direct mapping so the PUD is pointing to a physical address, not a PMD page. The problem is that the page table walker in kern_addr_valid() is not checking pud_large() and treats the physical address as if it was a PMD. If it happens to look like pmd_none then it'll silently fail, probably returning zeros instead of real data. If the data happens to look like a present PMD though, it will be walked resulting in the oops above. This patch adds the necessary pud_large() check. Unfortunately the problem was not readily reproducible and now they are running the backup program without accessing /proc/kcore so the patch has not been validated but I think it makes sense. Signed-off-by: Mel Gorman Reviewed-by: Rik van Riel Reviewed-by: Michal Hocko Acked-by: Johannes Weiner Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20130211145236.GX21389@suse.de Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/pgtable.h | 5 +++++ arch/x86/mm/init_64.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index c3520d76820e..3f3dd526b3b8 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -142,6 +142,11 @@ static inline unsigned long pmd_pfn(pmd_t pmd) return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT; } +static inline unsigned long pud_pfn(pud_t pud) +{ + return (pud_val(pud) & PTE_PFN_MASK) >> PAGE_SHIFT; +} + #define pte_page(pte) pfn_to_page(pte_pfn(pte)) static inline int pmd_large(pmd_t pte) diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index fc18be0f6f29..faf7a6830c0b 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -821,6 +821,9 @@ int kern_addr_valid(unsigned long addr) if (pud_none(*pud)) return 0; + if (pud_large(*pud)) + return pfn_valid(pud_pfn(*pud)); + pmd = pmd_offset(pud, addr); if (pmd_none(*pmd)) return 0; -- GitLab From dc66ff14a9489f8c239ecc43a20ca946cce8d217 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 24 Jan 2013 13:11:10 +0000 Subject: [PATCH 1660/1799] x86/xen: don't assume %ds is usable in xen_iret for 32-bit PVOPS. commit 13d2b4d11d69a92574a55bfd985cfb0ca77aebdc upstream. This fixes CVE-2013-0228 / XSA-42 Drew Jones while working on CVE-2013-0190 found that that unprivileged guest user in 32bit PV guest can use to crash the > guest with the panic like this: ------------- general protection fault: 0000 [#1] SMP last sysfs file: /sys/devices/vbd-51712/block/xvda/dev Modules linked in: sunrpc ipt_REJECT nf_conntrack_ipv4 nf_defrag_ipv4 iptable_filter ip_tables ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack ip6table_filter ip6_tables ipv6 xen_netfront ext4 mbcache jbd2 xen_blkfront dm_mirror dm_region_hash dm_log dm_mod [last unloaded: scsi_wait_scan] Pid: 1250, comm: r Not tainted 2.6.32-356.el6.i686 #1 EIP: 0061:[] EFLAGS: 00010086 CPU: 0 EIP is at xen_iret+0x12/0x2b EAX: eb8d0000 EBX: 00000001 ECX: 08049860 EDX: 00000010 ESI: 00000000 EDI: 003d0f00 EBP: b77f8388 ESP: eb8d1fe0 DS: 0000 ES: 007b FS: 0000 GS: 00e0 SS: 0069 Process r (pid: 1250, ti=eb8d0000 task=c2953550 task.ti=eb8d0000) Stack: 00000000 0027f416 00000073 00000206 b77f8364 0000007b 00000000 00000000 Call Trace: Code: c3 8b 44 24 18 81 4c 24 38 00 02 00 00 8d 64 24 30 e9 03 00 00 00 8d 76 00 f7 44 24 08 00 00 02 80 75 33 50 b8 00 e0 ff ff 21 e0 <8b> 40 10 8b 04 85 a0 f6 ab c0 8b 80 0c b0 b3 c0 f6 44 24 0d 02 EIP: [] xen_iret+0x12/0x2b SS:ESP 0069:eb8d1fe0 general protection fault: 0000 [#2] ---[ end trace ab0d29a492dcd330 ]--- Kernel panic - not syncing: Fatal exception Pid: 1250, comm: r Tainted: G D --------------- 2.6.32-356.el6.i686 #1 Call Trace: [] ? panic+0x6e/0x122 [] ? oops_end+0xbc/0xd0 [] ? do_general_protection+0x0/0x210 [] ? error_code+0x73/ ------------- Petr says: " I've analysed the bug and I think that xen_iret() cannot cope with mangled DS, in this case zeroed out (null selector/descriptor) by either xen_failsafe_callback() or RESTORE_REGS because the corresponding LDT entry was invalidated by the reproducer. " Jan took a look at the preliminary patch and came up a fix that solves this problem: "This code gets called after all registers other than those handled by IRET got already restored, hence a null selector in %ds or a non-null one that got loaded from a code or read-only data descriptor would cause a kernel mode fault (with the potential of crashing the kernel as a whole, if panic_on_oops is set)." The way to fix this is to realize that the we can only relay on the registers that IRET restores. The two that are guaranteed are the %cs and %ss as they are always fixed GDT selectors. Also they are inaccessible from user mode - so they cannot be altered. This is the approach taken in this patch. Another alternative option suggested by Jan would be to relay on the subtle realization that using the %ebp or %esp relative references uses the %ss segment. In which case we could switch from using %eax to %ebp and would not need the %ss over-rides. That would also require one extra instruction to compensate for the one place where the register is used as scaled index. However Andrew pointed out that is too subtle and if further work was to be done in this code-path it could escape folks attention and lead to accidents. Reviewed-by: Petr Matousek Reported-by: Petr Matousek Reviewed-by: Andrew Cooper Signed-off-by: Jan Beulich Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/xen-asm_32.S | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S index b040b0e518ca..7328f71651e1 100644 --- a/arch/x86/xen/xen-asm_32.S +++ b/arch/x86/xen/xen-asm_32.S @@ -88,11 +88,11 @@ ENTRY(xen_iret) */ #ifdef CONFIG_SMP GET_THREAD_INFO(%eax) - movl TI_cpu(%eax), %eax - movl __per_cpu_offset(,%eax,4), %eax - mov xen_vcpu(%eax), %eax + movl %ss:TI_cpu(%eax), %eax + movl %ss:__per_cpu_offset(,%eax,4), %eax + mov %ss:xen_vcpu(%eax), %eax #else - movl xen_vcpu, %eax + movl %ss:xen_vcpu, %eax #endif /* check IF state we're restoring */ @@ -105,11 +105,11 @@ ENTRY(xen_iret) * resuming the code, so we don't have to be worried about * being preempted to another CPU. */ - setz XEN_vcpu_info_mask(%eax) + setz %ss:XEN_vcpu_info_mask(%eax) xen_iret_start_crit: /* check for unmasked and pending */ - cmpw $0x0001, XEN_vcpu_info_pending(%eax) + cmpw $0x0001, %ss:XEN_vcpu_info_pending(%eax) /* * If there's something pending, mask events again so we can @@ -117,7 +117,7 @@ xen_iret_start_crit: * touch XEN_vcpu_info_mask. */ jne 1f - movb $1, XEN_vcpu_info_mask(%eax) + movb $1, %ss:XEN_vcpu_info_mask(%eax) 1: popl %eax -- GitLab From 15295d7dc33491a0a015a0f48d04bbaa696b802d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 11 Feb 2013 20:49:49 +0100 Subject: [PATCH 1661/1799] PCI/PM: Clean up PME state when removing a device commit 249bfb83cf8ba658955f0245ac3981d941f746ee upstream. Devices are added to pci_pme_list when drivers use pci_enable_wake() or pci_wake_from_d3(), but they aren't removed from the list unless the driver explicitly disables wakeup. Many drivers never disable wakeup, so their devices remain on the list even after they are removed, e.g., via hotplug. A subsequent PME poll will oops when it tries to touch the device. This patch disables PME# on a device before removing it, which removes the device from pci_pme_list. This is safe even if the device never had PME# enabled. This oops can be triggered by unplugging a Thunderbolt ethernet adapter on a Macbook Pro, as reported by Daniel below. [bhelgaas: changelog] Reference: http://lkml.kernel.org/r/CAMVG2svG21yiM1wkH4_2pen2n+cr2-Zv7TbH3Gj+8MwevZjDbw@mail.gmail.com Reported-and-tested-by: Daniel J Blueman Signed-off-by: Rafael J. Wysocki Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/pci/remove.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index fd77e2bde2e8..eae55c7b6470 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -19,6 +19,8 @@ static void pci_free_resources(struct pci_dev *dev) static void pci_stop_dev(struct pci_dev *dev) { + pci_pme_active(dev, false); + if (dev->is_added) { pci_proc_detach_device(dev); pci_remove_sysfs_dev_files(dev); -- GitLab From 266c43c175a51002b04c18a453a39708d1775ced Mon Sep 17 00:00:00 2001 From: Satoru Takeuchi Date: Thu, 14 Feb 2013 09:12:52 +0900 Subject: [PATCH 1662/1799] efi: Clear EFI_RUNTIME_SERVICES rather than EFI_BOOT by "noefi" boot parameter commit 1de63d60cd5b0d33a812efa455d5933bf1564a51 upstream. There was a serious problem in samsung-laptop that its platform driver is designed to run under BIOS and running under EFI can cause the machine to become bricked or can cause Machine Check Exceptions. Discussion about this problem: https://bugs.launchpad.net/ubuntu-cdimage/+bug/1040557 https://bugzilla.kernel.org/show_bug.cgi?id=47121 The patches to fix this problem: efi: Make 'efi_enabled' a function to query EFI facilities 83e68189745ad931c2afd45d8ee3303929233e7f samsung-laptop: Disable on EFI hardware e0094244e41c4d0c7ad69920681972fc45d8ce34 Unfortunately this problem comes back again if users specify "noefi" option. This parameter clears EFI_BOOT and that driver continues to run even if running under EFI. Refer to the document, this parameter should clear EFI_RUNTIME_SERVICES instead. Documentation/kernel-parameters.txt: =============================================================================== ... noefi [X86] Disable EFI runtime services support. ... =============================================================================== Documentation/x86/x86_64/uefi.txt: =============================================================================== ... - If some or all EFI runtime services don't work, you can try following kernel command line parameters to turn off some or all EFI runtime services. noefi turn off all EFI runtime services ... =============================================================================== Signed-off-by: Satoru Takeuchi Link: http://lkml.kernel.org/r/511C2C04.2070108@jp.fujitsu.com Cc: Matt Fleming Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/platform/efi/efi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 6fcd4ad9bb62..3705bb049e54 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -86,7 +86,7 @@ EXPORT_SYMBOL(efi_enabled); static int __init setup_noefi(char *arg) { - clear_bit(EFI_BOOT, &x86_efi_facility); + clear_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility); return 0; } early_param("noefi", setup_noefi); -- GitLab From 248924caf7d1e452e3cad8433ae7b4942654ea8b Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 8 Aug 2012 05:23:22 +0000 Subject: [PATCH 1663/1799] igb: Remove artificial restriction on RQDPC stat reading commit ae1c07a6b7ced6c0c94c99e3b53f4e7856fa8bff upstream. For some reason the reading of the RQDPC register was being artificially limited to 4K. Instead of limiting the value we should read the value and add the full amount. Otherwise this can lead to a misleading number of dropped packets when the actual value is in fact much higher. Signed-off-by: Alexander Duyck Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Cc: Vinson Lee Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/intel/igb/igb_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 6b4f0148ee6c..1fb180dbc7b1 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -4649,11 +4649,13 @@ void igb_update_stats(struct igb_adapter *adapter, bytes = 0; packets = 0; for (i = 0; i < adapter->num_rx_queues; i++) { - u32 rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0x0FFF; + u32 rqdpc = rd32(E1000_RQDPC(i)); struct igb_ring *ring = adapter->rx_ring[i]; - ring->rx_stats.drops += rqdpc_tmp; - net_stats->rx_fifo_errors += rqdpc_tmp; + if (rqdpc) { + ring->rx_stats.drops += rqdpc; + net_stats->rx_fifo_errors += rqdpc; + } do { start = u64_stats_fetch_begin_bh(&ring->rx_syncp); -- GitLab From 9ad3bfb9e26197c378d6c239180ed7bcf7c29fd8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 17 Feb 2013 10:49:37 -0800 Subject: [PATCH 1664/1799] Linux 3.4.32 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 930db766a3fd..ece89702c5cc 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 31 +SUBLEVEL = 32 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From ce0030c00f95cf9110d9cdcd41e901e1fb814417 Mon Sep 17 00:00:00 2001 From: Alexandre SIMON Date: Fri, 1 Feb 2013 15:31:54 +0100 Subject: [PATCH 1665/1799] printk: fix buffer overflow when calling log_prefix function from call_console_drivers This patch corrects a buffer overflow in kernels from 3.0 to 3.4 when calling log_prefix() function from call_console_drivers(). This bug existed in previous releases but has been revealed with commit 162a7e7500f9664636e649ba59defe541b7c2c60 (2.6.39 => 3.0) that made changes about how to allocate memory for early printk buffer (use of memblock_alloc). It disappears with commit 7ff9554bb578ba02166071d2d487b7fc7d860d62 (3.4 => 3.5) that does a refactoring of printk buffer management. In log_prefix(), the access to "p[0]", "p[1]", "p[2]" or "simple_strtoul(&p[1], &endp, 10)" may cause a buffer overflow as this function is called from call_console_drivers by passing "&LOG_BUF(cur_index)" where the index must be masked to do not exceed the buffer's boundary. The trick is to prepare in call_console_drivers() a buffer with the necessary data (PRI field of syslog message) to be safely evaluated in log_prefix(). This patch can be applied to stable kernel branches 3.0.y, 3.2.y and 3.4.y. Without this patch, one can freeze a server running this loop from shell : $ export DUMMY=`cat /dev/urandom | tr -dc '12345AZERTYUIOPQSDFGHJKLMWXCVBNazertyuiopqsdfghjklmwxcvbn' | head -c255` $ while true do ; echo $DUMMY > /dev/kmsg ; done The "server freeze" depends on where memblock_alloc does allocate printk buffer : if the buffer overflow is inside another kernel allocation the problem may not be revealed, else the server may hangs up. Signed-off-by: Alexandre SIMON Signed-off-by: Greg Kroah-Hartman --- include/linux/syslog.h | 6 ++++++ kernel/printk.c | 13 ++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/linux/syslog.h b/include/linux/syslog.h index 38911391a139..ce4c66556059 100644 --- a/include/linux/syslog.h +++ b/include/linux/syslog.h @@ -47,6 +47,12 @@ #define SYSLOG_FROM_CALL 0 #define SYSLOG_FROM_FILE 1 +/* + * Syslog priority (PRI) maximum length in char : '<[0-9]{1,3}>' + * See RFC5424 for details +*/ +#define SYSLOG_PRI_MAX_LENGTH 5 + int do_syslog(int type, char __user *buf, int count, bool from_file); #endif /* _LINUX_SYSLOG_H */ diff --git a/kernel/printk.c b/kernel/printk.c index b663c2c95d39..e95c66223d33 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -638,8 +638,19 @@ static void call_console_drivers(unsigned start, unsigned end) start_print = start; while (cur_index != end) { if (msg_level < 0 && ((end - cur_index) > 2)) { + /* + * prepare buf_prefix, as a contiguous array, + * to be processed by log_prefix function + */ + char buf_prefix[SYSLOG_PRI_MAX_LENGTH+1]; + unsigned i; + for (i = 0; i < ((end - cur_index)) && (i < SYSLOG_PRI_MAX_LENGTH); i++) { + buf_prefix[i] = LOG_BUF(cur_index + i); + } + buf_prefix[i] = '\0'; /* force '\0' as last string character */ + /* strip log prefix */ - cur_index += log_prefix(&LOG_BUF(cur_index), &msg_level, NULL); + cur_index += log_prefix((const char *)&buf_prefix, &msg_level, NULL); start_print = cur_index; } while (cur_index != end) { -- GitLab From 1c3000a67a350c7ac31897cf22ec8e4ddd47d3aa Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 21 Feb 2013 10:05:05 -0800 Subject: [PATCH 1666/1799] 3.4.33 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ece89702c5cc..a26d19a31d97 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 32 +SUBLEVEL = 33 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From 025cee7f8fef02af09b03c8e1cd9843cb32adf9b Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 30 Jan 2013 16:56:16 -0800 Subject: [PATCH 1667/1799] x86-32, mm: Rip out x86_32 NUMA remapping code commit f03574f2d5b2d6229dcdf2d322848065f72953c7 upstream. This code was an optimization for 32-bit NUMA systems. It has probably been the cause of a number of subtle bugs over the years, although the conditions to excite them would have been hard to trigger. Essentially, we remap part of the kernel linear mapping area, and then sometimes part of that area gets freed back in to the bootmem allocator. If those pages get used by kernel data structures (say mem_map[] or a dentry), there's no big deal. But, if anyone ever tried to use the linear mapping for these pages _and_ cared about their physical address, bad things happen. For instance, say you passed __GFP_ZERO to the page allocator and then happened to get handed one of these pages, it zero the remapped page, but it would make a pte to the _old_ page. There are probably a hundred other ways that it could screw with things. We don't need to hang on to performance optimizations for these old boxes any more. All my 32-bit NUMA systems are long dead and buried, and I probably had access to more than most people. This code is causing real things to break today: https://lkml.org/lkml/2013/1/9/376 I looked in to actually fixing this, but it requires surgery to way too much brittle code, as well as stuff like per_cpu_ptr_to_phys(). [ hpa: Cc: this for -stable, since it is a memory corruption issue. However, an alternative is to simply mark NUMA as depends BROKEN rather than EXPERIMENTAL in the X86_32 subclause... ] Link: http://lkml.kernel.org/r/20130131005616.1C79F411@kernel.stglabs.ibm.com Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/Kconfig | 4 - arch/x86/mm/numa.c | 3 - arch/x86/mm/numa_32.c | 161 ------------------------------------ arch/x86/mm/numa_internal.h | 6 -- 4 files changed, 174 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c9866b0b77d8..b1478f407238 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1243,10 +1243,6 @@ config HAVE_ARCH_BOOTMEM def_bool y depends on X86_32 && NUMA -config HAVE_ARCH_ALLOC_REMAP - def_bool y - depends on X86_32 && NUMA - config ARCH_HAVE_MEMORY_PRESENT def_bool y depends on X86_32 && DISCONTIGMEM diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index 19d3fa08b119..dae8397e3615 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -205,9 +205,6 @@ static void __init setup_node_data(int nid, u64 start, u64 end) if (end && (end - start) < NODE_MIN_SIZE) return; - /* initialize remap allocator before aligning to ZONE_ALIGN */ - init_alloc_remap(nid, start, end); - start = roundup(start, ZONE_ALIGN); printk(KERN_INFO "Initmem setup node %d %016Lx-%016Lx\n", diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c index 534255a36b6b..73a6d7395bd3 100644 --- a/arch/x86/mm/numa_32.c +++ b/arch/x86/mm/numa_32.c @@ -73,167 +73,6 @@ unsigned long node_memmap_size_bytes(int nid, unsigned long start_pfn, extern unsigned long highend_pfn, highstart_pfn; -#define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE) - -static void *node_remap_start_vaddr[MAX_NUMNODES]; -void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags); - -/* - * Remap memory allocator - */ -static unsigned long node_remap_start_pfn[MAX_NUMNODES]; -static void *node_remap_end_vaddr[MAX_NUMNODES]; -static void *node_remap_alloc_vaddr[MAX_NUMNODES]; - -/** - * alloc_remap - Allocate remapped memory - * @nid: NUMA node to allocate memory from - * @size: The size of allocation - * - * Allocate @size bytes from the remap area of NUMA node @nid. The - * size of the remap area is predetermined by init_alloc_remap() and - * only the callers considered there should call this function. For - * more info, please read the comment on top of init_alloc_remap(). - * - * The caller must be ready to handle allocation failure from this - * function and fall back to regular memory allocator in such cases. - * - * CONTEXT: - * Single CPU early boot context. - * - * RETURNS: - * Pointer to the allocated memory on success, %NULL on failure. - */ -void *alloc_remap(int nid, unsigned long size) -{ - void *allocation = node_remap_alloc_vaddr[nid]; - - size = ALIGN(size, L1_CACHE_BYTES); - - if (!allocation || (allocation + size) > node_remap_end_vaddr[nid]) - return NULL; - - node_remap_alloc_vaddr[nid] += size; - memset(allocation, 0, size); - - return allocation; -} - -#ifdef CONFIG_HIBERNATION -/** - * resume_map_numa_kva - add KVA mapping to the temporary page tables created - * during resume from hibernation - * @pgd_base - temporary resume page directory - */ -void resume_map_numa_kva(pgd_t *pgd_base) -{ - int node; - - for_each_online_node(node) { - unsigned long start_va, start_pfn, nr_pages, pfn; - - start_va = (unsigned long)node_remap_start_vaddr[node]; - start_pfn = node_remap_start_pfn[node]; - nr_pages = (node_remap_end_vaddr[node] - - node_remap_start_vaddr[node]) >> PAGE_SHIFT; - - printk(KERN_DEBUG "%s: node %d\n", __func__, node); - - for (pfn = 0; pfn < nr_pages; pfn += PTRS_PER_PTE) { - unsigned long vaddr = start_va + (pfn << PAGE_SHIFT); - pgd_t *pgd = pgd_base + pgd_index(vaddr); - pud_t *pud = pud_offset(pgd, vaddr); - pmd_t *pmd = pmd_offset(pud, vaddr); - - set_pmd(pmd, pfn_pmd(start_pfn + pfn, - PAGE_KERNEL_LARGE_EXEC)); - - printk(KERN_DEBUG "%s: %08lx -> pfn %08lx\n", - __func__, vaddr, start_pfn + pfn); - } - } -} -#endif - -/** - * init_alloc_remap - Initialize remap allocator for a NUMA node - * @nid: NUMA node to initizlie remap allocator for - * - * NUMA nodes may end up without any lowmem. As allocating pgdat and - * memmap on a different node with lowmem is inefficient, a special - * remap allocator is implemented which can be used by alloc_remap(). - * - * For each node, the amount of memory which will be necessary for - * pgdat and memmap is calculated and two memory areas of the size are - * allocated - one in the node and the other in lowmem; then, the area - * in the node is remapped to the lowmem area. - * - * As pgdat and memmap must be allocated in lowmem anyway, this - * doesn't waste lowmem address space; however, the actual lowmem - * which gets remapped over is wasted. The amount shouldn't be - * problematic on machines this feature will be used. - * - * Initialization failure isn't fatal. alloc_remap() is used - * opportunistically and the callers will fall back to other memory - * allocation mechanisms on failure. - */ -void __init init_alloc_remap(int nid, u64 start, u64 end) -{ - unsigned long start_pfn = start >> PAGE_SHIFT; - unsigned long end_pfn = end >> PAGE_SHIFT; - unsigned long size, pfn; - u64 node_pa, remap_pa; - void *remap_va; - - /* - * The acpi/srat node info can show hot-add memroy zones where - * memory could be added but not currently present. - */ - printk(KERN_DEBUG "node %d pfn: [%lx - %lx]\n", - nid, start_pfn, end_pfn); - - /* calculate the necessary space aligned to large page size */ - size = node_memmap_size_bytes(nid, start_pfn, end_pfn); - size += ALIGN(sizeof(pg_data_t), PAGE_SIZE); - size = ALIGN(size, LARGE_PAGE_BYTES); - - /* allocate node memory and the lowmem remap area */ - node_pa = memblock_find_in_range(start, end, size, LARGE_PAGE_BYTES); - if (!node_pa) { - pr_warning("remap_alloc: failed to allocate %lu bytes for node %d\n", - size, nid); - return; - } - memblock_reserve(node_pa, size); - - remap_pa = memblock_find_in_range(min_low_pfn << PAGE_SHIFT, - max_low_pfn << PAGE_SHIFT, - size, LARGE_PAGE_BYTES); - if (!remap_pa) { - pr_warning("remap_alloc: failed to allocate %lu bytes remap area for node %d\n", - size, nid); - memblock_free(node_pa, size); - return; - } - memblock_reserve(remap_pa, size); - remap_va = phys_to_virt(remap_pa); - - /* perform actual remap */ - for (pfn = 0; pfn < size >> PAGE_SHIFT; pfn += PTRS_PER_PTE) - set_pmd_pfn((unsigned long)remap_va + (pfn << PAGE_SHIFT), - (node_pa >> PAGE_SHIFT) + pfn, - PAGE_KERNEL_LARGE); - - /* initialize remap allocator parameters */ - node_remap_start_pfn[nid] = node_pa >> PAGE_SHIFT; - node_remap_start_vaddr[nid] = remap_va; - node_remap_end_vaddr[nid] = remap_va + size; - node_remap_alloc_vaddr[nid] = remap_va; - - printk(KERN_DEBUG "remap_alloc: node %d [%08llx-%08llx) -> [%p-%p)\n", - nid, node_pa, node_pa + size, remap_va, remap_va + size); -} - void __init initmem_init(void) { x86_numa_init(); diff --git a/arch/x86/mm/numa_internal.h b/arch/x86/mm/numa_internal.h index 7178c3afe05e..ad86ec91e640 100644 --- a/arch/x86/mm/numa_internal.h +++ b/arch/x86/mm/numa_internal.h @@ -21,12 +21,6 @@ void __init numa_reset_distance(void); void __init x86_numa_init(void); -#ifdef CONFIG_X86_64 -static inline void init_alloc_remap(int nid, u64 start, u64 end) { } -#else -void __init init_alloc_remap(int nid, u64 start, u64 end); -#endif - #ifdef CONFIG_NUMA_EMU void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt); -- GitLab From 99867c9603b88d11ef8c7223b978d389fcb8e4c6 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 31 Jan 2013 13:53:10 -0800 Subject: [PATCH 1668/1799] x86-32, mm: Remove reference to resume_map_numa_kva() commit bb112aec5ee41427e9b9726e3d57b896709598ed upstream. Remove reference to removed function resume_map_numa_kva(). Signed-off-by: H. Peter Anvin Cc: Dave Hansen Link: http://lkml.kernel.org/r/20130131005616.1C79F411@kernel.stglabs.ibm.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/mmzone_32.h | 6 ------ arch/x86/power/hibernate_32.c | 2 -- 2 files changed, 8 deletions(-) diff --git a/arch/x86/include/asm/mmzone_32.h b/arch/x86/include/asm/mmzone_32.h index 55728e121473..5e0286f8081a 100644 --- a/arch/x86/include/asm/mmzone_32.h +++ b/arch/x86/include/asm/mmzone_32.h @@ -14,12 +14,6 @@ extern struct pglist_data *node_data[]; #include -extern void resume_map_numa_kva(pgd_t *pgd); - -#else /* !CONFIG_NUMA */ - -static inline void resume_map_numa_kva(pgd_t *pgd) {} - #endif /* CONFIG_NUMA */ #ifdef CONFIG_DISCONTIGMEM diff --git a/arch/x86/power/hibernate_32.c b/arch/x86/power/hibernate_32.c index 74202c1910cd..7d28c885d238 100644 --- a/arch/x86/power/hibernate_32.c +++ b/arch/x86/power/hibernate_32.c @@ -129,8 +129,6 @@ static int resume_physical_mapping_init(pgd_t *pgd_base) } } - resume_map_numa_kva(pgd_base); - return 0; } -- GitLab From 5c444ede11d516377ec6a3230d450441f46cfb4f Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 31 Jan 2013 14:00:48 -0800 Subject: [PATCH 1669/1799] x86-32, mm: Remove reference to alloc_remap() commit 07f4207a305c834f528d08428df4531744e25678 upstream. We have removed the remap allocator for x86-32, and x86-64 never had it (and doesn't need it). Remove residual reference to it. Reported-by: Yinghai Lu Signed-off-by: H. Peter Anvin Cc: Dave Hansen Link: http://lkml.kernel.org/r/CAE9FiQVn6_QZi3fNQ-JHYiR-7jeDJ5hT0SyT_%2BzVvfOj=PzF3w@mail.gmail.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/numa.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index dae8397e3615..c1e83944abfe 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -193,7 +193,6 @@ int __init numa_add_memblk(int nid, u64 start, u64 end) static void __init setup_node_data(int nid, u64 start, u64 end) { const size_t nd_size = roundup(sizeof(pg_data_t), PAGE_SIZE); - bool remapped = false; u64 nd_pa; void *nd; int tnid; @@ -211,28 +210,22 @@ static void __init setup_node_data(int nid, u64 start, u64 end) nid, start, end); /* - * Allocate node data. Try remap allocator first, node-local - * memory and then any node. Never allocate in DMA zone. + * Allocate node data. Try node-local memory and then any node. + * Never allocate in DMA zone. */ - nd = alloc_remap(nid, nd_size); - if (nd) { - nd_pa = __pa(nd); - remapped = true; - } else { - nd_pa = memblock_alloc_nid(nd_size, SMP_CACHE_BYTES, nid); - if (!nd_pa) { - pr_err("Cannot find %zu bytes in node %d\n", - nd_size, nid); - return; - } - nd = __va(nd_pa); + nd_pa = memblock_alloc_nid(nd_size, SMP_CACHE_BYTES, nid); + if (!nd_pa) { + pr_err("Cannot find %zu bytes in node %d\n", + nd_size, nid); + return; } + nd = __va(nd_pa); /* report and initialize */ - printk(KERN_INFO " NODE_DATA [%016Lx - %016Lx]%s\n", - nd_pa, nd_pa + nd_size - 1, remapped ? " (remapped)" : ""); + printk(KERN_INFO " NODE_DATA [mem %#010Lx-%#010Lx]\n", + nd_pa, nd_pa + nd_size - 1); tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT); - if (!remapped && tnid != nid) + if (tnid != nid) printk(KERN_INFO " NODE_DATA(%d) on node %d\n", nid, tnid); node_data[nid] = nd; -- GitLab From 17c2f96bd1de5999900303b3eb923b8cdf6ee2ba Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 18 Feb 2013 09:58:02 -0800 Subject: [PATCH 1670/1799] mm: fix pageblock bitmap allocation commit 7c45512df987c5619db041b5c9b80d281e26d3db upstream. Commit c060f943d092 ("mm: use aligned zone start for pfn_to_bitidx calculation") fixed out calculation of the index into the pageblock bitmap when a !SPARSEMEM zome was not aligned to pageblock_nr_pages. However, the _allocation_ of that bitmap had never taken this alignment requirement into accout, so depending on the exact size and alignment of the zone, the use of that index could then access past the allocation, resulting in some very subtle memory corruption. This was reported (and bisected) by Ingo Molnar: one of his random config builds would hang with certain very specific kernel command line options. In the meantime, commit c060f943d092 has been marked for stable, so this fix needs to be back-ported to the stable kernels that backported the commit to use the right alignment. Bisected-and-tested-by: Ingo Molnar Acked-by: Mel Gorman Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/page_alloc.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 691b8ecdaa69..533ea80f856a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4216,10 +4216,11 @@ static void __meminit calculate_node_totalpages(struct pglist_data *pgdat, * round what is now in bits to nearest long in bits, then return it in * bytes. */ -static unsigned long __init usemap_size(unsigned long zonesize) +static unsigned long __init usemap_size(unsigned long zone_start_pfn, unsigned long zonesize) { unsigned long usemapsize; + zonesize += zone_start_pfn & (pageblock_nr_pages-1); usemapsize = roundup(zonesize, pageblock_nr_pages); usemapsize = usemapsize >> pageblock_order; usemapsize *= NR_PAGEBLOCK_BITS; @@ -4229,17 +4230,19 @@ static unsigned long __init usemap_size(unsigned long zonesize) } static void __init setup_usemap(struct pglist_data *pgdat, - struct zone *zone, unsigned long zonesize) + struct zone *zone, + unsigned long zone_start_pfn, + unsigned long zonesize) { - unsigned long usemapsize = usemap_size(zonesize); + unsigned long usemapsize = usemap_size(zone_start_pfn, zonesize); zone->pageblock_flags = NULL; if (usemapsize) zone->pageblock_flags = alloc_bootmem_node_nopanic(pgdat, usemapsize); } #else -static inline void setup_usemap(struct pglist_data *pgdat, - struct zone *zone, unsigned long zonesize) {} +static inline void setup_usemap(struct pglist_data *pgdat, struct zone *zone, + unsigned long zone_start_pfn, unsigned long zonesize) {} #endif /* CONFIG_SPARSEMEM */ #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE @@ -4367,7 +4370,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, continue; set_pageblock_order(pageblock_default_order()); - setup_usemap(pgdat, zone, size); + setup_usemap(pgdat, zone, zone_start_pfn, size); ret = init_currently_empty_zone(zone, zone_start_pfn, size, MEMMAP_EARLY); BUG_ON(ret); -- GitLab From 526a26556b9069238ea7eecb9095cc672daef0e5 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 7 Feb 2013 17:14:08 -0800 Subject: [PATCH 1671/1799] timeconst.pl: Eliminate Perl warning commit 63a3f603413ffe82ad775f2d62a5afff87fd94a0 upstream. defined(@array) is deprecated in Perl and gives off a warning. Restructure the code to remove that warning. [ hpa: it would be interesting to revert to the timeconst.bc script. It appears that the failures reported by akpm during testing of that script was due to a known broken version of make, not a problem with bc. The Makefile rules could probably be restructured to avoid the make bug, or it is probably old enough that it doesn't matter. ] Reported-by: Andi Kleen Signed-off-by: H. Peter Anvin Cc: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- kernel/timeconst.pl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/kernel/timeconst.pl b/kernel/timeconst.pl index eb51d76e058a..3f42652a6a37 100644 --- a/kernel/timeconst.pl +++ b/kernel/timeconst.pl @@ -369,10 +369,8 @@ if ($hz eq '--can') { die "Usage: $0 HZ\n"; } - @val = @{$canned_values{$hz}}; - if (!defined(@val)) { - @val = compute_values($hz); - } + $cv = $canned_values{$hz}; + @val = defined($cv) ? @$cv : compute_values($hz); output($hz, @val); } exit 0; -- GitLab From b3c57f009cfd9ed81737169c4026bfd03191d993 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 23 Nov 2012 10:08:44 +0100 Subject: [PATCH 1672/1799] genirq: Avoid deadlock in spurious handling commit e716efde75267eab919cdb2bef5b2cb77f305326 upstream. commit 52553ddf(genirq: fix regression in irqfixup, irqpoll) introduced a potential deadlock by calling the action handler with the irq descriptor lock held. Remove the call and let the handling code run even for an interrupt where only a single action is registered. That matches the goal of the above commit and avoids the deadlock. Document the confusing action = desc->action reload in the handling loop while at it. Reported-and-tested-by: "Wang, Warner" Tested-by: Edward Donovan Cc: "Wang, Song-Bo (Stoney)" Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/irq/spurious.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index 611cd6003c45..7b5f012bde9d 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -80,13 +80,11 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force) /* * All handlers must agree on IRQF_SHARED, so we test just the - * first. Check for action->next as well. + * first. */ action = desc->action; if (!action || !(action->flags & IRQF_SHARED) || - (action->flags & __IRQF_TIMER) || - (action->handler(irq, action->dev_id) == IRQ_HANDLED) || - !action->next) + (action->flags & __IRQF_TIMER)) goto out; /* Already running on another processor */ @@ -104,6 +102,7 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force) do { if (handle_irq_event(desc) == IRQ_HANDLED) ret = IRQ_HANDLED; + /* Make sure that there is still a valid action */ action = desc->action; } while ((desc->istate & IRQS_PENDING) && action); desc->istate &= ~IRQS_POLL_INPROGRESS; -- GitLab From 7c3e516d99265e4aa915f3c05611b0f426bf8ce3 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 15 Feb 2013 11:08:11 +0100 Subject: [PATCH 1673/1799] posix-cpu-timers: Fix nanosleep task_struct leak commit e6c42c295e071dd74a66b5a9fcf4f44049888ed8 upstream. The trinity fuzzer triggered a task_struct reference leak via clock_nanosleep with CPU_TIMERs. do_cpu_nanosleep() calls posic_cpu_timer_create(), but misses a corresponding posix_cpu_timer_del() which leads to the task_struct reference leak. Reported-and-tested-by: Tommi Rantala Signed-off-by: Stanislaw Gruszka Cc: Dave Jones Cc: John Stultz Cc: Oleg Nesterov Link: http://lkml.kernel.org/r/20130215100810.GF4392@redhat.com Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/posix-cpu-timers.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 125cb67daa21..acbb79c9092c 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -1422,8 +1422,10 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, while (!signal_pending(current)) { if (timer.it.cpu.expires.sched == 0) { /* - * Our timer fired and was reset. + * Our timer fired and was reset, below + * deletion can not fail. */ + posix_cpu_timer_del(&timer); spin_unlock_irq(&timer.it_lock); return 0; } @@ -1441,9 +1443,26 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, * We were interrupted by a signal. */ sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp); - posix_cpu_timer_set(&timer, 0, &zero_it, it); + error = posix_cpu_timer_set(&timer, 0, &zero_it, it); + if (!error) { + /* + * Timer is now unarmed, deletion can not fail. + */ + posix_cpu_timer_del(&timer); + } spin_unlock_irq(&timer.it_lock); + while (error == TIMER_RETRY) { + /* + * We need to handle case when timer was or is in the + * middle of firing. In other cases we already freed + * resources. + */ + spin_lock_irq(&timer.it_lock); + error = posix_cpu_timer_del(&timer); + spin_unlock_irq(&timer.it_lock); + } + if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) { /* * It actually did fire already. -- GitLab From dd9c58a90c955ae794c1080156db8d8f64a52a21 Mon Sep 17 00:00:00 2001 From: Leonid Shatz Date: Mon, 4 Feb 2013 14:33:37 +0200 Subject: [PATCH 1674/1799] hrtimer: Prevent hrtimer_enqueue_reprogram race commit b22affe0aef429d657bc6505aacb1c569340ddd2 upstream. hrtimer_enqueue_reprogram contains a race which could result in timer.base switch during unlock/lock sequence. hrtimer_enqueue_reprogram is releasing the lock protecting the timer base for calling raise_softirq_irqsoff() due to a lock ordering issue versus rq->lock. If during that time another CPU calls __hrtimer_start_range_ns() on the same hrtimer, the timer base might switch, before the current CPU can lock base->lock again and therefor the unlock_timer_base() call will unlock the wrong lock. [ tglx: Added comment and massaged changelog ] Signed-off-by: Leonid Shatz Signed-off-by: Izik Eidus Cc: Andrea Arcangeli Link: http://lkml.kernel.org/r/1359981217-389-1-git-send-email-izik.eidus@ravellosystems.com Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/hrtimer.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 6db7a5ed52b5..cdd5607c0ceb 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -640,21 +640,9 @@ static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) * and expiry check is done in the hrtimer_interrupt or in the softirq. */ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, - struct hrtimer_clock_base *base, - int wakeup) + struct hrtimer_clock_base *base) { - if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) { - if (wakeup) { - raw_spin_unlock(&base->cpu_base->lock); - raise_softirq_irqoff(HRTIMER_SOFTIRQ); - raw_spin_lock(&base->cpu_base->lock); - } else - __raise_softirq_irqoff(HRTIMER_SOFTIRQ); - - return 1; - } - - return 0; + return base->cpu_base->hres_active && hrtimer_reprogram(timer, base); } static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) @@ -735,8 +723,7 @@ static inline int hrtimer_switch_to_hres(void) { return 0; } static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { } static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, - struct hrtimer_clock_base *base, - int wakeup) + struct hrtimer_clock_base *base) { return 0; } @@ -995,8 +982,21 @@ int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, * * XXX send_remote_softirq() ? */ - if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases)) - hrtimer_enqueue_reprogram(timer, new_base, wakeup); + if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases) + && hrtimer_enqueue_reprogram(timer, new_base)) { + if (wakeup) { + /* + * We need to drop cpu_base->lock to avoid a + * lock ordering issue vs. rq->lock. + */ + raw_spin_unlock(&new_base->cpu_base->lock); + raise_softirq_irqoff(HRTIMER_SOFTIRQ); + local_irq_restore(flags); + return ret; + } else { + __raise_softirq_irqoff(HRTIMER_SOFTIRQ); + } + } unlock_hrtimer_base(timer, &flags); -- GitLab From 507d34bf74e3cef390d74b180ed9695e6bf3dcbb Mon Sep 17 00:00:00 2001 From: Olaf Hering <[mailto:olaf@aepfle.de]> Date: Sun, 3 Feb 2013 17:22:37 -0800 Subject: [PATCH 1675/1799] x86: Hyper-V: register clocksource only if its advertised commit 32068f6527b8f1822a30671dedaf59c567325026 upstream. Enable hyperv_clocksource only if its advertised as a feature. XenServer 6 returns the signature which is checked in ms_hyperv_platform(), but it does not offer all features. Currently the clocksource is enabled unconditionally in ms_hyperv_init_platform(), and the result is a hanging guest. Hyper-V spec Bit 1 indicates the availability of Partition Reference Counter. Register the clocksource only if this bit is set. The guest in question prints this in dmesg: [ 0.000000] Hypervisor detected: Microsoft HyperV [ 0.000000] HyperV: features 0x70, hints 0x0 This bug can be reproduced easily be setting 'viridian=1' in a HVM domU .cfg file. A workaround without this patch is to boot the HVM guest with 'clocksource=jiffies'. Signed-off-by: Olaf Hering Link: http://lkml.kernel.org/r/1359940959-32168-1-git-send-email-kys@microsoft.com Signed-off-by: K. Y. Srinivasan Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mshyperv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 0a630dd4b620..646d192b18a2 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -68,7 +68,8 @@ static void __init ms_hyperv_init_platform(void) printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n", ms_hyperv.features, ms_hyperv.hints); - clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100); + if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE) + clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100); } const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { -- GitLab From 7fb3e95821e901ed594c88747e5729a39723d2ff Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Mon, 11 Feb 2013 19:49:48 +0400 Subject: [PATCH 1676/1799] ALSA: ali5451: remove irq enabling in pointer callback commit dacae5a19b4cbe1b5e3a86de23ea74cbe9ec9652 upstream. snd_ali_pointer function is called with local interrupts disabled. However it seems very strange to reenable them in such way. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Denis Efremov Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/ali5451/ali5451.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index bdd6164e9c7e..131fd1f5db05 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -1435,7 +1435,7 @@ static snd_pcm_uframes_t snd_ali_pointer(struct snd_pcm_substream *substream) spin_lock(&codec->reg_lock); if (!pvoice->running) { - spin_unlock_irq(&codec->reg_lock); + spin_unlock(&codec->reg_lock); return 0; } outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR)); -- GitLab From ceb0446b6dff34bfe41c9fa54796e7b21a17bd56 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Mon, 11 Feb 2013 19:04:06 +0400 Subject: [PATCH 1677/1799] ALSA: rme32.c irq enabling after spin_lock_irq commit f49a59c4471d81a233e09dda45187cc44fda009d upstream. According to the other code in this driver and similar code in rme96 it seems, that spin_lock_irq in snd_rme32_capture_close function should be paired with spin_unlock_irq. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Denis Efremov Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/rme32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index b4819d5e41db..64da910ac34c 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -1017,7 +1017,7 @@ static int snd_rme32_capture_close(struct snd_pcm_substream *substream) spin_lock_irq(&rme32->lock); rme32->capture_substream = NULL; rme32->capture_periodsize = 0; - spin_unlock(&rme32->lock); + spin_unlock_irq(&rme32->lock); return 0; } -- GitLab From 0c10d7fd0d53e3e44cc04edc37120bce6d74e2ca Mon Sep 17 00:00:00 2001 From: Dirkjan Bussink Date: Wed, 30 Jan 2013 11:44:50 +0100 Subject: [PATCH 1678/1799] tty: Prevent deadlock in n_gsm driver commit 4d9b109060f690f5c835130ff54165ae157b3087 upstream. This change fixes a deadlock when the multiplexer is closed while there are still client side ports open. When the multiplexer is closed and there are active tty's it tries to close them with tty_vhangup. This has a problem though, because tty_vhangup needs the tty_lock. This patch changes it to unlock the tty_lock before attempting the hangup and relocks afterwards. The additional call to tty_port_tty_set is needed because otherwise the port stays active because of the reference counter. This change also exposed another problem that other code paths don't expect that the multiplexer could have been closed. This patch also adds checks for these cases in the gsmtty_ class of function that could be called. The documentation explicitly states that "first close all virtual ports before closing the physical port" but we've found this to not always reality in our field situations. The GPRS / UTMS modem sometimes crashes and needs a power cycle in that case which means cleanly shutting down everything is not always possible. This change makes it much more robust for our situation where at least the system is recoverable with this patch and doesn't hang in a deadlock situation inside the kernel. The patch is against the long term support kernel (3.4.27) and should apply cleanly to more recent branches. Tested with a Telit GE864-QUADV2 and Telit HE910 modem. Signed-off-by: Dirkjan Bussink Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 90dff8233efd..4a418e44d562 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1692,6 +1692,8 @@ static inline void dlci_put(struct gsm_dlci *dlci) kref_put(&dlci->ref, gsm_dlci_free); } +static void gsm_destroy_network(struct gsm_dlci *dlci); + /** * gsm_dlci_release - release DLCI * @dlci: DLCI to destroy @@ -1705,9 +1707,19 @@ static void gsm_dlci_release(struct gsm_dlci *dlci) { struct tty_struct *tty = tty_port_tty_get(&dlci->port); if (tty) { + mutex_lock(&dlci->mutex); + gsm_destroy_network(dlci); + mutex_unlock(&dlci->mutex); + + /* tty_vhangup needs the tty_lock, so unlock and + relock after doing the hangup. */ + tty_unlock(); tty_vhangup(tty); + tty_lock(); + tty_port_tty_set(&dlci->port, NULL); tty_kref_put(tty); } + dlci->state = DLCI_CLOSED; dlci_put(dlci); } @@ -2933,6 +2945,8 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp) if (dlci == NULL) return; + if (dlci->state == DLCI_CLOSED) + return; mutex_lock(&dlci->mutex); gsm_destroy_network(dlci); mutex_unlock(&dlci->mutex); @@ -2951,6 +2965,8 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp) static void gsmtty_hangup(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return; tty_port_hangup(&dlci->port); gsm_dlci_begin_close(dlci); } @@ -2958,9 +2974,12 @@ static void gsmtty_hangup(struct tty_struct *tty) static int gsmtty_write(struct tty_struct *tty, const unsigned char *buf, int len) { + int sent; struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return -EINVAL; /* Stuff the bytes into the fifo queue */ - int sent = kfifo_in_locked(dlci->fifo, buf, len, &dlci->lock); + sent = kfifo_in_locked(dlci->fifo, buf, len, &dlci->lock); /* Need to kick the channel */ gsm_dlci_data_kick(dlci); return sent; @@ -2969,18 +2988,24 @@ static int gsmtty_write(struct tty_struct *tty, const unsigned char *buf, static int gsmtty_write_room(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return -EINVAL; return TX_SIZE - kfifo_len(dlci->fifo); } static int gsmtty_chars_in_buffer(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return -EINVAL; return kfifo_len(dlci->fifo); } static void gsmtty_flush_buffer(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return; /* Caution needed: If we implement reliable transport classes then the data being transmitted can't simply be junked once it has first hit the stack. Until then we can just blow it @@ -2999,6 +3024,8 @@ static void gsmtty_wait_until_sent(struct tty_struct *tty, int timeout) static int gsmtty_tiocmget(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return -EINVAL; return dlci->modem_rx; } @@ -3008,6 +3035,8 @@ static int gsmtty_tiocmset(struct tty_struct *tty, struct gsm_dlci *dlci = tty->driver_data; unsigned int modem_tx = dlci->modem_tx; + if (dlci->state == DLCI_CLOSED) + return -EINVAL; modem_tx &= ~clear; modem_tx |= set; @@ -3026,6 +3055,8 @@ static int gsmtty_ioctl(struct tty_struct *tty, struct gsm_netconfig nc; int index; + if (dlci->state == DLCI_CLOSED) + return -EINVAL; switch (cmd) { case GSMIOC_ENABLE_NET: if (copy_from_user(&nc, (void __user *)arg, sizeof(nc))) @@ -3052,6 +3083,9 @@ static int gsmtty_ioctl(struct tty_struct *tty, static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old) { + struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return; /* For the moment its fixed. In actual fact the speed information for the virtual channel can be propogated in both directions by the RPN control message. This however rapidly gets nasty as we @@ -3063,6 +3097,8 @@ static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old) static void gsmtty_throttle(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return; if (tty->termios->c_cflag & CRTSCTS) dlci->modem_tx &= ~TIOCM_DTR; dlci->throttled = 1; @@ -3073,6 +3109,8 @@ static void gsmtty_throttle(struct tty_struct *tty) static void gsmtty_unthrottle(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return; if (tty->termios->c_cflag & CRTSCTS) dlci->modem_tx |= TIOCM_DTR; dlci->throttled = 0; @@ -3084,6 +3122,8 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state) { struct gsm_dlci *dlci = tty->driver_data; int encode = 0; /* Off */ + if (dlci->state == DLCI_CLOSED) + return -EINVAL; if (state == -1) /* "On indefinitely" - we can't encode this properly */ -- GitLab From 46605dae03a55a70d7fd9886f466b435afc7738b Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Tue, 29 Jan 2013 20:07:41 +0100 Subject: [PATCH 1679/1799] tty: set_termios/set_termiox should not return -EINTR commit 183d95cdd834381c594d3aa801c1f9f9c0c54fa9 upstream. See https://bugzilla.redhat.com/show_bug.cgi?id=904907 read command causes bash to abort with double free or corruption (out). A simple test-case from Roman: // Compile the reproducer and send sigchld ti that process. // EINTR occurs even if SA_RESTART flag is set. void handler(int sig) { } main() { struct sigaction act; act.sa_handler = handler; act.sa_flags = SA_RESTART; sigaction (SIGCHLD, &act, 0); struct termio ttp; ioctl(0, TCGETA, &ttp); while(1) { if (ioctl(0, TCSETAW, ttp) < 0) { if (errno == EINTR) { fprintf(stderr, "BUG!"); return(1); } } } } Change set_termios/set_termiox to return -ERESTARTSYS to fix this particular problem. I didn't dare to change other EINTR's in drivers/tty/, but they look equally wrong. Reported-by: Roman Rakus Reported-by: Lingzhu Xiang Signed-off-by: Oleg Nesterov Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ioctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index a1b9a2f68567..f8d03da536dd 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -617,7 +617,7 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) if (opt & TERMIOS_WAIT) { tty_wait_until_sent(tty, 0); if (signal_pending(current)) - return -EINTR; + return -ERESTARTSYS; } tty_set_termios(tty, &tmp_termios); @@ -684,7 +684,7 @@ static int set_termiox(struct tty_struct *tty, void __user *arg, int opt) if (opt & TERMIOS_WAIT) { tty_wait_until_sent(tty, 0); if (signal_pending(current)) - return -EINTR; + return -ERESTARTSYS; } mutex_lock(&tty->termios_mutex); -- GitLab From 906c9c42101742d1ec86ab22eb55d24d496830a7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 13 Feb 2013 17:53:28 +0100 Subject: [PATCH 1680/1799] USB: serial: fix null-pointer dereferences on disconnect commit b2ca699076573c94fee9a73cb0d8645383b602a0 upstream. Make sure serial-driver dtr_rts is called with disc_mutex held after checking the disconnected flag. Due to a bug in the tty layer, dtr_rts may get called after a device has been disconnected and the tty-device unregistered. Some drivers have had individual checks for disconnect to make sure the disconnected interface was not accessed, but this should really be handled in usb-serial core (at least until the long-standing tty-bug has been fixed). Note that the problem has been made more acute with commit 0998d0631001 ("device-core: Ensure drvdata = NULL when no driver is bound") as the port data is now also NULL when dtr_rts is called resulting in further oopses. Reported-by: Chris Ruehl Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 20 +++++++++----------- drivers/usb/serial/mct_u232.c | 22 +++++++++------------- drivers/usb/serial/sierra.c | 8 +------- drivers/usb/serial/ssu100.c | 19 ++++++++----------- drivers/usb/serial/usb-serial.c | 14 ++++++++++++-- drivers/usb/serial/usb_wwan.c | 8 +++----- 6 files changed, 42 insertions(+), 49 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 77469442b3fa..87ef1503552d 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1919,24 +1919,22 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on) { struct ftdi_private *priv = usb_get_serial_port_data(port); - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) { - /* Disable flow control */ - if (!on && usb_control_msg(port->serial->dev, + /* Disable flow control */ + if (!on) { + if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, priv->interface, NULL, 0, WDR_TIMEOUT) < 0) { - dev_err(&port->dev, "error from flowcontrol urb\n"); + dev_err(&port->dev, "error from flowcontrol urb\n"); } - /* drop RTS and DTR */ - if (on) - set_mctrl(port, TIOCM_DTR | TIOCM_RTS); - else - clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } - mutex_unlock(&port->serial->disc_mutex); + /* drop RTS and DTR */ + if (on) + set_mctrl(port, TIOCM_DTR | TIOCM_RTS); + else + clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } /* diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index d0bf56dba07e..933dd07aa087 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -514,19 +514,15 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on) unsigned int control_state; struct mct_u232_private *priv = usb_get_serial_port_data(port); - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) { - /* drop DTR and RTS */ - spin_lock_irq(&priv->lock); - if (on) - priv->control_state |= TIOCM_DTR | TIOCM_RTS; - else - priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); - control_state = priv->control_state; - spin_unlock_irq(&priv->lock); - mct_u232_set_modem_ctrl(port->serial, control_state); - } - mutex_unlock(&port->serial->disc_mutex); + spin_lock_irq(&priv->lock); + if (on) + priv->control_state |= TIOCM_DTR | TIOCM_RTS; + else + priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); + control_state = priv->control_state; + spin_unlock_irq(&priv->lock); + + mct_u232_set_modem_ctrl(port->serial, control_state); } static void mct_u232_close(struct usb_serial_port *port) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index b622d695fdbc..8ec15c2540b8 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -890,19 +890,13 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) static void sierra_dtr_rts(struct usb_serial_port *port, int on) { - struct usb_serial *serial = port->serial; struct sierra_port_private *portdata; portdata = usb_get_serial_port_data(port); portdata->rts_state = on; portdata->dtr_state = on; - if (serial->dev) { - mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) - sierra_send_setup(port); - mutex_unlock(&serial->disc_mutex); - } + sierra_send_setup(port); } static int sierra_startup(struct usb_serial *serial) diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 3cdc8a52de44..b8db69d96df6 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -532,19 +532,16 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on) dbg("%s\n", __func__); - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) { - /* Disable flow control */ - if (!on && - ssu100_setregister(dev, 0, UART_MCR, 0) < 0) + /* Disable flow control */ + if (!on) { + if (ssu100_setregister(dev, 0, UART_MCR, 0) < 0) dev_err(&port->dev, "error from flowcontrol urb\n"); - /* drop RTS and DTR */ - if (on) - set_mctrl(dev, TIOCM_DTR | TIOCM_RTS); - else - clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS); } - mutex_unlock(&port->serial->disc_mutex); + /* drop RTS and DTR */ + if (on) + set_mctrl(dev, TIOCM_DTR | TIOCM_RTS); + else + clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS); } static void ssu100_update_msr(struct usb_serial_port *port, u8 msr) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index c627ba21b1e8..e4b199cbc97b 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -699,10 +699,20 @@ static int serial_carrier_raised(struct tty_port *port) static void serial_dtr_rts(struct tty_port *port, int on) { struct usb_serial_port *p = container_of(port, struct usb_serial_port, port); - struct usb_serial_driver *drv = p->serial->type; + struct usb_serial *serial = p->serial; + struct usb_serial_driver *drv = serial->type; - if (drv->dtr_rts) + if (!drv->dtr_rts) + return; + /* + * Work-around bug in the tty-layer which can result in dtr_rts + * being called after a disconnect (and tty_unregister_device + * has returned). Remove once bug has been squashed. + */ + mutex_lock(&serial->disc_mutex); + if (!serial->disconnected) drv->dtr_rts(p, on); + mutex_unlock(&serial->disc_mutex); } static const struct tty_port_operations serial_port_ops = { diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index c88657dd31c8..820436ec60e9 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -41,7 +41,6 @@ static bool debug; void usb_wwan_dtr_rts(struct usb_serial_port *port, int on) { - struct usb_serial *serial = port->serial; struct usb_wwan_port_private *portdata; struct usb_wwan_intf_private *intfdata; @@ -54,12 +53,11 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on) return; portdata = usb_get_serial_port_data(port); - mutex_lock(&serial->disc_mutex); + /* FIXME: locking */ portdata->rts_state = on; portdata->dtr_state = on; - if (serial->dev) - intfdata->send_setup(port); - mutex_unlock(&serial->disc_mutex); + + intfdata->send_setup(port); } EXPORT_SYMBOL(usb_wwan_dtr_rts); -- GitLab From 1946c763f335fcc7482936c039fddeb179c7f384 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 17 Feb 2013 17:01:20 +0000 Subject: [PATCH 1681/1799] b43: Increase number of RX DMA slots commit ccae0e50c16a7f7adb029c169147400d1ce9f703 upstream. Bastian Bittorf reported that some of the silent freezes on a Linksys WRT54G were due to overflow of the RX DMA ring buffer, which was created with 64 slots. That finding reminded me that I was seeing similar crashed on a netbook, which also has a relatively slow processor. After increasing the number of slots to 128, runs on the netbook that previously failed now worked; however, I found that 109 slots had been used in one test. For that reason, the number of slots is being increased to 256. Signed-off-by: Larry Finger Cc: Bastian Bittorf Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/b43/dma.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index 315b96ed1d90..9fdd1983079c 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -169,7 +169,7 @@ struct b43_dmadesc_generic { /* DMA engine tuning knobs */ #define B43_TXRING_SLOTS 256 -#define B43_RXRING_SLOTS 64 +#define B43_RXRING_SLOTS 256 #define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN) #define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN) -- GitLab From d1179077b018d6c5488eaaa5c71349094d5104f3 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 8 Feb 2013 12:28:18 -0600 Subject: [PATCH 1682/1799] rtlwifi: rtl8192cu: Add new USB ID commit 8708aac79e4572ba673d7a21e94ddca9f3abb7fc upstream. A new model of the RTL8188CUS has appeared. Reported-and-tested-by: Thomas Rosenkrantz Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 61e57689a058..8cf41bb98837 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -285,6 +285,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)}, /* RTL8188CUS-VL */ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x818a, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x819a, rtl92cu_hal_cfg)}, /* 8188 Combo for BC4 */ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)}, -- GitLab From 6a171676006047cd613093b74a6cfdcba8686065 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 18 Feb 2013 10:29:30 +0200 Subject: [PATCH 1683/1799] rtlwifi: usb: allocate URB control message setup_packet and data buffer separately commit bc6b89237acb3dee6af6e64e51a18255fef89cc2 upstream. rtlwifi allocates both setup_packet and data buffer of control message urb, using shared kmalloc in _usbctrl_vendorreq_async_write. Structure used for allocating is: struct { u8 data[254]; struct usb_ctrlrequest dr; }; Because 'struct usb_ctrlrequest' is __packed, setup packet is unaligned and DMA mapping of both 'data' and 'dr' confuses ARM/sunxi, leading to memory corruptions and freezes. Patch changes setup packet to be allocated separately. [v2]: - Use WARN_ON_ONCE instead of WARN_ON Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/usb.c | 44 +++++++++++++++++++----------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 17cd028d2351..6ce848457d16 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -42,8 +42,12 @@ static void usbctrl_async_callback(struct urb *urb) { - if (urb) - kfree(urb->context); + if (urb) { + /* free dr */ + kfree(urb->setup_packet); + /* free databuf */ + kfree(urb->transfer_buffer); + } } static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request, @@ -55,39 +59,47 @@ static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request, u8 reqtype; struct usb_ctrlrequest *dr; struct urb *urb; - struct rtl819x_async_write_data { - u8 data[REALTEK_USB_VENQT_MAX_BUF_SIZE]; - struct usb_ctrlrequest dr; - } *buf; + const u16 databuf_maxlen = REALTEK_USB_VENQT_MAX_BUF_SIZE; + u8 *databuf; + + if (WARN_ON_ONCE(len > databuf_maxlen)) + len = databuf_maxlen; pipe = usb_sndctrlpipe(udev, 0); /* write_out */ reqtype = REALTEK_USB_VENQT_WRITE; - buf = kmalloc(sizeof(*buf), GFP_ATOMIC); - if (!buf) + dr = kmalloc(sizeof(*dr), GFP_ATOMIC); + if (!dr) return -ENOMEM; + databuf = kmalloc(databuf_maxlen, GFP_ATOMIC); + if (!databuf) { + kfree(dr); + return -ENOMEM; + } + urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { - kfree(buf); + kfree(databuf); + kfree(dr); return -ENOMEM; } - dr = &buf->dr; - dr->bRequestType = reqtype; dr->bRequest = request; dr->wValue = cpu_to_le16(value); dr->wIndex = cpu_to_le16(index); dr->wLength = cpu_to_le16(len); /* data are already in little-endian order */ - memcpy(buf, pdata, len); + memcpy(databuf, pdata, len); usb_fill_control_urb(urb, udev, pipe, - (unsigned char *)dr, buf, len, - usbctrl_async_callback, buf); + (unsigned char *)dr, databuf, len, + usbctrl_async_callback, NULL); rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc < 0) - kfree(buf); + if (rc < 0) { + kfree(databuf); + kfree(dr); + } usb_free_urb(urb); return rc; } -- GitLab From 4f4eb62481b02ffec9edee9f109d22d6debe0281 Mon Sep 17 00:00:00 2001 From: Stefan Bader Date: Fri, 15 Feb 2013 09:48:52 +0100 Subject: [PATCH 1684/1799] xen: Send spinlock IPI to all waiters commit 76eaca031f0af2bb303e405986f637811956a422 upstream. There is a loophole between Xen's current implementation of pv-spinlocks and the scheduler. This was triggerable through a testcase until v3.6 changed the TLB flushing code. The problem potentially is still there just not observable in the same way. What could happen was (is): 1. CPU n tries to schedule task x away and goes into a slow wait for the runq lock of CPU n-# (must be one with a lower number). 2. CPU n-#, while processing softirqs, tries to balance domains and goes into a slow wait for its own runq lock (for updating some records). Since this is a spin_lock_irqsave in softirq context, interrupts will be re-enabled for the duration of the poll_irq hypercall used by Xen. 3. Before the runq lock of CPU n-# is unlocked, CPU n-1 receives an interrupt (e.g. endio) and when processing the interrupt, tries to wake up task x. But that is in schedule and still on_cpu, so try_to_wake_up goes into a tight loop. 4. The runq lock of CPU n-# gets unlocked, but the message only gets sent to the first waiter, which is CPU n-# and that is busily stuck. 5. CPU n-# never returns from the nested interruption to take and release the lock because the scheduler uses a busy wait. And CPU n never finishes the task migration because the unlock notification only went to CPU n-#. To avoid this and since the unlocking code has no real sense of which waiter is best suited to grab the lock, just send the IPI to all of them. This causes the waiters to return from the hyper- call (those not interrupted at least) and do active spinlocking. BugLink: http://bugs.launchpad.net/bugs/1011792 Acked-by: Jan Beulich Signed-off-by: Stefan Bader Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/spinlock.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index d69cc6c3f808..67bc7bae746e 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -328,7 +328,6 @@ static noinline void xen_spin_unlock_slow(struct xen_spinlock *xl) if (per_cpu(lock_spinners, cpu) == xl) { ADD_STATS(released_slow_kicked, 1); xen_send_IPI_one(cpu, XEN_SPIN_UNLOCK_VECTOR); - break; } } } -- GitLab From 2199a6528ce9b299f3a3e2a6b50cfd197cbc135e Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Mon, 18 Feb 2013 14:57:58 +0000 Subject: [PATCH 1685/1799] xen: close evtchn port if binding to irq fails commit e7e44e444876478d50630f57b0c31d29f6725020 upstream. Signed-off-by: Wei Liu Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/xen/evtchn.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c index b1f60a0c0bea..b2db77e5a593 100644 --- a/drivers/xen/evtchn.c +++ b/drivers/xen/evtchn.c @@ -269,6 +269,14 @@ static int evtchn_bind_to_user(struct per_user_data *u, int port) u->name, (void *)(unsigned long)port); if (rc >= 0) rc = evtchn_make_refcounted(port); + else { + /* bind failed, should close the port now */ + struct evtchn_close close; + close.port = port; + if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) + BUG(); + set_port_user(port, NULL); + } return rc; } @@ -277,6 +285,8 @@ static void evtchn_unbind_from_user(struct per_user_data *u, int port) { int irq = irq_from_evtchn(port); + BUG_ON(irq < 0); + unbind_from_irqhandler(irq, (void *)(unsigned long)port); set_port_user(port, NULL); -- GitLab From 362efcc9b0ba020f9124c70c56381ed64491aeca Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 29 Jan 2013 16:44:27 -0700 Subject: [PATCH 1686/1799] Driver core: treat unregistered bus_types as having no devices commit 4fa3e78be7e985ca814ce2aa0c09cbee404efcf7 upstream. A bus_type has a list of devices (klist_devices), but the list and the subsys_private structure that contains it are not initialized until the bus_type is registered with bus_register(). The panic/reboot path has fixups that look up devices in pci_bus_type. If we panic before registering pci_bus_type, the bus_type exists but the list does not, so mach_reboot_fixups() trips over a null pointer and panics again: mach_reboot_fixups pci_get_device .. bus_find_device(&pci_bus_type, ...) bus->p is NULL Joonsoo reported a problem when panicking before PCI was initialized. I think this patch should be sufficient to replace the patch he posted here: https://lkml.org/lkml/2012/12/28/75 ("[PATCH] x86, reboot: skip reboot_fixups in early boot phase") Reported-by: Joonsoo Kim Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 26a06b801b5b..b850cecb147b 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -294,7 +294,7 @@ int bus_for_each_dev(struct bus_type *bus, struct device *start, struct device *dev; int error = 0; - if (!bus) + if (!bus || !bus->p) return -EINVAL; klist_iter_init_node(&bus->p->klist_devices, &i, @@ -328,7 +328,7 @@ struct device *bus_find_device(struct bus_type *bus, struct klist_iter i; struct device *dev; - if (!bus) + if (!bus || !bus->p) return NULL; klist_iter_init_node(&bus->p->klist_devices, &i, -- GitLab From 4209ee0d3f7992af3903b5f9a3359f6d2f597c4b Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Mon, 8 Oct 2012 16:29:24 -0700 Subject: [PATCH 1687/1799] mm: mmu_notifier: have mmu_notifiers use a global SRCU so they may safely schedule commit 21a92735f660eaecf69a6f2e777f18463760ec32 upstream. With an RCU based mmu_notifier implementation, any callout to mmu_notifier_invalidate_range_{start,end}() or mmu_notifier_invalidate_page() would not be allowed to call schedule() as that could potentially allow a modification to the mmu_notifier structure while it is currently being used. Since srcu allocs 4 machine words per instance per cpu, we may end up with memory exhaustion if we use srcu per mm. So all mms share a global srcu. Note that during large mmu_notifier activity exit & unregister paths might hang for longer periods, but it is tolerable for current mmu_notifier clients. Signed-off-by: Sagi Grimberg Signed-off-by: Andrea Arcangeli Cc: Peter Zijlstra Cc: Haggai Eran Cc: "Paul E. McKenney" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/mmu_notifier.h | 1 + mm/mmu_notifier.c | 73 ++++++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 25 deletions(-) diff --git a/include/linux/mmu_notifier.h b/include/linux/mmu_notifier.h index 1d1b1e13f79f..ee2baf034fc4 100644 --- a/include/linux/mmu_notifier.h +++ b/include/linux/mmu_notifier.h @@ -4,6 +4,7 @@ #include #include #include +#include struct mmu_notifier; struct mmu_notifier_ops; diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c index 862b60822d9f..35ff447d8d14 100644 --- a/mm/mmu_notifier.c +++ b/mm/mmu_notifier.c @@ -14,10 +14,14 @@ #include #include #include +#include #include #include #include +/* global SRCU for all MMs */ +struct srcu_struct srcu; + /* * This function can't run concurrently against mmu_notifier_register * because mm->mm_users > 0 during mmu_notifier_register and exit_mmap @@ -25,8 +29,8 @@ * in parallel despite there being no task using this mm any more, * through the vmas outside of the exit_mmap context, such as with * vmtruncate. This serializes against mmu_notifier_unregister with - * the mmu_notifier_mm->lock in addition to RCU and it serializes - * against the other mmu notifiers with RCU. struct mmu_notifier_mm + * the mmu_notifier_mm->lock in addition to SRCU and it serializes + * against the other mmu notifiers with SRCU. struct mmu_notifier_mm * can't go away from under us as exit_mmap holds an mm_count pin * itself. */ @@ -34,12 +38,13 @@ void __mmu_notifier_release(struct mm_struct *mm) { struct mmu_notifier *mn; struct hlist_node *n; + int id; /* * RCU here will block mmu_notifier_unregister until * ->release returns. */ - rcu_read_lock(); + id = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) /* * if ->release runs before mmu_notifier_unregister it @@ -50,7 +55,7 @@ void __mmu_notifier_release(struct mm_struct *mm) */ if (mn->ops->release) mn->ops->release(mn, mm); - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); spin_lock(&mm->mmu_notifier_mm->lock); while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) { @@ -68,7 +73,7 @@ void __mmu_notifier_release(struct mm_struct *mm) spin_unlock(&mm->mmu_notifier_mm->lock); /* - * synchronize_rcu here prevents mmu_notifier_release to + * synchronize_srcu here prevents mmu_notifier_release to * return to exit_mmap (which would proceed freeing all pages * in the mm) until the ->release method returns, if it was * invoked by mmu_notifier_unregister. @@ -76,7 +81,7 @@ void __mmu_notifier_release(struct mm_struct *mm) * The mmu_notifier_mm can't go away from under us because one * mm_count is hold by exit_mmap. */ - synchronize_rcu(); + synchronize_srcu(&srcu); } /* @@ -89,14 +94,14 @@ int __mmu_notifier_clear_flush_young(struct mm_struct *mm, { struct mmu_notifier *mn; struct hlist_node *n; - int young = 0; + int young = 0, id; - rcu_read_lock(); + id = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->clear_flush_young) young |= mn->ops->clear_flush_young(mn, mm, address); } - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); return young; } @@ -106,9 +111,9 @@ int __mmu_notifier_test_young(struct mm_struct *mm, { struct mmu_notifier *mn; struct hlist_node *n; - int young = 0; + int young = 0, id; - rcu_read_lock(); + id = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->test_young) { young = mn->ops->test_young(mn, mm, address); @@ -116,7 +121,7 @@ int __mmu_notifier_test_young(struct mm_struct *mm, break; } } - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); return young; } @@ -126,8 +131,9 @@ void __mmu_notifier_change_pte(struct mm_struct *mm, unsigned long address, { struct mmu_notifier *mn; struct hlist_node *n; + int id; - rcu_read_lock(); + id = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->change_pte) mn->ops->change_pte(mn, mm, address, pte); @@ -138,7 +144,7 @@ void __mmu_notifier_change_pte(struct mm_struct *mm, unsigned long address, else if (mn->ops->invalidate_page) mn->ops->invalidate_page(mn, mm, address); } - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); } void __mmu_notifier_invalidate_page(struct mm_struct *mm, @@ -146,13 +152,14 @@ void __mmu_notifier_invalidate_page(struct mm_struct *mm, { struct mmu_notifier *mn; struct hlist_node *n; + int id; - rcu_read_lock(); + id = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->invalidate_page) mn->ops->invalidate_page(mn, mm, address); } - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); } void __mmu_notifier_invalidate_range_start(struct mm_struct *mm, @@ -160,13 +167,14 @@ void __mmu_notifier_invalidate_range_start(struct mm_struct *mm, { struct mmu_notifier *mn; struct hlist_node *n; + int id; - rcu_read_lock(); + id = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->invalidate_range_start) mn->ops->invalidate_range_start(mn, mm, start, end); } - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); } void __mmu_notifier_invalidate_range_end(struct mm_struct *mm, @@ -174,13 +182,14 @@ void __mmu_notifier_invalidate_range_end(struct mm_struct *mm, { struct mmu_notifier *mn; struct hlist_node *n; + int id; - rcu_read_lock(); + id = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->invalidate_range_end) mn->ops->invalidate_range_end(mn, mm, start, end); } - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); } static int do_mmu_notifier_register(struct mmu_notifier *mn, @@ -192,6 +201,12 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn, BUG_ON(atomic_read(&mm->mm_users) <= 0); + /* + * Verify that mmu_notifier_init() already run and the global srcu is + * initialized. + */ + BUG_ON(!srcu.per_cpu_ref); + ret = -ENOMEM; mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm), GFP_KERNEL); if (unlikely(!mmu_notifier_mm)) @@ -274,8 +289,8 @@ void __mmu_notifier_mm_destroy(struct mm_struct *mm) /* * This releases the mm_count pin automatically and frees the mm * structure if it was the last user of it. It serializes against - * running mmu notifiers with RCU and against mmu_notifier_unregister - * with the unregister lock + RCU. All sptes must be dropped before + * running mmu notifiers with SRCU and against mmu_notifier_unregister + * with the unregister lock + SRCU. All sptes must be dropped before * calling mmu_notifier_unregister. ->release or any other notifier * method may be invoked concurrently with mmu_notifier_unregister, * and only after mmu_notifier_unregister returned we're guaranteed @@ -290,8 +305,9 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) * RCU here will force exit_mmap to wait ->release to finish * before freeing the pages. */ - rcu_read_lock(); + int id; + id = srcu_read_lock(&srcu); /* * exit_mmap will block in mmu_notifier_release to * guarantee ->release is called before freeing the @@ -299,7 +315,7 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) */ if (mn->ops->release) mn->ops->release(mn, mm); - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); spin_lock(&mm->mmu_notifier_mm->lock); hlist_del_rcu(&mn->hlist); @@ -310,10 +326,17 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) * Wait any running method to finish, of course including * ->release if it was run by mmu_notifier_relase instead of us. */ - synchronize_rcu(); + synchronize_srcu(&srcu); BUG_ON(atomic_read(&mm->mm_count) <= 0); mmdrop(mm); } EXPORT_SYMBOL_GPL(mmu_notifier_unregister); + +static int __init mmu_notifier_init(void) +{ + return init_srcu_struct(&srcu); +} + +module_init(mmu_notifier_init); -- GitLab From d0730c2bf33c1cdab392f88013be6b5ebacf0f29 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Mon, 8 Oct 2012 16:31:52 -0700 Subject: [PATCH 1688/1799] mm: mmu_notifier: make the mmu_notifier srcu static commit 70400303ce0c4ced3139499c676d5c79636b0c72 upstream. The variable must be static especially given the variable name. s/RCU/SRCU/ over a few comments. Signed-off-by: Andrea Arcangeli Cc: Xiao Guangrong Cc: Sagi Grimberg Cc: Peter Zijlstra Cc: Haggai Eran Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mmu_notifier.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c index 35ff447d8d14..3775c9076e4d 100644 --- a/mm/mmu_notifier.c +++ b/mm/mmu_notifier.c @@ -20,7 +20,7 @@ #include /* global SRCU for all MMs */ -struct srcu_struct srcu; +static struct srcu_struct srcu; /* * This function can't run concurrently against mmu_notifier_register @@ -41,7 +41,7 @@ void __mmu_notifier_release(struct mm_struct *mm) int id; /* - * RCU here will block mmu_notifier_unregister until + * SRCU here will block mmu_notifier_unregister until * ->release returns. */ id = srcu_read_lock(&srcu); @@ -302,7 +302,7 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) if (!hlist_unhashed(&mn->hlist)) { /* - * RCU here will force exit_mmap to wait ->release to finish + * SRCU here will force exit_mmap to wait ->release to finish * before freeing the pages. */ int id; -- GitLab From 7fecb64cca9a98f60ff4bc794bb353512bd5c665 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Fri, 22 Feb 2013 16:35:34 -0800 Subject: [PATCH 1689/1799] mmu_notifier_unregister NULL Pointer deref and multiple ->release() callouts commit 751efd8610d3d7d67b7bdf7f62646edea7365dd7 upstream. There is a race condition between mmu_notifier_unregister() and __mmu_notifier_release(). Assume two tasks, one calling mmu_notifier_unregister() as a result of a filp_close() ->flush() callout (task A), and the other calling mmu_notifier_release() from an mmput() (task B). A B t1 srcu_read_lock() t2 if (!hlist_unhashed()) t3 srcu_read_unlock() t4 srcu_read_lock() t5 hlist_del_init_rcu() t6 synchronize_srcu() t7 srcu_read_unlock() t8 hlist_del_rcu() <--- NULL pointer deref. Additionally, the list traversal in __mmu_notifier_release() is not protected by the by the mmu_notifier_mm->hlist_lock which can result in callouts to the ->release() notifier from both mmu_notifier_unregister() and __mmu_notifier_release(). -stable suggestions: The stable trees prior to 3.7.y need commits 21a92735f660 and 70400303ce0c cherry-picked in that order prior to cherry-picking this commit. The 3.7.y tree already has those two commits. Signed-off-by: Robin Holt Cc: Andrea Arcangeli Cc: Wanpeng Li Cc: Xiao Guangrong Cc: Avi Kivity Cc: Hugh Dickins Cc: Marcelo Tosatti Cc: Sagi Grimberg Cc: Haggai Eran Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mmu_notifier.c | 82 ++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c index 3775c9076e4d..8d1ca2de4080 100644 --- a/mm/mmu_notifier.c +++ b/mm/mmu_notifier.c @@ -37,49 +37,51 @@ static struct srcu_struct srcu; void __mmu_notifier_release(struct mm_struct *mm) { struct mmu_notifier *mn; - struct hlist_node *n; int id; /* - * SRCU here will block mmu_notifier_unregister until - * ->release returns. + * srcu_read_lock() here will block synchronize_srcu() in + * mmu_notifier_unregister() until all registered + * ->release() callouts this function makes have + * returned. */ id = srcu_read_lock(&srcu); - hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) - /* - * if ->release runs before mmu_notifier_unregister it - * must be handled as it's the only way for the driver - * to flush all existing sptes and stop the driver - * from establishing any more sptes before all the - * pages in the mm are freed. - */ - if (mn->ops->release) - mn->ops->release(mn, mm); - srcu_read_unlock(&srcu, id); - spin_lock(&mm->mmu_notifier_mm->lock); while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) { mn = hlist_entry(mm->mmu_notifier_mm->list.first, struct mmu_notifier, hlist); + /* - * We arrived before mmu_notifier_unregister so - * mmu_notifier_unregister will do nothing other than - * to wait ->release to finish and - * mmu_notifier_unregister to return. + * Unlink. This will prevent mmu_notifier_unregister() + * from also making the ->release() callout. */ hlist_del_init_rcu(&mn->hlist); + spin_unlock(&mm->mmu_notifier_mm->lock); + + /* + * Clear sptes. (see 'release' description in mmu_notifier.h) + */ + if (mn->ops->release) + mn->ops->release(mn, mm); + + spin_lock(&mm->mmu_notifier_mm->lock); } spin_unlock(&mm->mmu_notifier_mm->lock); /* - * synchronize_srcu here prevents mmu_notifier_release to - * return to exit_mmap (which would proceed freeing all pages - * in the mm) until the ->release method returns, if it was - * invoked by mmu_notifier_unregister. - * - * The mmu_notifier_mm can't go away from under us because one - * mm_count is hold by exit_mmap. + * All callouts to ->release() which we have done are complete. + * Allow synchronize_srcu() in mmu_notifier_unregister() to complete + */ + srcu_read_unlock(&srcu, id); + + /* + * mmu_notifier_unregister() may have unlinked a notifier and may + * still be calling out to it. Additionally, other notifiers + * may have been active via vmtruncate() et. al. Block here + * to ensure that all notifier callouts for this mm have been + * completed and the sptes are really cleaned up before returning + * to exit_mmap(). */ synchronize_srcu(&srcu); } @@ -300,31 +302,31 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) { BUG_ON(atomic_read(&mm->mm_count) <= 0); + spin_lock(&mm->mmu_notifier_mm->lock); if (!hlist_unhashed(&mn->hlist)) { - /* - * SRCU here will force exit_mmap to wait ->release to finish - * before freeing the pages. - */ int id; - id = srcu_read_lock(&srcu); /* - * exit_mmap will block in mmu_notifier_release to - * guarantee ->release is called before freeing the - * pages. + * Ensure we synchronize up with __mmu_notifier_release(). */ + id = srcu_read_lock(&srcu); + + hlist_del_rcu(&mn->hlist); + spin_unlock(&mm->mmu_notifier_mm->lock); + if (mn->ops->release) mn->ops->release(mn, mm); - srcu_read_unlock(&srcu, id); - spin_lock(&mm->mmu_notifier_mm->lock); - hlist_del_rcu(&mn->hlist); + /* + * Allow __mmu_notifier_release() to complete. + */ + srcu_read_unlock(&srcu, id); + } else spin_unlock(&mm->mmu_notifier_mm->lock); - } /* - * Wait any running method to finish, of course including - * ->release if it was run by mmu_notifier_relase instead of us. + * Wait for any running method to finish, including ->release() if it + * was run by __mmu_notifier_release() instead of us. */ synchronize_srcu(&srcu); -- GitLab From 2030511afec79a7f65b967c3d8a22e4a1edd9532 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 14 Dec 2012 17:02:16 +0100 Subject: [PATCH 1690/1799] KVM: s390: Handle hosts not supporting s390-virtio. commit 55c171a6d90dc0574021f9c836127cfd1a7d2e30 upstream. Running under a kvm host does not necessarily imply the presence of a page mapped above the main memory with the virtio information; however, the code includes a hard coded access to that page. Instead, check for the presence of the page and exit gracefully before we hit an addressing exception if it does not exist. Reviewed-by: Marcelo Tosatti Reviewed-by: Alexander Graf Signed-off-by: Cornelia Huck Signed-off-by: Gleb Natapov Signed-off-by: Greg Kroah-Hartman --- drivers/s390/kvm/kvm_virtio.c | 38 +++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index d74e9ae6dfb3..f97b2aa65f42 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c @@ -417,6 +417,26 @@ static void kvm_extint_handler(struct ext_code ext_code, } } +/* + * For s390-virtio, we expect a page above main storage containing + * the virtio configuration. Try to actually load from this area + * in order to figure out if the host provides this page. + */ +static int __init test_devices_support(unsigned long addr) +{ + int ret = -EIO; + + asm volatile( + "0: lura 0,%1\n" + "1: xgr %0,%0\n" + "2:\n" + EX_TABLE(0b,2b) + EX_TABLE(1b,2b) + : "+d" (ret) + : "a" (addr) + : "0", "cc"); + return ret; +} /* * Init function for virtio * devices are in a single page above top of "normal" mem @@ -428,21 +448,23 @@ static int __init kvm_devices_init(void) if (!MACHINE_IS_KVM) return -ENODEV; + if (test_devices_support(real_memory_size) < 0) + return -ENODEV; + + rc = vmem_add_mapping(real_memory_size, PAGE_SIZE); + if (rc) + return rc; + + kvm_devices = (void *) real_memory_size; + kvm_root = root_device_register("kvm_s390"); if (IS_ERR(kvm_root)) { rc = PTR_ERR(kvm_root); printk(KERN_ERR "Could not register kvm_s390 root device"); + vmem_remove_mapping(real_memory_size, PAGE_SIZE); return rc; } - rc = vmem_add_mapping(real_memory_size, PAGE_SIZE); - if (rc) { - root_device_unregister(kvm_root); - return rc; - } - - kvm_devices = (void *) real_memory_size; - INIT_WORK(&hotplug_work, hotplug_devices); service_subclass_irq_register(); -- GitLab From e3aa5ed471454f36e99b8d3a960746eb58c07180 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Fri, 25 Jan 2013 15:34:15 +0100 Subject: [PATCH 1691/1799] s390/kvm: Fix store status for ACRS/FPRS commit 15bc8d8457875f495c59d933b05770ba88d1eacb upstream. On store status we need to copy the current state of registers into a save area. Currently we might save stale versions: The sie state descriptor doesnt have fields for guest ACRS,FPRS, those registers are simply stored in the host registers. The host program must copy these away if needed. We do that in vcpu_put/load. If we now do a store status in KVM code between vcpu_put/load, the saved values are not up-to-date. Lets collect the ACRS/FPRS before saving them. This also fixes some strange problems with hotplug and virtio-ccw, since the low level machine check handler (on hotplug a machine check will happen) will revalidate all registers with the content of the save area. Signed-off-by: Christian Borntraeger Signed-off-by: Gleb Natapov Signed-off-by: Greg Kroah-Hartman --- arch/s390/kvm/kvm-s390.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 217ce44395a4..e00accf9523e 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -677,6 +677,14 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr) } else prefix = 0; + /* + * The guest FPRS and ACRS are in the host FPRS/ACRS due to the lazy + * copying in vcpu load/put. Lets update our copies before we save + * it into the save area + */ + save_fp_regs(&vcpu->arch.guest_fpregs); + save_access_regs(vcpu->run->s.regs.acrs); + if (__guestcopy(vcpu, addr + offsetof(struct save_area, fp_regs), vcpu->arch.guest_fpregs.fprs, 128, prefix)) return -EFAULT; -- GitLab From 803437207a3e6fef7791adeb7a0c2adb4b012459 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 18 Feb 2013 09:52:08 +0100 Subject: [PATCH 1692/1799] futex: Revert "futex: Mark get_robust_list as deprecated" commit fe2b05f7ca9f906be61dced5489f63b8b4d7c770 upstream. This reverts commit ec0c4274e33c0373e476b73e01995c53128f1257. get_robust_list() is in use and a removal would break existing user space. With the permission checks in place it's not longer a security hole. Remove the deprecation warnings. Signed-off-by: Thomas Gleixner Cc: Cyrill Gorcunov Cc: Richard Weinberger Cc: akpm@linux-foundation.org Cc: paul.gortmaker@windriver.com Cc: davej@redhat.com Cc: keescook@chromium.org Cc: ebiederm@xmission.com Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 2 -- kernel/futex_compat.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index 19eb089ca003..887943044d46 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -2471,8 +2471,6 @@ SYSCALL_DEFINE3(get_robust_list, int, pid, if (!futex_cmpxchg_enabled) return -ENOSYS; - WARN_ONCE(1, "deprecated: get_robust_list will be deleted in 2013.\n"); - rcu_read_lock(); ret = -ESRCH; diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c index 83e368b005fc..a9642d528630 100644 --- a/kernel/futex_compat.c +++ b/kernel/futex_compat.c @@ -142,8 +142,6 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, if (!futex_cmpxchg_enabled) return -ENOSYS; - WARN_ONCE(1, "deprecated: get_robust_list will be deleted in 2013.\n"); - rcu_read_lock(); ret = -ESRCH; -- GitLab From 0b7fba4034da2a6dd6ebb994ad9f592939a752cf Mon Sep 17 00:00:00 2001 From: Jim Somerville Date: Thu, 21 Feb 2013 16:41:59 -0800 Subject: [PATCH 1693/1799] inotify: remove broken mask checks causing unmount to be EINVAL commit 676a0675cf9200ac047fb50825f80867b3bb733b upstream. Running the command: inotifywait -e unmount /mnt/disk immediately aborts with a -EINVAL return code. This is however a valid parameter. This abort occurs only if unmount is the sole event parameter. If other event parameters are supplied, then the unmount event wait will work. The problem was introduced by commit 44b350fc23e ("inotify: Fix mask checks"). In that commit, it states: The mask checks in inotify_update_existing_watch() and inotify_new_watch() are useless because inotify_arg_to_mask() sets FS_IN_IGNORED and FS_EVENT_ON_CHILD bits anyway. But instead of removing the useless checks, it did this: mask = inotify_arg_to_mask(arg); - if (unlikely(!mask)) + if (unlikely(!(mask & IN_ALL_EVENTS))) return -EINVAL; The problem is that IN_ALL_EVENTS doesn't include IN_UNMOUNT, and other parts of the code keep IN_UNMOUNT separate from IN_ALL_EVENTS. So the check should be: if (unlikely(!(mask & (IN_ALL_EVENTS | IN_UNMOUNT)))) But inotify_arg_to_mask(arg) always sets the IN_UNMOUNT bit in the mask anyway, so the check is always going to pass and thus should simply be removed. Also note that inotify_arg_to_mask completely controls what mask bits get set from arg, there's no way for invalid bits to get enabled there. Lets fix it by simply removing the useless broken checks. Signed-off-by: Jim Somerville Signed-off-by: Paul Gortmaker Cc: Jerome Marchand Cc: John McCutchan Cc: Robert Love Cc: Eric Paris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/notify/inotify/inotify_user.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 8445fbc8985c..6f292dd53c6d 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -579,8 +579,6 @@ static int inotify_update_existing_watch(struct fsnotify_group *group, /* don't allow invalid bits: we don't want flags set */ mask = inotify_arg_to_mask(arg); - if (unlikely(!(mask & IN_ALL_EVENTS))) - return -EINVAL; fsn_mark = fsnotify_find_inode_mark(group, inode); if (!fsn_mark) @@ -632,8 +630,6 @@ static int inotify_new_watch(struct fsnotify_group *group, /* don't allow invalid bits: we don't want flags set */ mask = inotify_arg_to_mask(arg); - if (unlikely(!(mask & IN_ALL_EVENTS))) - return -EINVAL; tmp_i_mark = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL); if (unlikely(!tmp_i_mark)) -- GitLab From 9fd4e539ed0737be165fc633063885a477ac556a Mon Sep 17 00:00:00 2001 From: MITSUNARI Shigeo Date: Thu, 21 Feb 2013 16:42:01 -0800 Subject: [PATCH 1694/1799] fs/block_dev.c: page cache wrongly left invalidated after revalidate_disk() commit 7630b661da330b35dd57b6f5d6d62b386f2dd751 upstream. We found that bdev->bd_invalidated was left set once revalidate_disk() is called, which results in page cache flush every time that device is open. Specifically, we found this problem in MD block device. Once we resize a MD device, mdadm --monitor periodically flush all page cache for that device every 60 or 1000 seconds when it opens the device. This bug lies since at least 3.2.0 till the latest kernel(3.6.2). Patch is attached. The following steps will reproduce the problem. 1. prepair a block device (eg /dev/sdb). 2. create two partitions: sudo parted /dev/sdb mklabel gpt mkpart primary 0% 50% mkpart primary 50% 100% 3. create a md device. sudo mdadm -C /dev/md/hoge -l 1 -n 2 -e 1.2 --assume-clean --auto=md --symlink=no /dev/sdb1 /dev/sdb2 4. create file system and mount it sudo mkfs.ext3 /dev/md/hoge sudo mkdir /mnt/test sudo mount /dev/md/hoge /mnt/test 5. try to resize the device sudo mdadm -G /dev/md/hoge --size=max 6. create a file to fill file cache. sudo dd if=/dev/urandom of=/mnt/test/data bs=1M count=10 and verify the current status of file by free command. 7. mdadm monitor will open the md device every 1000 seconds and you will find all file cache on the device are cleared. The timing can be reduced by the following steps. a) kill mdadm and restart it with --delay option /sbin/mdadm --monitor --delay=30 --pid-file /var/run/mdadm/monitor.pid --daemonise --scan --syslog or open the md device directly. sudo dd if=/dev/md/hoge of=/dev/null bs=4096 count=1 Signed-off-by: MITSUNARI Shigeo Cc: Al Viro Cc: Jeff Moyer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/block_dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/block_dev.c b/fs/block_dev.c index ba11c30f302d..b3be92c980ee 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1047,6 +1047,7 @@ int revalidate_disk(struct gendisk *disk) mutex_lock(&bdev->bd_mutex); check_disk_size_change(disk, bdev); + bdev->bd_invalidated = 0; mutex_unlock(&bdev->bd_mutex); bdput(bdev); return ret; -- GitLab From cd336937712589aff73931ed84c2bc56d0574a3c Mon Sep 17 00:00:00 2001 From: Junxiao Bi Date: Thu, 21 Feb 2013 16:42:45 -0800 Subject: [PATCH 1695/1799] ocfs2: unlock super lock if lockres refresh failed commit 3278bb748d2437eb1464765f36429e5d6aa91c38 upstream. If lockres refresh failed, the super lock will never be released which will cause some processes on other cluster nodes hung forever. Signed-off-by: Junxiao Bi Cc: Joel Becker Cc: Mark Fasheh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/dlmglue.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 81a4cd22f80b..231eab2b2d07 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -2545,6 +2545,7 @@ int ocfs2_super_lock(struct ocfs2_super *osb, * everything is up to the caller :) */ status = ocfs2_should_refresh_lock_res(lockres); if (status < 0) { + ocfs2_cluster_unlock(osb, lockres, level); mlog_errno(status); goto bail; } @@ -2553,8 +2554,10 @@ int ocfs2_super_lock(struct ocfs2_super *osb, ocfs2_complete_lock_res_refresh(lockres, status); - if (status < 0) + if (status < 0) { + ocfs2_cluster_unlock(osb, lockres, level); mlog_errno(status); + } ocfs2_track_lock_refresh(lockres); } bail: -- GitLab From 3b6e03c9ac4d57ccb03737a997069dc7ab65601c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 21 Feb 2013 16:44:04 -0800 Subject: [PATCH 1696/1799] drivers/video/backlight/adp88?0_bl.c: fix resume commit 5eb02c01bd1f3ef195989ab05e835e2b0711b5a9 upstream. Clearing the NSTBY bit in the control register also automatically clears the BLEN bit. So we need to make sure to set it again during resume, otherwise the backlight will stay off. Signed-off-by: Lars-Peter Clausen Acked-by: Michael Hennerich Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/video/backlight/adp8860_bl.c | 2 +- drivers/video/backlight/adp8870_bl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index 550dbf0bb896..feda482d4af1 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c @@ -791,7 +791,7 @@ static int adp8860_i2c_suspend(struct i2c_client *client, pm_message_t message) static int adp8860_i2c_resume(struct i2c_client *client) { - adp8860_set_bits(client, ADP8860_MDCR, NSTBY); + adp8860_set_bits(client, ADP8860_MDCR, NSTBY | BLEN); return 0; } diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index 9be58c6f18f1..c7a2c35abdda 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c @@ -965,7 +965,7 @@ static int adp8870_i2c_suspend(struct i2c_client *client, pm_message_t message) static int adp8870_i2c_resume(struct i2c_client *client) { - adp8870_set_bits(client, ADP8870_MDCR, NSTBY); + adp8870_set_bits(client, ADP8870_MDCR, NSTBY | BLEN); return 0; } -- GitLab From 06c7976c91566d676766ad57b574757f6d0abd02 Mon Sep 17 00:00:00 2001 From: Greg Thelen Date: Fri, 22 Feb 2013 16:36:01 -0800 Subject: [PATCH 1697/1799] tmpfs: fix use-after-free of mempolicy object commit 5f00110f7273f9ff04ac69a5f85bb535a4fd0987 upstream. The tmpfs remount logic preserves filesystem mempolicy if the mpol=M option is not specified in the remount request. A new policy can be specified if mpol=M is given. Before this patch remounting an mpol bound tmpfs without specifying mpol= mount option in the remount request would set the filesystem's mempolicy object to a freed mempolicy object. To reproduce the problem boot a DEBUG_PAGEALLOC kernel and run: # mkdir /tmp/x # mount -t tmpfs -o size=100M,mpol=interleave nodev /tmp/x # grep /tmp/x /proc/mounts nodev /tmp/x tmpfs rw,relatime,size=102400k,mpol=interleave:0-3 0 0 # mount -o remount,size=200M nodev /tmp/x # grep /tmp/x /proc/mounts nodev /tmp/x tmpfs rw,relatime,size=204800k,mpol=??? 0 0 # note ? garbage in mpol=... output above # dd if=/dev/zero of=/tmp/x/f count=1 # panic here Panic: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [< (null)>] (null) [...] Oops: 0010 [#1] SMP DEBUG_PAGEALLOC Call Trace: mpol_shared_policy_init+0xa5/0x160 shmem_get_inode+0x209/0x270 shmem_mknod+0x3e/0xf0 shmem_create+0x18/0x20 vfs_create+0xb5/0x130 do_last+0x9a1/0xea0 path_openat+0xb3/0x4d0 do_filp_open+0x42/0xa0 do_sys_open+0xfe/0x1e0 compat_sys_open+0x1b/0x20 cstar_dispatch+0x7/0x1f Non-debug kernels will not crash immediately because referencing the dangling mpol will not cause a fault. Instead the filesystem will reference a freed mempolicy object, which will cause unpredictable behavior. The problem boils down to a dropped mpol reference below if shmem_parse_options() does not allocate a new mpol: config = *sbinfo shmem_parse_options(data, &config, true) mpol_put(sbinfo->mpol) sbinfo->mpol = config.mpol /* BUG: saves unreferenced mpol */ This patch avoids the crash by not releasing the mempolicy if shmem_parse_options() doesn't create a new mpol. How far back does this issue go? I see it in both 2.6.36 and 3.3. I did not look back further. Signed-off-by: Greg Thelen Acked-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/shmem.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mm/shmem.c b/mm/shmem.c index a409bd817819..58c4a477be67 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2177,6 +2177,7 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data) unsigned long inodes; int error = -EINVAL; + config.mpol = NULL; if (shmem_parse_options(data, &config, true)) return error; @@ -2201,8 +2202,13 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data) sbinfo->max_inodes = config.max_inodes; sbinfo->free_inodes = config.max_inodes - inodes; - mpol_put(sbinfo->mpol); - sbinfo->mpol = config.mpol; /* transfers initial ref */ + /* + * Preserve previous mempolicy unless mpol remount option was specified. + */ + if (config.mpol) { + mpol_put(sbinfo->mpol); + sbinfo->mpol = config.mpol; /* transfers initial ref */ + } out: spin_unlock(&sbinfo->stat_lock); return error; -- GitLab From f4ce5b3f263c05e7af66fa4eba7c4eb8e1b006bf Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Fri, 22 Feb 2013 16:35:59 -0800 Subject: [PATCH 1698/1799] mm/fadvise.c: drain all pagevecs if POSIX_FADV_DONTNEED fails to discard all pages commit 67d46b296a1ba1477c0df8ff3bc5e0167a0b0732 upstream. Rob van der Heij reported the following (paraphrased) on private mail. The scenario is that I want to avoid backups to fill up the page cache and purge stuff that is more likely to be used again (this is with s390x Linux on z/VM, so I don't give it as much memory that we don't care anymore). So I have something with LD_PRELOAD that intercepts the close() call (from tar, in this case) and issues a posix_fadvise() just before closing the file. This mostly works, except for small files (less than 14 pages) that remains in page cache after the face. Unfortunately Rob has not had a chance to test this exact patch but the test program below should be reproducing the problem he described. The issue is the per-cpu pagevecs for LRU additions. If the pages are added by one CPU but fadvise() is called on another then the pages remain resident as the invalidate_mapping_pages() only drains the local pagevecs via its call to pagevec_release(). The user-visible effect is that a program that uses fadvise() properly is not obeyed. A possible fix for this is to put the necessary smarts into invalidate_mapping_pages() to globally drain the LRU pagevecs if a pagevec page could not be discarded. The downside with this is that an inode cache shrink would send a global IPI and memory pressure potentially causing global IPI storms is very undesirable. Instead, this patch adds a check during fadvise(POSIX_FADV_DONTNEED) to check if invalidate_mapping_pages() discarded all the requested pages. If a subset of pages are discarded it drains the LRU pagevecs and tries again. If the second attempt fails, it assumes it is due to the pages being mapped, locked or dirty and does not care. With this patch, an application using fadvise() correctly will be obeyed but there is a downside that a malicious application can force the kernel to send global IPIs and increase overhead. If accepted, I would like this to be considered as a -stable candidate. It's not an urgent issue but it's a system call that is not working as advertised which is weak. The following test program demonstrates the problem. It should never report that pages are still resident but will without this patch. It assumes that CPU 0 and 1 exist. int main() { int fd; int pagesize = getpagesize(); ssize_t written = 0, expected; char *buf; unsigned char *vec; int resident, i; cpu_set_t set; /* Prepare a buffer for writing */ expected = FILESIZE_PAGES * pagesize; buf = malloc(expected + 1); if (buf == NULL) { printf("ENOMEM\n"); exit(EXIT_FAILURE); } buf[expected] = 0; memset(buf, 'a', expected); /* Prepare the mincore vec */ vec = malloc(FILESIZE_PAGES); if (vec == NULL) { printf("ENOMEM\n"); exit(EXIT_FAILURE); } /* Bind ourselves to CPU 0 */ CPU_ZERO(&set); CPU_SET(0, &set); if (sched_setaffinity(getpid(), sizeof(set), &set) == -1) { perror("sched_setaffinity"); exit(EXIT_FAILURE); } /* open file, unlink and write buffer */ fd = open("fadvise-test-file", O_CREAT|O_EXCL|O_RDWR); if (fd == -1) { perror("open"); exit(EXIT_FAILURE); } unlink("fadvise-test-file"); while (written < expected) { ssize_t this_write; this_write = write(fd, buf + written, expected - written); if (this_write == -1) { perror("write"); exit(EXIT_FAILURE); } written += this_write; } free(buf); /* * Force ourselves to another CPU. If fadvise only flushes the local * CPUs pagevecs then the fadvise will fail to discard all file pages */ CPU_ZERO(&set); CPU_SET(1, &set); if (sched_setaffinity(getpid(), sizeof(set), &set) == -1) { perror("sched_setaffinity"); exit(EXIT_FAILURE); } /* sync and fadvise to discard the page cache */ fsync(fd); if (posix_fadvise(fd, 0, expected, POSIX_FADV_DONTNEED) == -1) { perror("posix_fadvise"); exit(EXIT_FAILURE); } /* map the file and use mincore to see which parts of it are resident */ buf = mmap(NULL, expected, PROT_READ, MAP_SHARED, fd, 0); if (buf == NULL) { perror("mmap"); exit(EXIT_FAILURE); } if (mincore(buf, expected, vec) == -1) { perror("mincore"); exit(EXIT_FAILURE); } /* Check residency */ for (i = 0, resident = 0; i < FILESIZE_PAGES; i++) { if (vec[i]) resident++; } if (resident != 0) { printf("Nr unexpected pages resident: %d\n", resident); exit(EXIT_FAILURE); } munmap(buf, expected); close(fd); free(vec); exit(EXIT_SUCCESS); } Signed-off-by: Mel Gorman Reported-by: Rob van der Heij Tested-by: Rob van der Heij Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/fadvise.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/mm/fadvise.c b/mm/fadvise.c index 469491e0af79..dcb98722a22f 100644 --- a/mm/fadvise.c +++ b/mm/fadvise.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -124,9 +125,22 @@ SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice) start_index = (offset+(PAGE_CACHE_SIZE-1)) >> PAGE_CACHE_SHIFT; end_index = (endbyte >> PAGE_CACHE_SHIFT); - if (end_index >= start_index) - invalidate_mapping_pages(mapping, start_index, + if (end_index >= start_index) { + unsigned long count = invalidate_mapping_pages(mapping, + start_index, end_index); + + /* + * If fewer pages were invalidated than expected then + * it is possible that some of the pages were on + * a per-cpu pagevec for a remote CPU. Drain all + * pagevecs and try again. + */ + if (count < (end_index - start_index + 1)) { + lru_add_drain_all(); + invalidate_mapping_pages(mapping, start_index, end_index); + } + } break; default: ret = -EINVAL; -- GitLab From 38bc0fe99edd35ef738800167c67055f8ca7e476 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 14 Feb 2013 18:14:27 +0000 Subject: [PATCH 1699/1799] drivercore: Fix ordering between deferred_probe and exiting initcalls commit d72cca1eee5b26e313da2a380d4862924e271031 upstream. One of the side effects of deferred probe is that some drivers which used to be probed before initcalls completed are now happening slightly later. This causes two problems. - If a console driver gets deferred, then it may not be ready when userspace starts. For example, if a uart depends on pinctrl, then the uart will get deferred and /dev/console will not be available - __init sections will be discarded before built-in drivers are probed. Strictly speaking, __init functions should not be called in a drivers __probe path, but there are a lot of drivers (console stuff again) that do anyway. In the past it was perfectly safe to do so because all built-in drivers got probed before the end of initcalls. This patch fixes the problem by forcing the first pass of the deferred list to complete at late_initcall time. This is late enough to catch the drivers that are known to have the above issues. Signed-off-by: Grant Likely Tested-by: Haojian Zhuang Cc: Arnd Bergmann Cc: Russell King Cc: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 1b1cbb571d38..97fc774e6bc2 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -160,6 +160,8 @@ static int deferred_probe_initcall(void) driver_deferred_probe_enable = true; driver_deferred_probe_trigger(); + /* Sort as many dependencies as possible before exiting initcalls */ + flush_workqueue(deferred_wq); return 0; } late_initcall(deferred_probe_initcall); -- GitLab From 8e0ed8259d2016543b07a43896bc6f4b7f541e42 Mon Sep 17 00:00:00 2001 From: fanchaoting Date: Mon, 4 Feb 2013 21:15:02 +0800 Subject: [PATCH 1700/1799] umount oops when remove blocklayoutdriver first commit 5a12cca697aca5dfba42a7d4c3356acc0445a2b0 upstream. now pnfs client uses block layout, maybe we can remove blocklayoutdriver first. if we umount later, it can cause oops in unset_pnfs_layoutdriver. because nfss->pnfs_curr_ld->clear_layoutdriver is invalid. reproduce it: modprobe blocklayoutdriver mount -t nfs4 -o minorversion=1 pnfsip:/ /mnt/ rmmod blocklayoutdriver umount /mnt then you can see following CPU 0 Pid: 17023, comm: umount.nfs4 Tainted: GF O 3.7.0-rc6-pnfs #1 VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform RIP: 0010:[] [] unset_pnfs_layoutdriver+0x1d/0x70 [nfsv4] RSP: 0018:ffff8800022d9e48 EFLAGS: 00010286 RAX: ffffffffa04a1b00 RBX: ffff88000b013800 RCX: 0000000000000001 RDX: ffffffff81ae8ee0 RSI: ffff880001ee94b8 RDI: ffff88000b013800 RBP: ffff8800022d9e58 R08: 0000000000000001 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: ffff880001ee9400 R13: ffff8800105978c0 R14: 00007fff25846c08 R15: 0000000001bba550 FS: 00007f45ae7f0700(0000) GS:ffff880012c00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: ffffffffa04a1b38 CR3: 0000000002c0c000 CR4: 00000000000006f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process umount.nfs4 (pid: 17023, threadinfo ffff8800022d8000, task ffff880006e48aa0) Stack: ffff8800105978c0 ffff88000b013800 ffff8800022d9e78 ffffffffa04cd0ce ffff8800022d9e78 ffff88000b013800 ffff8800022d9ea8 ffffffffa04755a7 ffff8800022d9ea8 ffff880002f96400 ffff88000b013800 ffff880002f96400 Call Trace: [] nfs4_destroy_server+0x1e/0x30 [nfsv4] [] nfs_free_server+0xb7/0x150 [nfs] [] nfs_kill_super+0x35/0x40 [nfs] [] deactivate_locked_super+0x45/0x70 [] deactivate_super+0x4a/0x70 [] mntput_no_expire+0xd2/0x130 [] sys_umount+0x72/0xe0 [] system_call_fastpath+0x16/0x1b Code: 06 e1 b8 ea ff ff ff eb 9e 0f 1f 44 00 00 55 48 89 e5 53 48 83 ec 08 66 66 66 66 90 48 8b 87 80 03 00 00 48 89 fb 48 85 c0 74 29 <48> 8b 40 38 48 85 c0 74 02 ff d0 48 8b 03 3e ff 48 04 0f 94 c2 RIP [] unset_pnfs_layoutdriver+0x1d/0x70 [nfsv4] RSP CR2: ffffffffa04a1b38 ---[ end trace 29f75aaedda058bf ]--- Signed-off-by: fanchaoting Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/blocklayout/blocklayout.c | 1 + fs/nfs/objlayout/objio_osd.c | 1 + 2 files changed, 2 insertions(+) diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index d16dae2a9b2e..3a9c2470e4f9 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -1155,6 +1155,7 @@ static const struct nfs_pageio_ops bl_pg_write_ops = { static struct pnfs_layoutdriver_type blocklayout_type = { .id = LAYOUT_BLOCK_VOLUME, .name = "LAYOUT_BLOCK_VOLUME", + .owner = THIS_MODULE, .read_pagelist = bl_read_pagelist, .write_pagelist = bl_write_pagelist, .alloc_layout_hdr = bl_alloc_layout_hdr, diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index 1afe74c42c8a..65538f569f42 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c @@ -589,6 +589,7 @@ static struct pnfs_layoutdriver_type objlayout_type = { .flags = PNFS_LAYOUTRET_ON_SETATTR | PNFS_LAYOUTRET_ON_ERROR, + .owner = THIS_MODULE, .alloc_layout_hdr = objlayout_alloc_layout_hdr, .free_layout_hdr = objlayout_free_layout_hdr, -- GitLab From 92a5267ac37e74cf44675f5992fc6fa4ad694a04 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 19 Feb 2013 12:04:42 -0500 Subject: [PATCH 1701/1799] NLM: Ensure that we resend all pending blocking locks after a reclaim commit 666b3d803a511fbc9bc5e5ea8ce66010cf03ea13 upstream. Currently, nlmclnt_lock will break out of the for(;;) loop when the reclaimer wakes up the blocking lock thread by setting nlm_lck_denied_grace_period. This causes the lock request to fail with an ENOLCK error. The intention was always to ensure that we resend the lock request after the grace period has expired. Reported-by: Wangyuan Zhang Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/lockd/clntproc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 8392cb85bd54..a3a09877ea62 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -551,6 +551,9 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) status = nlmclnt_block(block, req, NLMCLNT_POLL_TIMEOUT); if (status < 0) break; + /* Resend the blocking lock request after a server reboot */ + if (resp->status == nlm_lck_denied_grace_period) + continue; if (resp->status != nlm_lck_blocked) break; } -- GitLab From a8fb02fe99203fea52046151817672102124d389 Mon Sep 17 00:00:00 2001 From: Tomasz Guszkowski Date: Tue, 5 Feb 2013 22:10:31 +0100 Subject: [PATCH 1702/1799] p54usb: corrected USB ID for T-Com Sinus 154 data II commit 008e33f733ca51acb2dd9d88ea878693b04d1d2a upstream. Corrected USB ID for T-Com Sinus 154 data II. ISL3887-based. The device was tested in managed mode with no security, WEP 128 bit and WPA-PSK (TKIP) with firmware 2.13.1.0.lm87.arm (md5sum: 7d676323ac60d6e1a3b6d61e8c528248). It works. Signed-off-by: Tomasz Guszkowski Acked-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 be20cf765bc3..af30777ce31f 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -84,8 +84,8 @@ static struct usb_device_id p54u_table[] = { {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ {USB_DEVICE(0x0803, 0x4310)}, /* Zoom 4410a */ - {USB_DEVICE(0x083a, 0x4503)}, /* T-Com Sinus 154 data II */ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ + {USB_DEVICE(0x083a, 0x4531)}, /* T-Com Sinus 154 data II */ {USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */ {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ -- GitLab From e3fc3cb2a03623b48250dd3a12378a42d276f20e Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 31 Jan 2013 21:14:33 +0100 Subject: [PATCH 1703/1799] ALSA: usb-audio: fix Roland A-PRO support commit 7da58046482fceb17c4a0d4afefd9507ec56de7f upstream. The quirk for the Roland/Cakewalk A-PRO keyboards accidentally used the wrong interface number, which prevented the driver from attaching to the device. Signed-off-by: Clemens Ladisch Signed-off-by: Greg Kroah-Hartman --- sound/usb/quirks-table.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 63128cd62544..fa4c2f7e6aba 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -1658,7 +1658,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { /* .vendor_name = "Roland", */ /* .product_name = "A-PRO", */ - .ifnum = 1, + .ifnum = 0, .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = & (const struct snd_usb_midi_endpoint_info) { .out_cables = 0x0003, -- GitLab From e32afc122e3a808944a9f7af5612bf2a3cbea89a Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Thu, 21 Feb 2013 01:55:50 +0000 Subject: [PATCH 1704/1799] ALSA: usb: Fix Processing Unit Descriptor parsers commit b531f81b0d70ffbe8d70500512483227cc532608 upstream. Commit 99fc86450c439039d2ef88d06b222fd51a779176 "ALSA: usb-mixer: parse descriptors with structs" introduced a set of useful parsers for descriptors. Unfortunately the parses for the Processing Unit Descriptor came with a very subtle bug... Functions uac_processing_unit_iProcessing() and uac_processing_unit_specific() were indexing the baSourceID array forgetting the fields before the iProcessing and process-specific descriptors. The problem was observed with Sound Blaster Extigy mixer, where nNrModes in Up/Down-mix Processing Unit Descriptor was accessed at offset 10 of the descriptor (value 0) instead of offset 15 (value 7). In result the resulting control had interesting limit values: Simple mixer control 'Channel Routing Mode Select',0 Capabilities: volume volume-joined penum Playback channels: Mono Capture channels: Mono Limits: 0 - -1 Mono: -1 [100%] Fixed by starting from the bmControls, which was calculated correctly, instead of baSourceID. Now the mentioned control is fine: Simple mixer control 'Channel Routing Mode Select',0 Capabilities: volume volume-joined penum Playback channels: Mono Capture channels: Mono Limits: 0 - 6 Mono: 0 [0%] Signed-off-by: Pawel Moll Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/audio.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h index a54b8255d75f..6f8b026b3396 100644 --- a/include/linux/usb/audio.h +++ b/include/linux/usb/audio.h @@ -384,14 +384,16 @@ static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_de int protocol) { __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); - return desc->baSourceID[desc->bNrInPins + control_size]; + return *(uac_processing_unit_bmControls(desc, protocol) + + control_size); } static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc, int protocol) { __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); - return &desc->baSourceID[desc->bNrInPins + control_size + 1]; + return uac_processing_unit_bmControls(desc, protocol) + + control_size + 1; } /* 4.5.2 Class-Specific AS Interface Descriptor */ -- GitLab From 63b2afe91cef7d844ea07a1ad17be63ded94e8ca Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 1 Feb 2013 14:01:27 +0100 Subject: [PATCH 1705/1799] ALSA: hda - Release assigned pin/cvt at error path of hdmi_pcm_open() commit 2ad779b7329d6894a80df94e693e72eaa0d56790 upstream. If the driver detects and invalid ELD, it gives an open error. But it forgot to release the assigned pin, converter and spdif ctls before returning. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_hdmi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index d1b805aefa57..f694dd77ad44 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -924,8 +924,12 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, if (!static_hdmi_pcm && eld->eld_valid) { snd_hdmi_eld_update_pcm_info(eld, hinfo); if (hinfo->channels_min > hinfo->channels_max || - !hinfo->rates || !hinfo->formats) + !hinfo->rates || !hinfo->formats) { + per_cvt->assigned = 0; + hinfo->nid = 0; + snd_hda_spdif_ctls_unassign(codec, pin_idx); return -ENODEV; + } } /* Store the updated parameters */ -- GitLab From 7e8b41d605b06c68a7df890e34cb560d837e87ac Mon Sep 17 00:00:00 2001 From: Fernando Luis Vazquez Cao Date: Tue, 12 Feb 2013 16:47:44 +0900 Subject: [PATCH 1706/1799] ALSA: hda - Workaround for silent output on Sony Vaio VGC-LN51JGB with ALC889 commit 12e31a78c70dc12897fda2489113f445c0e94a18 upstream. Some Vaio all-in-one desktop PCs (for example VGC-LN51JGB) are affected by the same issue that caused Vaio Z laptops to become silent: the speaker pin must be connected to the first DAC even though the codec itself advertises flexible routing through any of the DACs. Use the no-primary-hp fixup for choosing the speaker pin as the primary so that the right DAC is assigned on this device. Signed-off-by: Fernando Luis Vazquez Cao 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 f7f877626d88..adb97d6c504a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5440,6 +5440,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601), SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT), SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP), + SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP), /* All Apple entries are in codec SSIDs */ SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF), -- GitLab From 652328944e2514cd8306a71a2bbac4896efa49ed Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 19 Feb 2013 16:11:22 +0100 Subject: [PATCH 1707/1799] ALSA: hda - hdmi: ELD shouldn't be valid after unplug commit bbfd8a19b6913f50a362457c34d49bfafe5e456e upstream. Currently, eld_valid is never set to false, except at kernel module load time. This patch makes sure that eld is no longer valid when the cable is (hot-)unplugged. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_hdmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index f694dd77ad44..02a6e3f481ef 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -993,6 +993,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", codec->addr, pin_nid, eld->monitor_present, eld_valid); + eld->eld_valid = false; if (eld_valid) { if (!snd_hdmi_get_eld(eld, codec, pin_nid)) snd_hdmi_show_eld(eld); -- GitLab From 5cf5b734496e73c30f43833138078ee7884ec725 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 14 Feb 2013 11:49:01 -0800 Subject: [PATCH 1708/1799] sunvdc: Fix off-by-one in generic_request(). [ Upstream commit f4d9605434c0fd4cc8639bf25cfc043418c52362 ] The 'operations' bitmap corresponds one-for-one with the operation codes, no adjustment is necessary. Reported-by: Mark Kettenis Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/block/sunvdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index 9dcf76a10bb6..31dd45177a7a 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -461,7 +461,7 @@ static int generic_request(struct vdc_port *port, u8 op, void *buf, int len) int op_len, err; void *req_buf; - if (!(((u64)1 << ((u64)op - 1)) & port->operations)) + if (!(((u64)1 << (u64)op) & port->operations)) return -EOPNOTSUPP; switch (op) { -- GitLab From 746042cf26dbcf5a8feb4f8938a3531a6169c96e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 5 Feb 2013 11:47:09 -0500 Subject: [PATCH 1709/1799] drm/radeon/dce6: fix display powergating commit 0e3d50bfcbd338254795a700dcff429a96cba1a6 upstream. Only enable it when we disable the display rather than at DPMS time since enabling it requires a full modeset to restore the display state. Fixes blank screens in certain cases. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_crtc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 15594a30ebd4..ebbfbd201739 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -258,8 +258,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) radeon_crtc->enabled = true; /* adjust pm to dpms changes BEFORE enabling crtcs */ radeon_pm_compute_clocks(rdev); - if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) - atombios_powergate_crtc(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_ENABLE); if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) atombios_enable_crtc_memreq(crtc, ATOM_ENABLE); @@ -277,8 +275,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_DISABLE); radeon_crtc->enabled = false; - if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) - atombios_powergate_crtc(crtc, ATOM_ENABLE); /* adjust pm to dpms changes AFTER disabling crtcs */ radeon_pm_compute_clocks(rdev); break; @@ -1670,6 +1666,8 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) int i; atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + if (ASIC_IS_DCE6(rdev)) + atombios_powergate_crtc(crtc, ATOM_ENABLE); for (i = 0; i < rdev->num_crtc; i++) { if (rdev->mode_info.crtcs[i] && -- GitLab From b701cf407f9508fb899b482d9224daba2cedec75 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 7 Feb 2013 11:19:15 +1000 Subject: [PATCH 1710/1799] drm/udl: make usage as a console safer commit bcb39af4486be07e896fc374a2336bad3104ae0a upstream. Okay you don't really want to use udl devices as your console, but if you are unlucky enough to do so, you run into a lot of schedule while atomic due to printk being called from all sorts of funky places. So check if we are in an atomic context, and queue the damage for later, the next printk should cause it to appear. This isn't ideal, but it is simple, and seems to work okay in my testing here. (dirty area idea came from xenfb) fixes a bunch of sleeping while atomic issues running fbcon on udl devices. Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/udl/udl_drv.h | 2 ++ drivers/gpu/drm/udl/udl_fb.c | 44 +++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index e76057586612..2b8c4fdda975 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -74,6 +74,8 @@ struct udl_framebuffer { struct drm_framebuffer base; struct udl_gem_object *obj; bool active_16; /* active on the 16-bit channel */ + int x1, y1, x2, y2; /* dirty rect */ + spinlock_t dirty_lock; }; #define to_udl_fb(x) container_of(x, struct udl_framebuffer, base) diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index b9282cf7aea3..9fbb2778716d 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -153,6 +153,9 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, struct urb *urb; int aligned_x; int bpp = (fb->base.bits_per_pixel / 8); + int x2, y2; + bool store_for_later = false; + unsigned long flags; if (!fb->active_16) return 0; @@ -160,8 +163,6 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, if (!fb->obj->vmapping) udl_gem_vmap(fb->obj); - start_cycles = get_cycles(); - aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long)); width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long)); x = aligned_x; @@ -171,19 +172,53 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, (y + height > fb->base.height)) return -EINVAL; + /* if we are in atomic just store the info + can't test inside spin lock */ + if (in_atomic()) + store_for_later = true; + + x2 = x + width - 1; + y2 = y + height - 1; + + spin_lock_irqsave(&fb->dirty_lock, flags); + + if (fb->y1 < y) + y = fb->y1; + if (fb->y2 > y2) + y2 = fb->y2; + if (fb->x1 < x) + x = fb->x1; + if (fb->x2 > x2) + x2 = fb->x2; + + if (store_for_later) { + fb->x1 = x; + fb->x2 = x2; + fb->y1 = y; + fb->y2 = y2; + spin_unlock_irqrestore(&fb->dirty_lock, flags); + return 0; + } + + fb->x1 = fb->y1 = INT_MAX; + fb->x2 = fb->y2 = 0; + + spin_unlock_irqrestore(&fb->dirty_lock, flags); + start_cycles = get_cycles(); + urb = udl_get_urb(dev); if (!urb) return 0; cmd = urb->transfer_buffer; - for (i = y; i < y + height ; i++) { + for (i = y; i <= y2 ; i++) { const int line_offset = fb->base.pitches[0] * i; const int byte_offset = line_offset + (x * bpp); const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); if (udl_render_hline(dev, bpp, &urb, (char *) fb->obj->vmapping, &cmd, byte_offset, dev_byte_offset, - width * bpp, + (x2 - x + 1) * bpp, &bytes_identical, &bytes_sent)) goto error; } @@ -408,6 +443,7 @@ udl_framebuffer_init(struct drm_device *dev, { int ret; + spin_lock_init(&ufb->dirty_lock); ufb->obj = obj; ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs); drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd); -- GitLab From ae4c05e0232e869cf2418ac6c0c862bb5287d672 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 7 Feb 2013 12:30:25 +1000 Subject: [PATCH 1711/1799] drm/udl: disable fb_defio by default commit 677d23b70bf949f75746c80cbae92c233c6b5e2a upstream. There seems to be a bad interaction between gem/shmem and defio on top, I get list corruption on the page lru in the shmem code. Turn it off for now until we get some more digging done. Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/udl/udl_fb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 9fbb2778716d..f02d223d3947 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -22,9 +22,9 @@ #include "drm_fb_helper.h" -#define DL_DEFIO_WRITE_DELAY 5 /* fb_deferred_io.delay in jiffies */ +#define DL_DEFIO_WRITE_DELAY (HZ/20) /* fb_deferred_io.delay in jiffies */ -static int fb_defio = 1; /* Optionally enable experimental fb_defio mmap support */ +static int fb_defio = 0; /* Optionally enable experimental fb_defio mmap support */ static int fb_bpp = 16; module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); -- GitLab From df28f4890263a0540b395402b43b57f047ccf7d5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 24 Jan 2013 14:14:19 +1000 Subject: [PATCH 1712/1799] vgacon/vt: clear buffer attributes when we load a 512 character font (v2) commit 2a2483072393b27f4336ab068a1f48ca19ff1c1e upstream. When we switch from 256->512 byte font rendering mode, it means the current contents of the screen is being reinterpreted. The bit that holds the high bit of the 9-bit font, may have been previously set, and thus the new font misrenders. The problem case we see is grub2 writes spaces with the bit set, so it ends up with data like 0x820, which gets reinterpreted into 0x120 char which the font translates into G with a circumflex. This flashes up on screen at boot and is quite ugly. A current side effect of this patch though is that any rendering on the screen changes color to a slightly darker color, but at least the screen no longer corrupts. v2: as suggested by hpa, always clear the attribute space, whether we are are going to or from 512 chars. Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 2 +- drivers/video/console/vgacon.c | 22 +++++++++++++++------- include/linux/vt_kern.h | 1 + 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 18d06be8c9bd..068abe1524a1 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -656,7 +656,7 @@ static inline void save_screen(struct vc_data *vc) * Redrawing of screen */ -static void clear_buffer_attributes(struct vc_data *vc) +void clear_buffer_attributes(struct vc_data *vc) { unsigned short *p = (unsigned short *)vc->vc_origin; int count = vc->vc_screenbuf_size / 2; diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index d449a74d4a31..5855d17d19ac 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -1064,7 +1064,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) unsigned short video_port_status = vga_video_port_reg + 6; int font_select = 0x00, beg, i; char *charmap; - + bool clear_attribs = false; if (vga_video_type != VIDEO_TYPE_EGAM) { charmap = (char *) VGA_MAP_MEM(colourmap, 0); beg = 0x0e; @@ -1169,12 +1169,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) /* if 512 char mode is already enabled don't re-enable it. */ if ((set) && (ch512 != vga_512_chars)) { - /* attribute controller */ - for (i = 0; i < MAX_NR_CONSOLES; i++) { - struct vc_data *c = vc_cons[i].d; - if (c && c->vc_sw == &vga_con) - c->vc_hi_font_mask = ch512 ? 0x0800 : 0; - } vga_512_chars = ch512; /* 256-char: enable intensity bit 512-char: disable intensity bit */ @@ -1185,8 +1179,22 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) it means, but it works, and it appears necessary */ inb_p(video_port_status); vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); + clear_attribs = true; } raw_spin_unlock_irq(&vga_lock); + + if (clear_attribs) { + for (i = 0; i < MAX_NR_CONSOLES; i++) { + struct vc_data *c = vc_cons[i].d; + if (c && c->vc_sw == &vga_con) { + /* force hi font mask to 0, so we always clear + the bit on either transition */ + c->vc_hi_font_mask = 0x00; + clear_buffer_attributes(c); + c->vc_hi_font_mask = ch512 ? 0x0800 : 0; + } + } + } return 0; } diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index e33d77f15bda..49e39d4396d0 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -47,6 +47,7 @@ int con_set_cmap(unsigned char __user *cmap); int con_get_cmap(unsigned char __user *cmap); void scrollback(struct vc_data *vc, int lines); void scrollfront(struct vc_data *vc, int lines); +void clear_buffer_attributes(struct vc_data *vc); void update_region(struct vc_data *vc, unsigned long start, int count); void redraw_screen(struct vc_data *vc, int is_switch); #define update_screen(x) redraw_screen(x, 0) -- GitLab From 7b480b03691358af771e6104087e05ffecc7d16a Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 15 Feb 2013 13:36:27 -0200 Subject: [PATCH 1713/1799] drm: don't add inferred modes for monitors that don't support them commit 196e077dc165a307efbd9e7569f81bbdbcf18f65 upstream. If bit 0 of the features byte (0x18) is set to 0, then, according to the EDID spec, "the display is non-continuous frequency (multi-mode) and is only specified to accept the video timing formats that are listed in Base EDID and certain Extension Blocks". For more information, please see the EDID spec, check the notes of the table that explains the "Feature Support" byte (18h) and also the notes on the tables of the section that explains "Display Range Limits & Additional Timing Description Definition (tag #FDh)". Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=45729 Reviewed-by: Alex Deucher Reviewed-by: Adam Jackson Signed-off-by: Paulo Zanoni Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_edid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 9d9835a4fee1..384edc677625 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1769,7 +1769,8 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) num_modes += add_cvt_modes(connector, edid); num_modes += add_standard_modes(connector, edid); num_modes += add_established_modes(connector, edid); - num_modes += add_inferred_modes(connector, edid); + if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) + num_modes += add_inferred_modes(connector, edid); num_modes += add_cea_modes(connector, edid); if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) -- GitLab From d8fe02dde5c0aa474a32fe13d0743be515bb41dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 31 Jan 2013 19:43:37 +0200 Subject: [PATCH 1714/1799] drm: Fill depth/bits_per_pixel for C8 format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c51a6bc5f6d328926a9a4a1247c5030faf190a80 upstream. Set depth/bits_per_pixel to 8 for C8 format. Signed-off-by: Ville Syrjälä Acked-by: Dave Airlie Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_crtc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4fd363f1656c..8320c6bb48d5 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3409,6 +3409,7 @@ void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp) { switch (format) { + case DRM_FORMAT_C8: case DRM_FORMAT_RGB332: case DRM_FORMAT_BGR233: *depth = 8; -- GitLab From d8a5f7fe8d632290ecbb6f692b98136957abe21a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 31 Jan 2013 19:43:38 +0200 Subject: [PATCH 1715/1799] drm: Use C8 instead of RGB332 when determining the format from depth/bpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d84f031bd230fdf9c3b7734940c859bf28b90219 upstream. Support for real RGB332 is a rarity, most hardware only really support C8. So use C8 instead of RGB332 when determining the format based on depth/bpp. This fixes 8bpp fbcon on i915, since i915 will only accept C8 and not RGB332. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=59572 Signed-off-by: Ville Syrjälä Acked-by: Dave Airlie Tested-by: mlsemon35@gmail.com Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 8320c6bb48d5..c61e67222160 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2023,7 +2023,7 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) switch (bpp) { case 8: - fmt = DRM_FORMAT_RGB332; + fmt = DRM_FORMAT_C8; break; case 16: if (depth == 15) -- GitLab From 61d40262e55fe00b817fe7e28f0f4dfad6e31fca Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 7 Feb 2013 10:10:04 +1000 Subject: [PATCH 1716/1799] drm/usb: bind driver to correct device commit 9f23de52b64f7fb801fd76f3dd8651a0dc89187b upstream. While looking at plymouth on udl I noticed that plymouth was trying to use its fb plugin not its drm one, it was trying to drmOpen a driver called usb not udl, noticed that we actually had out driver pointing at the wrong device. Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c index 37c9a523dd1c..767782a96c3a 100644 --- a/drivers/gpu/drm/drm_usb.c +++ b/drivers/gpu/drm/drm_usb.c @@ -18,7 +18,7 @@ int drm_get_usb_dev(struct usb_interface *interface, usbdev = interface_to_usbdev(interface); dev->usbdev = usbdev; - dev->dev = &usbdev->dev; + dev->dev = &interface->dev; mutex_lock(&drm_global_mutex); -- GitLab From bdfb3335569583fd195a3a1a89380d7648a9a85f Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 19 Feb 2013 03:15:14 +0000 Subject: [PATCH 1717/1799] target: Fix divide by zero bug in fabric_max_sectors for unconfigured devices commit 7a3cf6ca1ab2a2f7161c6dec5a787fc7a5de864e upstream This patch fixes a possible divide by zero bug when the fabric_max_sectors device attribute is written and backend se_device failed to be successfully configured -> enabled. Go ahead and use block_size=512 within se_dev_set_fabric_max_sectors() in the event of a target_configure_device() failure case, as no valid dev->dev_attrib.block_size value will have been setup yet. Signed-off-by: Nicholas Bellinger Cc: Herton Ronaldo Krzesinski Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_device.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 26c62f059754..4ecf9d61c221 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1230,6 +1230,8 @@ int se_dev_set_max_sectors(struct se_device *dev, u32 max_sectors) int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) { + int block_size = dev->se_sub_dev->se_dev_attrib.block_size; + if (atomic_read(&dev->dev_export_obj.obj_access_count)) { pr_err("dev[%p]: Unable to change SE Device" " fabric_max_sectors while dev_export_obj: %d count exists\n", @@ -1267,8 +1269,12 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) /* * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks() */ + if (!block_size) { + block_size = 512; + pr_warn("Defaulting to 512 for zero block_size\n"); + } fabric_max_sectors = se_dev_align_max_sectors(fabric_max_sectors, - dev->se_sub_dev->se_dev_attrib.block_size); + block_size); dev->se_sub_dev->se_dev_attrib.fabric_max_sectors = fabric_max_sectors; pr_debug("dev[%p]: SE Device max_sectors changed to %u\n", -- GitLab From df87bd32f94547ecaa586052a6edeb653294a5b4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 21 Jan 2013 19:48:59 +0100 Subject: [PATCH 1718/1799] intel/iommu: force writebuffer-flush quirk on Gen 4 Chipsets commit 210561ffd72d00eccf12c0131b8024d5436bae95 upstream. We already have the quirk entry for the mobile platform, but also reports on some desktop versions. So be paranoid and set it everywhere. References: http://www.mail-archive.com/dri-devel@lists.freedesktop.org/msg33138.html Reported-and-tested-by: Mihai Moldovan Cc: David Woodhouse Cc: "Sankaran, Rajesh" Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel-iommu.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 5d71873c6f65..17119247ac4c 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4212,13 +4212,19 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) { /* * Mobile 4 Series Chipset neglects to set RWBF capability, - * but needs it: + * but needs it. Same seems to hold for the desktop versions. */ printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n"); rwbf_quirk = 1; } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf); #define GGC 0x52 #define GGC_MEMORY_SIZE_MASK (0xf << 8) -- GitLab From 6bdf87562cb048e3e9a76d18e440794830647657 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Fri, 8 Feb 2013 16:35:37 +0200 Subject: [PATCH 1719/1799] drm/i915: disable shared panel fitter for pipe commit 24a1f16de97c4cf0029d9acd04be06db32208726 upstream. If encoder is switched off by BIOS, but the panel fitter is left on, we never try to turn off the panel fitter and leave it still attached to the pipe - which can cause blurry output elsewhere. Based on work by Chris Wilson Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=58867 Signed-off-by: Mika Kuoppala Tested-by: Andreas Sturmlechner [danvet: Remove the redundant HAS_PCH_SPLIT check and add a tiny comment.] Signed-off-by: Daniel Vetter 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 3c9b9c570405..6e8d7a757277 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3303,6 +3303,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; + u32 pctl; if (!intel_crtc->active) return; @@ -3318,6 +3319,13 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) intel_disable_plane(dev_priv, plane, pipe); intel_disable_pipe(dev_priv, pipe); + + /* Disable pannel fitter if it is on this pipe. */ + pctl = I915_READ(PFIT_CONTROL); + if ((pctl & PFIT_ENABLE) && + ((pctl & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT) == pipe) + I915_WRITE(PFIT_CONTROL, 0); + intel_disable_pll(dev_priv, pipe); intel_crtc->active = false; -- GitLab From a143ae690fbf24c2473d5c7c42875c29e150bd13 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Wed, 13 Feb 2013 22:20:22 +0100 Subject: [PATCH 1720/1799] drm/i915: Set i9xx sdvo clock limits according to specifications commit 4f7dfb6788dd022446847fbbfbe45e13bedb5be2 upstream. The Intel PRM says the M1 and M2 divisors must be in the range of 10-20 and 5-9. Since we do all calculations based on them being register values (which are subtracted by 2) we need to specify them accordingly. Signed-off-by: Patrik Jakobsson Reviewed-by: Chris Wilson Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=56359 Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6e8d7a757277..67f6db534090 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -142,8 +142,8 @@ static const intel_limit_t intel_limits_i9xx_sdvo = { .vco = { .min = 1400000, .max = 2800000 }, .n = { .min = 1, .max = 6 }, .m = { .min = 70, .max = 120 }, - .m1 = { .min = 10, .max = 22 }, - .m2 = { .min = 5, .max = 9 }, + .m1 = { .min = 8, .max = 18 }, + .m2 = { .min = 3, .max = 7 }, .p = { .min = 5, .max = 80 }, .p1 = { .min = 1, .max = 8 }, .p2 = { .dot_limit = 200000, -- GitLab From 59959c9505e28cc7b9ead416cb064b4e56ba7dd5 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 28 Jan 2013 16:14:31 +0000 Subject: [PATCH 1721/1799] staging: comedi: disallow COMEDI_DEVCONFIG on non-board minors commit 754ab5c0e55dd118273ca2c217c4d95e9fbc8259 upstream. Comedi has two sorts of minor devices: (a) normal board minor devices in the range 0 to COMEDI_NUM_BOARD_MINORS-1 inclusive; and (b) special subdevice minor devices in the range COMEDI_NUM_BOARD_MINORS upwards that are used to open the same underlying comedi device as the normal board minor devices, but with non-default read and write subdevices for asynchronous commands. The special subdevice minor devices get created when a board supporting asynchronous commands is attached to a normal board minor device, and destroyed when the board is detached from the normal board minor device. One way to attach or detach a board is by using the COMEDI_DEVCONFIG ioctl. This should only be used on normal board minors as the special subdevice minors are too ephemeral. In particular, the change introduced in commit 7d3135af399e92cf4c9bbc5f86b6c140aab3b88c ("staging: comedi: prevent auto-unconfig of manually configured devices") breaks horribly for special subdevice minor devices. Since there's no legitimate use for the COMEDI_DEVCONFIG ioctl on a special subdevice minor device node, disallow it and return -ENOTTY. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index b67c1070df76..cf67ce54f46f 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -136,6 +136,11 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, /* Device config is special, because it must work on * an unconfigured device. */ if (cmd == COMEDI_DEVCONFIG) { + if (minor >= COMEDI_NUM_BOARD_MINORS) { + /* Device config not appropriate on non-board minors. */ + rc = -ENOTTY; + goto done; + } rc = do_devconfig_ioctl(dev, (struct comedi_devconfig __user *)arg); if (rc == 0) -- GitLab From 4aee4099c7309d0610cf857d9d02d27ebfeb1b95 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 30 Jan 2013 20:07:29 +0000 Subject: [PATCH 1722/1799] staging: vt6656: Fix URB submitted while active warning. commit ae5943de8c8c4438cbac5cda599ff0b88c224468 upstream. This error happens because PIPEnsControlOut and PIPEnsControlIn unlock the spin lock for delay, letting in another thread. The patch moves the current MP_SET_FLAG to before filling of sUsbCtlRequest for pControlURB and clears it in event of failing. Any thread calling either function while fMP_CONTROL_READS or fMP_CONTROL_WRITES flags set will return STATUS_FAILURE. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/usbpipe.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index c612ab58f389..f759352a268a 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -168,6 +168,11 @@ int PIPEnsControlOut( if (pDevice->Flags & fMP_CONTROL_WRITES) return STATUS_FAILURE; + if (pDevice->Flags & fMP_CONTROL_READS) + return STATUS_FAILURE; + + MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES); + pDevice->sUsbCtlRequest.bRequestType = 0x40; pDevice->sUsbCtlRequest.bRequest = byRequest; pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue); @@ -182,12 +187,13 @@ int PIPEnsControlOut( ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC); if (ntStatus != 0) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control send request submission failed: %d\n", ntStatus); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "control send request submission failed: %d\n", + ntStatus); + MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); return STATUS_FAILURE; } - else { - MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES); - } + spin_unlock_irq(&pDevice->lock); for (ii = 0; ii <= USB_CTL_WAIT; ii ++) { @@ -227,6 +233,11 @@ int PIPEnsControlIn( if (pDevice->Flags & fMP_CONTROL_READS) return STATUS_FAILURE; + if (pDevice->Flags & fMP_CONTROL_WRITES) + return STATUS_FAILURE; + + MP_SET_FLAG(pDevice, fMP_CONTROL_READS); + pDevice->sUsbCtlRequest.bRequestType = 0xC0; pDevice->sUsbCtlRequest.bRequest = byRequest; pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue); @@ -240,10 +251,11 @@ int PIPEnsControlIn( ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC); if (ntStatus != 0) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control request submission failed: %d\n", ntStatus); - }else { - MP_SET_FLAG(pDevice, fMP_CONTROL_READS); - } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "control request submission failed: %d\n", ntStatus); + MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); + return STATUS_FAILURE; + } spin_unlock_irq(&pDevice->lock); for (ii = 0; ii <= USB_CTL_WAIT; ii ++) { -- GitLab From 03e578b9213094935c692d5728229cc8c0df0fd6 Mon Sep 17 00:00:00 2001 From: Chris Rattray Date: Fri, 1 Feb 2013 15:51:41 +0000 Subject: [PATCH 1723/1799] ASoC: wm2200: correct IN2L and IN3L digital mute commit 0d2b6422529a26ac4dee06196524ba9da70cf735 upstream. Signed-off-by: Chris Rattray Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm2200.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 8e0cf146a68c..9932aacaa5b8 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -990,9 +990,9 @@ SOC_DOUBLE_R_TLV("IN3 Volume", WM2200_IN3L_CONTROL, WM2200_IN3R_CONTROL, SOC_DOUBLE_R("IN1 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L, WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L, +SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_2L, WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L, +SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_3L, WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_MUTE_SHIFT, 1, 1), SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_1L, -- GitLab From 76753d39bf46abf7e37df89e2258bef933bb2207 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Sun, 13 Jan 2013 13:49:47 +0200 Subject: [PATCH 1724/1799] ARM: PXA3xx: program the CSMSADRCFG register commit d107a204154ddd79339203c2deeb7433f0cf6777 upstream. The Chip Select Configuration Register must be programmed to 0x2 in order to achieve the correct behavior of the Static Memory Controller. Without this patch devices wired to DFI and accessed through SMC cannot be accessed after resume from S2. Do not rely on the boot loader to program the CSMSADRCFG register by programming it in the kernel smemc module. Signed-off-by: Igor Grinberg Acked-by: Eric Miao Signed-off-by: Haojian Zhuang Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-pxa/include/mach/smemc.h | 1 + arch/arm/mach-pxa/smemc.c | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-pxa/include/mach/smemc.h b/arch/arm/mach-pxa/include/mach/smemc.h index b7de471b273a..b802f285fe00 100644 --- a/arch/arm/mach-pxa/include/mach/smemc.h +++ b/arch/arm/mach-pxa/include/mach/smemc.h @@ -37,6 +37,7 @@ #define CSADRCFG1 (SMEMC_VIRT + 0x84) /* Address Configuration Register for CS1 */ #define CSADRCFG2 (SMEMC_VIRT + 0x88) /* Address Configuration Register for CS2 */ #define CSADRCFG3 (SMEMC_VIRT + 0x8C) /* Address Configuration Register for CS3 */ +#define CSMSADRCFG (SMEMC_VIRT + 0xA0) /* Chip Select Configuration Register */ /* * More handy macros for PCMCIA diff --git a/arch/arm/mach-pxa/smemc.c b/arch/arm/mach-pxa/smemc.c index 79923058d10f..f38aa890b2c9 100644 --- a/arch/arm/mach-pxa/smemc.c +++ b/arch/arm/mach-pxa/smemc.c @@ -40,6 +40,8 @@ static void pxa3xx_smemc_resume(void) __raw_writel(csadrcfg[1], CSADRCFG1); __raw_writel(csadrcfg[2], CSADRCFG2); __raw_writel(csadrcfg[3], CSADRCFG3); + /* CSMSADRCFG wakes up in its default state (0), so we need to set it */ + __raw_writel(0x2, CSMSADRCFG); } static struct syscore_ops smemc_syscore_ops = { @@ -49,8 +51,19 @@ static struct syscore_ops smemc_syscore_ops = { static int __init smemc_init(void) { - if (cpu_is_pxa3xx()) + if (cpu_is_pxa3xx()) { + /* + * The only documentation we have on the + * Chip Select Configuration Register (CSMSADRCFG) is that + * it must be programmed to 0x2. + * Moreover, in the bit definitions, the second bit + * (CSMSADRCFG[1]) is called "SETALWAYS". + * Other bits are reserved in this register. + */ + __raw_writel(0x2, CSMSADRCFG); + register_syscore_ops(&smemc_syscore_ops); + } return 0; } -- GitLab From cae53e2a9a03e53152fdd331067923f7d65fc72e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 8 Jan 2013 21:58:31 +0000 Subject: [PATCH 1725/1799] ARM: samsung: fix assembly syntax for new gas commit 2815774bb38445006074e16251b9ef5123bdc616 upstream. Recent assembler versions complain about extraneous whitespace inside [] brackets. This fixes all of these instances for the samsung platforms. We should backport this to all kernels that might need to be built with new binutils. arch/arm/kernel/entry-armv.S: Assembler messages: arch/arm/kernel/entry-armv.S:214: Error: ARM register expected -- `ldr r2,[ r6,#(0x10)]' arch/arm/kernel/entry-armv.S:214: Error: ARM register expected -- `ldr r0,[ r6,#(0x14)]' arch/arm/kernel/entry-armv.S:430: Error: ARM register expected -- `ldr r2,[ r6,#(0x10)]' arch/arm/kernel/entry-armv.S:430: Error: ARM register expected -- `ldr r0,[ r6,#(0x14)]' arch/arm/mach-s3c24xx/sleep-s3c2410.S: Assembler messages: arch/arm/mach-s3c24xx/sleep-s3c2410.S:48: Error: ARM register expected -- `ldr r7,[ r4 ]' arch/arm/mach-s3c24xx/sleep-s3c2410.S:49: Error: ARM register expected -- `ldr r8,[ r5 ]' arch/arm/mach-s3c24xx/sleep-s3c2410.S:50: Error: ARM register expected -- `ldr r9,[ r6 ]' arch/arm/mach-s3c24xx/sleep-s3c2410.S:64: Error: ARM register expected -- `streq r7,[ r4 ]' arch/arm/mach-s3c24xx/sleep-s3c2410.S:65: Error: ARM register expected -- `streq r8,[ r5 ]' arch/arm/mach-s3c24xx/sleep-s3c2410.S:66: Error: ARM register expected -- `streq r9,[ r6 ]' arch/arm/kernel/debug.S: Assembler messages: arch/arm/kernel/debug.S:83: Error: ARM register expected -- `ldr r2,[ r2,#((0x0B0)+(((0x56000000)-(0x50000000))+(0xF6000000+(0x01000000))))-((0)+(((0x56000000)-(0x50000000))+(0xF6000000+(0x01000000))))]' arch/arm/kernel/debug.S:83: Error: ARM register expected -- `ldr r2,[ r3,#(0x18)]' arch/arm/kernel/debug.S:85: Error: ARM register expected -- `ldr r2,[ r2,#((0x0B0)+(((0x56000000)-(0x50000000))+(0xF6000000+(0x01000000))))-((0)+(((0x56000000)-(0x50000000))+(0xF6000000+(0x01000000))))]' arch/arm/kernel/debug.S:85: Error: ARM register expected -- `ldr r2,[ r3,#(0x18)]' arch/arm/mach-s3c24xx/pm-h1940.S: Assembler messages: arch/arm/mach-s3c24xx/pm-h1940.S:33: Error: ARM register expected -- `ldr pc,[ r0,#((0x0B8)+(((0x56000000)-(0x50000000))+(0xF6000000+(0x01000000))))-(((0x56000000)-(0x50000000))+(0xF6000000+(0x01000000)))]' arch/arm/mach-s3c24xx/sleep-s3c2412.S: Assembler messages: arch/arm/mach-s3c24xx/sleep-s3c2412.S:60: Error: ARM register expected -- `ldrne r9,[ r1 ]' arch/arm/mach-s3c24xx/sleep-s3c2412.S:61: Error: ARM register expected -- `strne r9,[ r1 ]' arch/arm/mach-s3c24xx/sleep-s3c2412.S:62: Error: ARM register expected -- `ldrne r9,[ r2 ]' arch/arm/mach-s3c24xx/sleep-s3c2412.S:63: Error: ARM register expected -- `strne r9,[ r2 ]' arch/arm/mach-s3c24xx/sleep-s3c2412.S:64: Error: ARM register expected -- `ldrne r9,[ r3 ]' arch/arm/mach-s3c24xx/sleep-s3c2412.S:65: Error: ARM register expected -- `strne r9,[ r3 ]' arch/arm/kernel/debug.S:83: Error: ARM register expected -- `ldr r2,[ r3,#(0x08)]' arch/arm/kernel/debug.S:83: Error: ARM register expected -- `ldr r2,[ r3,#(0x18)]' arch/arm/kernel/debug.S:83: Error: ARM register expected -- `ldr r2,[ r3,#(0x10)]' arch/arm/kernel/debug.S:85: Error: ARM register expected -- `ldr r2,[ r3,#(0x08)]' arch/arm/kernel/debug.S:85: Error: ARM register expected -- `ldr r2,[ r3,#(0x18)]' arch/arm/kernel/debug.S:85: Error: ARM register expected -- `ldr r2,[ r3,#(0x10)]' Signed-off-by: Arnd Bergmann Acked-by: Kukjin Kim Cc: Ben Dooks Signed-off-by: Greg Kroah-Hartman --- .../mach-s3c24xx/include/mach/debug-macro.S | 12 ++++++------ .../mach-s3c24xx/include/mach/entry-macro.S | 4 ++-- arch/arm/mach-s3c24xx/pm-h1940.S | 2 +- arch/arm/mach-s3c24xx/sleep-s3c2410.S | 12 ++++++------ arch/arm/mach-s3c24xx/sleep-s3c2412.S | 12 ++++++------ .../plat-samsung/include/plat/debug-macro.S | 18 +++++++++--------- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/arch/arm/mach-s3c24xx/include/mach/debug-macro.S b/arch/arm/mach-s3c24xx/include/mach/debug-macro.S index 4135de87d1f7..13ed33c69113 100644 --- a/arch/arm/mach-s3c24xx/include/mach/debug-macro.S +++ b/arch/arm/mach-s3c24xx/include/mach/debug-macro.S @@ -40,17 +40,17 @@ addeq \rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART) addne \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART) bic \rd, \rd, #0xff000 - ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ] + ldr \rd, [\rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0)] and \rd, \rd, #0x00ff0000 teq \rd, #0x00440000 @ is it 2440? 1004: - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] moveq \rd, \rd, lsr #SHIFT_2440TXF tst \rd, #S3C2410_UFSTAT_TXFULL .endm .macro fifo_full_s3c2410 rd, rx - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] tst \rd, #S3C2410_UFSTAT_TXFULL .endm @@ -68,18 +68,18 @@ addeq \rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART) addne \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART) bic \rd, \rd, #0xff000 - ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ] + ldr \rd, [\rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0)] and \rd, \rd, #0x00ff0000 teq \rd, #0x00440000 @ is it 2440? 10000: - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] andne \rd, \rd, #S3C2410_UFSTAT_TXMASK andeq \rd, \rd, #S3C2440_UFSTAT_TXMASK .endm .macro fifo_level_s3c2410 rd, rx - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] and \rd, \rd, #S3C2410_UFSTAT_TXMASK .endm diff --git a/arch/arm/mach-s3c24xx/include/mach/entry-macro.S b/arch/arm/mach-s3c24xx/include/mach/entry-macro.S index 7615a14773fa..6a21beeba1da 100644 --- a/arch/arm/mach-s3c24xx/include/mach/entry-macro.S +++ b/arch/arm/mach-s3c24xx/include/mach/entry-macro.S @@ -31,10 +31,10 @@ @@ try the interrupt offset register, since it is there - ldr \irqstat, [ \base, #INTPND ] + ldr \irqstat, [\base, #INTPND ] teq \irqstat, #0 beq 1002f - ldr \irqnr, [ \base, #INTOFFSET ] + ldr \irqnr, [\base, #INTOFFSET ] mov \tmp, #1 tst \irqstat, \tmp, lsl \irqnr bne 1001f diff --git a/arch/arm/mach-s3c24xx/pm-h1940.S b/arch/arm/mach-s3c24xx/pm-h1940.S index c93bf2db9f4d..6183a688012b 100644 --- a/arch/arm/mach-s3c24xx/pm-h1940.S +++ b/arch/arm/mach-s3c24xx/pm-h1940.S @@ -30,4 +30,4 @@ h1940_pm_return: mov r0, #S3C2410_PA_GPIO - ldr pc, [ r0, #S3C2410_GSTATUS3 - S3C24XX_VA_GPIO ] + ldr pc, [r0, #S3C2410_GSTATUS3 - S3C24XX_VA_GPIO] diff --git a/arch/arm/mach-s3c24xx/sleep-s3c2410.S b/arch/arm/mach-s3c24xx/sleep-s3c2410.S index dd5b6388a5a5..65200ae72c90 100644 --- a/arch/arm/mach-s3c24xx/sleep-s3c2410.S +++ b/arch/arm/mach-s3c24xx/sleep-s3c2410.S @@ -45,9 +45,9 @@ ENTRY(s3c2410_cpu_suspend) ldr r4, =S3C2410_REFRESH ldr r5, =S3C24XX_MISCCR ldr r6, =S3C2410_CLKCON - ldr r7, [ r4 ] @ get REFRESH (and ensure in TLB) - ldr r8, [ r5 ] @ get MISCCR (and ensure in TLB) - ldr r9, [ r6 ] @ get CLKCON (and ensure in TLB) + ldr r7, [r4] @ get REFRESH (and ensure in TLB) + ldr r8, [r5] @ get MISCCR (and ensure in TLB) + ldr r9, [r6] @ get CLKCON (and ensure in TLB) orr r7, r7, #S3C2410_REFRESH_SELF @ SDRAM sleep command orr r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals @@ -61,8 +61,8 @@ ENTRY(s3c2410_cpu_suspend) @@ align next bit of code to cache line .align 5 s3c2410_do_sleep: - streq r7, [ r4 ] @ SDRAM sleep command - streq r8, [ r5 ] @ SDRAM power-down config - streq r9, [ r6 ] @ CPU sleep + streq r7, [r4] @ SDRAM sleep command + streq r8, [r5] @ SDRAM power-down config + streq r9, [r6] @ CPU sleep 1: beq 1b mov pc, r14 diff --git a/arch/arm/mach-s3c24xx/sleep-s3c2412.S b/arch/arm/mach-s3c24xx/sleep-s3c2412.S index c82418ed714d..5adaceb7da13 100644 --- a/arch/arm/mach-s3c24xx/sleep-s3c2412.S +++ b/arch/arm/mach-s3c24xx/sleep-s3c2412.S @@ -57,12 +57,12 @@ s3c2412_sleep_enter1: * retry, as simply returning causes the system to lock. */ - ldrne r9, [ r1 ] - strne r9, [ r1 ] - ldrne r9, [ r2 ] - strne r9, [ r2 ] - ldrne r9, [ r3 ] - strne r9, [ r3 ] + ldrne r9, [r1] + strne r9, [r1] + ldrne r9, [r2] + strne r9, [r2] + ldrne r9, [r3] + strne r9, [r3] bne s3c2412_sleep_enter1 mov pc, r14 diff --git a/arch/arm/plat-samsung/include/plat/debug-macro.S b/arch/arm/plat-samsung/include/plat/debug-macro.S index 207e275362a8..f3a9cff6d5d4 100644 --- a/arch/arm/plat-samsung/include/plat/debug-macro.S +++ b/arch/arm/plat-samsung/include/plat/debug-macro.S @@ -14,12 +14,12 @@ /* The S5PV210/S5PC110 implementations are as belows. */ .macro fifo_level_s5pv210 rd, rx - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] and \rd, \rd, #S5PV210_UFSTAT_TXMASK .endm .macro fifo_full_s5pv210 rd, rx - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] tst \rd, #S5PV210_UFSTAT_TXFULL .endm @@ -27,7 +27,7 @@ * most widely re-used */ .macro fifo_level_s3c2440 rd, rx - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] and \rd, \rd, #S3C2440_UFSTAT_TXMASK .endm @@ -36,7 +36,7 @@ #endif .macro fifo_full_s3c2440 rd, rx - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] tst \rd, #S3C2440_UFSTAT_TXFULL .endm @@ -45,11 +45,11 @@ #endif .macro senduart,rd,rx - strb \rd, [\rx, # S3C2410_UTXH ] + strb \rd, [\rx, # S3C2410_UTXH] .endm .macro busyuart, rd, rx - ldr \rd, [ \rx, # S3C2410_UFCON ] + ldr \rd, [\rx, # S3C2410_UFCON] tst \rd, #S3C2410_UFCON_FIFOMODE @ fifo enabled? beq 1001f @ @ FIFO enabled... @@ -60,7 +60,7 @@ 1001: @ busy waiting for non fifo - ldr \rd, [ \rx, # S3C2410_UTRSTAT ] + ldr \rd, [\rx, # S3C2410_UTRSTAT] tst \rd, #S3C2410_UTRSTAT_TXFE beq 1001b @@ -68,7 +68,7 @@ .endm .macro waituart,rd,rx - ldr \rd, [ \rx, # S3C2410_UFCON ] + ldr \rd, [\rx, # S3C2410_UFCON] tst \rd, #S3C2410_UFCON_FIFOMODE @ fifo enabled? beq 1001f @ @ FIFO enabled... @@ -79,7 +79,7 @@ b 1002f 1001: @ idle waiting for non fifo - ldr \rd, [ \rx, # S3C2410_UTRSTAT ] + ldr \rd, [\rx, # S3C2410_UTRSTAT] tst \rd, #S3C2410_UTRSTAT_TXFE beq 1001b -- GitLab From 27c303244ef8049be6fd8088230c7f5e02a522b3 Mon Sep 17 00:00:00 2001 From: Joonsoo Kim Date: Sat, 9 Feb 2013 05:52:45 +0100 Subject: [PATCH 1726/1799] ARM: 7643/1: sched: correct update_sched_clock() commit 7c4e9ced424be4d36df6a3e3825763e97ee97607 upstream. If we want load epoch_cyc and epoch_ns atomically, we should update epoch_cyc_copy first of all. This notify reader that updating is in progress. If we update epoch_cyc first like as current implementation, there is subtle error case. Look at the below example. cyc = 9 ns = 900 cyc_copy = 9 == CASE 1 == write cyc = 10 read cyc = 10 read ns = 900 write ns = 1000 write cyc_copy = 10 read cyc_copy = 10 output = (10, 900) == CASE 2 == read cyc = 9 write cyc = 10 write ns = 1000 read ns = 1000 read cyc_copy = 9 write cyc_copy = 10 output = (9, 1000) If atomic read is ensured, output should be (9, 900) or (10, 1000). But, output in example case are not. So, change updating sequence in order to correct this problem. Signed-off-by: Joonsoo Kim Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/sched_clock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c index 27d186abbc06..6bbf936b8354 100644 --- a/arch/arm/kernel/sched_clock.c +++ b/arch/arm/kernel/sched_clock.c @@ -84,11 +84,11 @@ static void notrace update_sched_clock(void) * detectable in cyc_to_fixed_sched_clock(). */ raw_local_irq_save(flags); - cd.epoch_cyc = cyc; + cd.epoch_cyc_copy = cyc; smp_wmb(); cd.epoch_ns = ns; smp_wmb(); - cd.epoch_cyc_copy = cyc; + cd.epoch_cyc = cyc; raw_local_irq_restore(flags); } -- GitLab From 25c3a0840c99270041487907b6365cb5bfc8a03f Mon Sep 17 00:00:00 2001 From: Phileas Fogg Date: Sat, 23 Feb 2013 00:32:19 +0100 Subject: [PATCH 1727/1799] powerpc/kexec: Disable hard IRQ before kexec commit 8520e443aa56cc157b015205ea53e7b9fc831291 upstream. Disable hard IRQ before kexec a new kernel image. Not doing it can result in corrupted data in the memory segments reserved for the new kernel. Signed-off-by: Phileas Fogg Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/machine_kexec_64.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index d7f609086a99..39833e0b282f 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -162,6 +162,8 @@ static int kexec_all_irq_disabled = 0; static void kexec_smp_down(void *arg) { local_irq_disable(); + hard_irq_disable(); + mb(); /* make sure our irqs are disabled before we say they are */ get_paca()->kexec_state = KEXEC_STATE_IRQS_OFF; while(kexec_all_irq_disabled == 0) @@ -244,6 +246,8 @@ static void kexec_prepare_cpus(void) wake_offline_cpus(); smp_call_function(kexec_smp_down, NULL, /* wait */0); local_irq_disable(); + hard_irq_disable(); + mb(); /* make sure IRQs are disabled before we say they are */ get_paca()->kexec_state = KEXEC_STATE_IRQS_OFF; @@ -281,6 +285,7 @@ static void kexec_prepare_cpus(void) if (ppc_md.kexec_cpu_down) ppc_md.kexec_cpu_down(0, 0); local_irq_disable(); + hard_irq_disable(); } #endif /* SMP */ -- GitLab From 49e8ae95b16fbc66b630b50ad3a18273b9342a06 Mon Sep 17 00:00:00 2001 From: John David Anglin Date: Mon, 14 Jan 2013 19:45:00 -0500 Subject: [PATCH 1728/1799] Purge existing TLB entries in set_pte_at and ptep_set_wrprotect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7139bc1579901b53db7e898789e916ee2fb52d78 upstream. This patch goes a long way toward fixing the minifail bug, and it  significantly improves the stability of SMP machines such as the rp3440.  When write  protecting a page for COW, we need to purge the existing translation.  Otherwise, the COW break doesn't occur as expected because the TLB may still have a stale entry which allows writes. [jejb: fix up checkpatch errors] Signed-off-by: John David Anglin Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- arch/parisc/include/asm/pgtable.h | 13 ++++++++++--- arch/parisc/kernel/cache.c | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index ee99f2339356..7df49fad29f9 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h @@ -12,11 +12,10 @@ #include #include +#include #include #include -struct vm_area_struct; - /* * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel * memory. For the return value to be meaningful, ADDR must be >= @@ -40,7 +39,14 @@ struct vm_area_struct; do{ \ *(pteptr) = (pteval); \ } while(0) -#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) + +extern void purge_tlb_entries(struct mm_struct *, unsigned long); + +#define set_pte_at(mm, addr, ptep, pteval) \ + do { \ + set_pte(ptep, pteval); \ + purge_tlb_entries(mm, addr); \ + } while (0) #endif /* !__ASSEMBLY__ */ @@ -466,6 +472,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, old = pte_val(*ptep); new = pte_val(pte_wrprotect(__pte (old))); } while (cmpxchg((unsigned long *) ptep, old, new) != old); + purge_tlb_entries(mm, addr); #else pte_t old_pte = *ptep; set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 9d181890a7e3..fa2146341dab 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -420,6 +420,24 @@ void kunmap_parisc(void *addr) EXPORT_SYMBOL(kunmap_parisc); #endif +void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) +{ + unsigned long flags; + + /* Note: purge_tlb_entries can be called at startup with + no context. */ + + /* Disable preemption while we play with %sr1. */ + preempt_disable(); + mtsp(mm->context, 1); + purge_tlb_start(flags); + pdtlb(addr); + pitlb(addr); + purge_tlb_end(flags); + preempt_enable(); +} +EXPORT_SYMBOL(purge_tlb_entries); + void __flush_tlb_range(unsigned long sid, unsigned long start, unsigned long end) { -- GitLab From aa3fc3566478493f635d265731d81a3defcef98d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 16 Dec 2012 22:00:50 +0100 Subject: [PATCH 1729/1799] pcmcia/vrc4171: Add missing spinlock init commit 811af9723859884f2f771f3174f3ddedab7c53b5 upstream. It doesn't seem this spinlock was properly initialized. This bug was introduced by commit 7a410e8d4d97457c8c381e2de9cdc7bd3306badc. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/pcmcia/vrc4171_card.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index 86e4a1a3c642..6bb02ab5dd9a 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c @@ -246,6 +246,7 @@ static int pccard_init(struct pcmcia_socket *sock) socket = &vrc4171_sockets[slot]; socket->csc_irq = search_nonuse_irq(); socket->io_irq = search_nonuse_irq(); + spin_lock_init(&socket->lock); return 0; } -- GitLab From 0bbdba111a75875890290150333c07f2d79b160a Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Thu, 17 Jan 2013 21:28:37 +0100 Subject: [PATCH 1730/1799] drivers/video: fsl-diu-fb: fix pixel formats for 24 and 16 bpp commit 5d3cc311a76073f6e0a27c0752f7e41f69e95ea7 upstream. Framebuffer colors for 24 and 16 bpp are currently wrong. The order of the color component arguments in the MAKE_PF() is not natural and causes some confusion. The generated pixel format values for 24 and 16 bpp depths do not much the values in the comments. Fix the macro arguments to be in the natural RGB order and adjust the arguments for all depths to generate correct pixel format values (equal to the values mentioned in the comments). Signed-off-by: Anatolij Gustschin Cc: Timur Tabi Acked-by: Timur Tabi Signed-off-by: Greg Kroah-Hartman --- drivers/video/fsl-diu-fb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 6af3f16754f0..d02a538518c2 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -923,7 +923,7 @@ static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel) #define PF_COMP_0_MASK 0x0000000F #define PF_COMP_0_SHIFT 0 -#define MAKE_PF(alpha, red, blue, green, size, c0, c1, c2, c3) \ +#define MAKE_PF(alpha, red, green, blue, size, c0, c1, c2, c3) \ cpu_to_le32(PF_BYTE_F | (alpha << PF_ALPHA_C_SHIFT) | \ (blue << PF_BLUE_C_SHIFT) | (green << PF_GREEN_C_SHIFT) | \ (red << PF_RED_C_SHIFT) | (c3 << PF_COMP_3_SHIFT) | \ @@ -933,10 +933,10 @@ static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel) switch (bits_per_pixel) { case 32: /* 0x88883316 */ - return MAKE_PF(3, 2, 0, 1, 3, 8, 8, 8, 8); + return MAKE_PF(3, 2, 1, 0, 3, 8, 8, 8, 8); case 24: /* 0x88082219 */ - return MAKE_PF(4, 0, 1, 2, 2, 0, 8, 8, 8); + return MAKE_PF(4, 0, 1, 2, 2, 8, 8, 8, 0); case 16: /* 0x65053118 */ return MAKE_PF(4, 2, 1, 0, 1, 5, 6, 5, 0); -- GitLab From 62a3dcc78d04dcd84276eaa7a40dec1066054532 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 24 Jan 2013 16:12:41 +1000 Subject: [PATCH 1731/1799] fbcon: don't lose the console font across generic->chip driver switch commit ae1287865f5361fa138d4d3b1b6277908b54eac9 upstream. If grub2 loads efifb/vesafb, then when systemd starts it can set the console font on that framebuffer device, however when we then load the native KMS driver, the first thing it does is tear down the generic framebuffer driver. The thing is the generic code is doing the right thing, it frees the font because otherwise it would leak memory. However we can assume that if you are removing the generic firmware driver (vesa/efi/offb), that a new driver *should* be loading soon after, so we effectively leak the font. However the old code left a dangling pointer in vc->vc_font.data and we can now reuse that dangling pointer to load the font into the new driver, now that we aren't freeing it. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=892340 Signed-off-by: Dave Airlie Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/video/console/fbcon.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 88e92041d8f0..bdcd34d842dc 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -990,7 +990,7 @@ static const char *fbcon_startup(void) } /* Setup default font */ - if (!p->fontdata) { + if (!p->fontdata && !vc->vc_font.data) { if (!fontname[0] || !(font = find_font(fontname))) font = get_default_font(info->var.xres, info->var.yres, @@ -1000,6 +1000,8 @@ static const char *fbcon_startup(void) vc->vc_font.height = font->height; vc->vc_font.data = (void *)(p->fontdata = font->data); vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */ + } else { + p->fontdata = vc->vc_font.data; } cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); @@ -1159,9 +1161,9 @@ static void fbcon_init(struct vc_data *vc, int init) ops->p = &fb_display[fg_console]; } -static void fbcon_free_font(struct display *p) +static void fbcon_free_font(struct display *p, bool freefont) { - if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) + if (freefont && p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); p->fontdata = NULL; p->userfont = 0; @@ -1173,8 +1175,8 @@ static void fbcon_deinit(struct vc_data *vc) struct fb_info *info; struct fbcon_ops *ops; int idx; + bool free_font = true; - fbcon_free_font(p); idx = con2fb_map[vc->vc_num]; if (idx == -1) @@ -1185,6 +1187,8 @@ static void fbcon_deinit(struct vc_data *vc) if (!info) goto finished; + if (info->flags & FBINFO_MISC_FIRMWARE) + free_font = false; ops = info->fbcon_par; if (!ops) @@ -1196,6 +1200,8 @@ static void fbcon_deinit(struct vc_data *vc) ops->flags &= ~FBCON_FLAGS_INIT; finished: + fbcon_free_font(p, free_font); + if (!con_is_bound(&fb_con)) fbcon_exit(); -- GitLab From c30b55c385288be48f7accd16a6929ad4d983311 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 25 Jan 2013 10:28:15 +1000 Subject: [PATCH 1732/1799] fb: rework locking to fix lock ordering on takeover commit 50e244cc793d511b86adea24972f3a7264cae114 upstream. Adjust the console layer to allow a take over call where the caller already holds the locks. Make the fb layer lock in order. This is partly a band aid, the fb layer is terminally confused about the locking rules it uses for its notifiers it seems. [akpm@linux-foundation.org: remove stray non-ascii char, tidy comment] [akpm@linux-foundation.org: export do_take_over_console()] [airlied: cleanup another non-ascii char] Signed-off-by: Alan Cox Cc: Florian Tobias Schandinat Cc: Stephen Rothwell Cc: Jiri Kosina Tested-by: Sedat Dilek Reviewed-by: Daniel Vetter Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 93 ++++++++++++++++++++++++++--------- drivers/video/console/fbcon.c | 29 ++++++++++- drivers/video/fbmem.c | 5 +- drivers/video/fbsysfs.c | 3 ++ include/linux/console.h | 1 + 5 files changed, 104 insertions(+), 27 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 068abe1524a1..e948f5baa5c2 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -3017,7 +3017,7 @@ int __init vty_init(const struct file_operations *console_fops) static struct class *vtconsole_class; -static int bind_con_driver(const struct consw *csw, int first, int last, +static int do_bind_con_driver(const struct consw *csw, int first, int last, int deflt) { struct module *owner = csw->owner; @@ -3028,7 +3028,7 @@ static int bind_con_driver(const struct consw *csw, int first, int last, if (!try_module_get(owner)) return -ENODEV; - console_lock(); + WARN_CONSOLE_UNLOCKED(); /* check if driver is registered */ for (i = 0; i < MAX_NR_CON_DRIVER; i++) { @@ -3113,11 +3113,22 @@ static int bind_con_driver(const struct consw *csw, int first, int last, retval = 0; err: - console_unlock(); module_put(owner); return retval; }; + +static int bind_con_driver(const struct consw *csw, int first, int last, + int deflt) +{ + int ret; + + console_lock(); + ret = do_bind_con_driver(csw, first, last, deflt); + console_unlock(); + return ret; +} + #ifdef CONFIG_VT_HW_CONSOLE_BINDING static int con_is_graphics(const struct consw *csw, int first, int last) { @@ -3229,9 +3240,9 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) if (!con_is_bound(csw)) con_driver->flag &= ~CON_DRIVER_FLAG_INIT; - console_unlock(); /* ignore return value, binding should not fail */ - bind_con_driver(defcsw, first, last, deflt); + do_bind_con_driver(defcsw, first, last, deflt); + console_unlock(); err: module_put(owner); return retval; @@ -3522,28 +3533,18 @@ int con_debug_leave(void) } EXPORT_SYMBOL_GPL(con_debug_leave); -/** - * register_con_driver - register console driver to console layer - * @csw: console driver - * @first: the first console to take over, minimum value is 0 - * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1 - * - * DESCRIPTION: This function registers a console driver which can later - * bind to a range of consoles specified by @first and @last. It will - * also initialize the console driver by calling con_startup(). - */ -int register_con_driver(const struct consw *csw, int first, int last) +static int do_register_con_driver(const struct consw *csw, int first, int last) { struct module *owner = csw->owner; struct con_driver *con_driver; const char *desc; int i, retval = 0; + WARN_CONSOLE_UNLOCKED(); + if (!try_module_get(owner)) return -ENODEV; - console_lock(); - for (i = 0; i < MAX_NR_CON_DRIVER; i++) { con_driver = ®istered_con_driver[i]; @@ -3596,10 +3597,29 @@ int register_con_driver(const struct consw *csw, int first, int last) } err: - console_unlock(); module_put(owner); return retval; } + +/** + * register_con_driver - register console driver to console layer + * @csw: console driver + * @first: the first console to take over, minimum value is 0 + * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1 + * + * DESCRIPTION: This function registers a console driver which can later + * bind to a range of consoles specified by @first and @last. It will + * also initialize the console driver by calling con_startup(). + */ +int register_con_driver(const struct consw *csw, int first, int last) +{ + int retval; + + console_lock(); + retval = do_register_con_driver(csw, first, last); + console_unlock(); + return retval; +} EXPORT_SYMBOL(register_con_driver); /** @@ -3653,17 +3673,44 @@ EXPORT_SYMBOL(unregister_con_driver); * when a driver wants to take over some existing consoles * and become default driver for newly opened ones. * - * take_over_console is basically a register followed by unbind + * take_over_console is basically a register followed by unbind + */ +int do_take_over_console(const struct consw *csw, int first, int last, int deflt) +{ + int err; + + err = do_register_con_driver(csw, first, last); + /* + * If we get an busy error we still want to bind the console driver + * and return success, as we may have unbound the console driver + * but not unregistered it. + */ + if (err == -EBUSY) + err = 0; + if (!err) + do_bind_con_driver(csw, first, last, deflt); + + return err; +} +EXPORT_SYMBOL_GPL(do_take_over_console); + +/* + * If we support more console drivers, this function is used + * when a driver wants to take over some existing consoles + * and become default driver for newly opened ones. + * + * take_over_console is basically a register followed by unbind */ int take_over_console(const struct consw *csw, int first, int last, int deflt) { int err; err = register_con_driver(csw, first, last); - /* if we get an busy error we still want to bind the console driver + /* + * If we get an busy error we still want to bind the console driver * and return success, as we may have unbound the console driver -  * but not unregistered it. - */ + * but not unregistered it. + */ if (err == -EBUSY) err = 0; if (!err) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index bdcd34d842dc..7ccec556373a 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -529,6 +529,33 @@ static int search_for_mapped_con(void) return retval; } +static int do_fbcon_takeover(int show_logo) +{ + int err, i; + + if (!num_registered_fb) + return -ENODEV; + + if (!show_logo) + logo_shown = FBCON_LOGO_DONTSHOW; + + for (i = first_fb_vc; i <= last_fb_vc; i++) + con2fb_map[i] = info_idx; + + err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc, + fbcon_is_default); + + if (err) { + for (i = first_fb_vc; i <= last_fb_vc; i++) + con2fb_map[i] = -1; + info_idx = -1; + } else { + fbcon_has_console_bind = 1; + } + + return err; +} + static int fbcon_takeover(int show_logo) { int err, i; @@ -3121,7 +3148,7 @@ static int fbcon_fb_registered(struct fb_info *info) } if (info_idx != -1) - ret = fbcon_takeover(1); + ret = do_fbcon_takeover(1); } else { for (i = first_fb_vc; i <= last_fb_vc; i++) { if (con2fb_map_boot[i] == idx) diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index c6ce416ab587..f04ccf7d86e9 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1642,7 +1642,9 @@ static int do_register_framebuffer(struct fb_info *fb_info) event.info = fb_info; if (!lock_fb_info(fb_info)) return -ENODEV; + console_lock(); fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); + console_unlock(); unlock_fb_info(fb_info); return 0; } @@ -1845,11 +1847,8 @@ int fb_new_modelist(struct fb_info *info) err = 1; if (!list_empty(&info->modelist)) { - if (!lock_fb_info(info)) - return -ENODEV; event.info = info; err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event); - unlock_fb_info(info); } return err; diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 67afa9c2289d..303fb9f35b2a 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -175,6 +175,8 @@ static ssize_t store_modes(struct device *device, if (i * sizeof(struct fb_videomode) != count) return -EINVAL; + if (!lock_fb_info(fb_info)) + return -ENODEV; console_lock(); list_splice(&fb_info->modelist, &old_list); fb_videomode_to_modelist((const struct fb_videomode *)buf, i, @@ -186,6 +188,7 @@ static ssize_t store_modes(struct device *device, fb_destroy_modelist(&old_list); console_unlock(); + unlock_fb_info(fb_info); return 0; } diff --git a/include/linux/console.h b/include/linux/console.h index 7201ce4280ca..e8ea7d7371bf 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -78,6 +78,7 @@ int con_is_bound(const struct consw *csw); int register_con_driver(const struct consw *csw, int first, int last); int unregister_con_driver(const struct consw *csw); int take_over_console(const struct consw *sw, int first, int last, int deflt); +int do_take_over_console(const struct consw *sw, int first, int last, int deflt); void give_up_console(const struct consw *sw); #ifdef CONFIG_HW_CONSOLE int con_debug_enter(struct vc_data *vc); -- GitLab From f515e1d59602f8eafaad39b6842bd823ad34654e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 25 Jan 2013 10:28:18 +1000 Subject: [PATCH 1733/1799] fb: Yet another band-aid for fixing lockdep mess commit e93a9a868792ad71cdd09d75e5a02d8067473c4e upstream. I've still got lockdep warnings even after Alan's patch, and it seems that yet more band aids are required to paper over similar paths for unbind_con_driver() and unregister_con_driver(). After this hack, lockdep warnings are finally gone. Signed-off-by: Takashi Iwai Cc: Alan Cox Cc: Florian Tobias Schandinat Cc: Jiri Kosina Tested-by: Sedat Dilek Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 43 +++++++++++++++++++++++------------ drivers/video/console/fbcon.c | 4 ++-- drivers/video/fbmem.c | 4 ++++ include/linux/console.h | 1 + include/linux/vt_kern.h | 2 ++ 5 files changed, 37 insertions(+), 17 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index e948f5baa5c2..268294c71c11 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -3164,6 +3164,18 @@ static int con_is_graphics(const struct consw *csw, int first, int last) * or 0 on success. */ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) +{ + int retval; + + console_lock(); + retval = do_unbind_con_driver(csw, first, last, deflt); + console_unlock(); + return retval; +} +EXPORT_SYMBOL(unbind_con_driver); + +/* unlocked version of unbind_con_driver() */ +int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt) { struct module *owner = csw->owner; const struct consw *defcsw = NULL; @@ -3173,7 +3185,7 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) if (!try_module_get(owner)) return -ENODEV; - console_lock(); + WARN_CONSOLE_UNLOCKED(); /* check if driver is registered and if it is unbindable */ for (i = 0; i < MAX_NR_CON_DRIVER; i++) { @@ -3186,10 +3198,8 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) } } - if (retval) { - console_unlock(); + if (retval) goto err; - } retval = -ENODEV; @@ -3205,15 +3215,11 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) } } - if (retval) { - console_unlock(); + if (retval) goto err; - } - if (!con_is_bound(csw)) { - console_unlock(); + if (!con_is_bound(csw)) goto err; - } first = max(first, con_driver->first); last = min(last, con_driver->last); @@ -3242,13 +3248,12 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) /* ignore return value, binding should not fail */ do_bind_con_driver(defcsw, first, last, deflt); - console_unlock(); err: module_put(owner); return retval; } -EXPORT_SYMBOL(unbind_con_driver); +EXPORT_SYMBOL_GPL(do_unbind_con_driver); static int vt_bind(struct con_driver *con) { @@ -3635,9 +3640,18 @@ EXPORT_SYMBOL(register_con_driver); */ int unregister_con_driver(const struct consw *csw) { - int i, retval = -ENODEV; + int retval; console_lock(); + retval = do_unregister_con_driver(csw); + console_unlock(); + return retval; +} +EXPORT_SYMBOL(unregister_con_driver); + +int do_unregister_con_driver(const struct consw *csw) +{ + int i, retval = -ENODEV; /* cannot unregister a bound driver */ if (con_is_bound(csw)) @@ -3663,10 +3677,9 @@ int unregister_con_driver(const struct consw *csw) } } err: - console_unlock(); return retval; } -EXPORT_SYMBOL(unregister_con_driver); +EXPORT_SYMBOL_GPL(do_unregister_con_driver); /* * If we support more console drivers, this function is used diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 7ccec556373a..5bf163e03840 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -3010,7 +3010,7 @@ static int fbcon_unbind(void) { int ret; - ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc, + ret = do_unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default); if (!ret) @@ -3083,7 +3083,7 @@ static int fbcon_fb_unregistered(struct fb_info *info) primary_device = -1; if (!num_registered_fb) - unregister_con_driver(&fb_con); + do_unregister_con_driver(&fb_con); return 0; } diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index f04ccf7d86e9..90f13152d213 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1660,8 +1660,10 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) if (!lock_fb_info(fb_info)) return -ENODEV; + console_lock(); event.info = fb_info; ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); + console_unlock(); unlock_fb_info(fb_info); if (ret) @@ -1676,7 +1678,9 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) num_registered_fb--; fb_cleanup_device(fb_info); event.info = fb_info; + console_lock(); fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); + console_unlock(); /* this may free fb info */ put_fb_info(fb_info); diff --git a/include/linux/console.h b/include/linux/console.h index e8ea7d7371bf..f59e9428d06b 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -77,6 +77,7 @@ extern const struct consw prom_con; /* SPARC PROM console */ int con_is_bound(const struct consw *csw); int register_con_driver(const struct consw *csw, int first, int last); int unregister_con_driver(const struct consw *csw); +int do_unregister_con_driver(const struct consw *csw); int take_over_console(const struct consw *sw, int first, int last, int deflt); int do_take_over_console(const struct consw *sw, int first, int last, int deflt); void give_up_console(const struct consw *sw); diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index 49e39d4396d0..57eeb1454558 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -132,6 +132,8 @@ void vt_event_post(unsigned int event, unsigned int old, unsigned int new); int vt_waitactive(int n); void change_console(struct vc_data *new_vc); void reset_vc(struct vc_data *vc); +extern int do_unbind_con_driver(const struct consw *csw, int first, int last, + int deflt); extern int unbind_con_driver(const struct consw *csw, int first, int last, int deflt); int vty_init(const struct file_operations *console_fops); -- GitLab From 6a924a76039689fd260ee311b85fb2202bcd4910 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 15 Jan 2013 23:30:27 +0800 Subject: [PATCH 1734/1799] mmc: sdhci-esdhc-imx: fix host version read commit ef4d0888bb7e1b963880f086575081c3d39cad2d upstream. When commit 95a2482 (mmc: sdhci-esdhc-imx: add basic imx6q usdhc support) works around host version issue on imx6q, it gets the register address fixup "reg ^= 2" lost for imx25/35/51/53 esdhc. Thus, the controller version on these SoCs is wrongly identified as v1 while it's actually v2. Add the address fixup back and take a different approach to correct imx6q host version, so that the host version read gets back to work for all SoCs. Signed-off-by: Shawn Guo Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sdhci-esdhc-imx.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 8abdaf6697a8..be46052228b7 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -232,15 +232,18 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) static u16 esdhc_readw_le(struct sdhci_host *host, int reg) { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host->priv; + if (unlikely(reg == SDHCI_HOST_VERSION)) { - u16 val = readw(host->ioaddr + (reg ^ 2)); - /* - * uSDHC supports SDHCI v3.0, but it's encoded as value - * 0x3 in host controller version register, which violates - * SDHCI_SPEC_300 definition. Work it around here. - */ - if ((val & SDHCI_SPEC_VER_MASK) == 3) - return --val; + reg ^= 2; + if (is_imx6q_usdhc(imx_data)) { + /* + * The usdhc register returns a wrong host version. + * Correct it here. + */ + return SDHCI_SPEC_300; + } } return readw(host->ioaddr + reg); -- GitLab From a9115fba99247ad51211beb3ffd23b6553c80ee9 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Mon, 18 Feb 2013 01:47:15 +0100 Subject: [PATCH 1735/1799] HID: wiimote: fix nunchuck button parser commit 89bdd0c6f38ccf0de43d5a36ede384a730f3394e upstream. The buttons of the Wii Remote Nunchuck extension are actually active low. Fix the parser to forward the inverted values. The comment in the function always said "0 == pressed" but the implementation was wrong from the beginning. Reported-by: Victor Quicksilver Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-wiimote-ext.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c index aa958706c0e5..9e5728502017 100644 --- a/drivers/hid/hid-wiimote-ext.c +++ b/drivers/hid/hid-wiimote-ext.c @@ -378,14 +378,14 @@ static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload) if (ext->motionp) { input_report_key(ext->input, - wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x04)); + wiiext_keymap[WIIEXT_KEY_Z], !(payload[5] & 0x04)); input_report_key(ext->input, - wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x08)); + wiiext_keymap[WIIEXT_KEY_C], !(payload[5] & 0x08)); } else { input_report_key(ext->input, - wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x01)); + wiiext_keymap[WIIEXT_KEY_Z], !(payload[5] & 0x01)); input_report_key(ext->input, - wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x02)); + wiiext_keymap[WIIEXT_KEY_C], !(payload[5] & 0x02)); } input_sync(ext->input); -- GitLab From 6e95f970d1cb6801b5f26d2c167fb1e0ad6c5dba Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 11 Feb 2013 08:22:22 +0000 Subject: [PATCH 1736/1799] bridge: set priority of STP packets [ Upstream commit 547b4e718115eea74087e28d7fa70aec619200db ] Spanning Tree Protocol packets should have always been marked as control packets, this causes them to get queued in the high prirority FIFO. As Radia Perlman mentioned in her LCA talk, STP dies if bridge gets overloaded and can't communicate. This is a long-standing bug back to the first versions of Linux bridge. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bridge/br_stp_bpdu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index e16aade51ae0..718cbe8ad42b 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,7 @@ static void br_send_bpdu(struct net_bridge_port *p, skb->dev = p->dev; skb->protocol = htons(ETH_P_802_2); + skb->priority = TC_PRIO_CONTROL; skb_reserve(skb, LLC_RESERVE); memcpy(__skb_put(skb, length), data, length); -- GitLab From b5428e471b91192a2438d04c1d2ff2b3d4708366 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 12 Feb 2013 06:16:53 +0000 Subject: [PATCH 1737/1799] net: fix infinite loop in __skb_recv_datagram() [ Upstream commit 77c1090f94d1b0b5186fb13a1b71b47b1343f87f ] Tommi was fuzzing with trinity and reported the following problem : commit 3f518bf745 (datagram: Add offset argument to __skb_recv_datagram) missed that a raw socket receive queue can contain skbs with no payload. We can loop in __skb_recv_datagram() with MSG_PEEK mode, because wait_for_packet() is not prepared to skip these skbs. [ 83.541011] INFO: rcu_sched detected stalls on CPUs/tasks: {} (detected by 0, t=26002 jiffies, g=27673, c=27672, q=75) [ 83.541011] INFO: Stall ended before state dump start [ 108.067010] BUG: soft lockup - CPU#0 stuck for 22s! [trinity-child31:2847] ... [ 108.067010] Call Trace: [ 108.067010] [] __skb_recv_datagram+0x1a3/0x3b0 [ 108.067010] [] skb_recv_datagram+0x2d/0x30 [ 108.067010] [] rawv6_recvmsg+0xad/0x240 [ 108.067010] [] sock_common_recvmsg+0x34/0x50 [ 108.067010] [] sock_recvmsg+0xbc/0xf0 [ 108.067010] [] sys_recvfrom+0xde/0x150 [ 108.067010] [] system_call_fastpath+0x16/0x1b Reported-by: Tommi Rantala Tested-by: Tommi Rantala Signed-off-by: Eric Dumazet Cc: Pavel Emelyanov Acked-by: Pavel Emelyanov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/datagram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/datagram.c b/net/core/datagram.c index e4fbfd6e2bd4..da7e0c867cc0 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -187,7 +187,7 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, skb_queue_walk(queue, skb) { *peeked = skb->peeked; if (flags & MSG_PEEK) { - if (*off >= skb->len) { + if (*off >= skb->len && skb->len) { *off -= skb->len; continue; } -- GitLab From 320c1509197bce83d2ebb45d4cc5f9b4d91c05dc Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Thu, 14 Feb 2013 03:18:57 +0000 Subject: [PATCH 1738/1799] xen-netback: correctly return errors from netbk_count_requests() [ Upstream commit 35876b5ffc154c357476b2c3bdab10feaf4bd8f0 ] netbk_count_requests() could detect an error, call netbk_fatal_tx_error() but return 0. The vif may then be used afterwards (e.g., in a call to netbk_tx_error(). Since netbk_fatal_tx_error() could set vif->refcnt to 1, the vif may be freed immediately after the call to netbk_fatal_tx_error() (e.g., if the vif is also removed). Netback thread Xenwatch thread ------------------------------------------- netbk_fatal_tx_err() netback_remove() xenvif_disconnect() ... free_netdev() netbk_tx_err() Oops! Signed-off-by: Wei Liu Signed-off-by: Jan Beulich Signed-off-by: David Vrabel Reported-by: Christopher S. Aker Acked-by: Ian Campbell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/xen-netback/netback.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index e2793d06e5d1..2bdf798b3d9c 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -883,13 +883,13 @@ static int netbk_count_requests(struct xenvif *vif, if (frags >= work_to_do) { netdev_err(vif->dev, "Need more frags\n"); netbk_fatal_tx_err(vif); - return -frags; + return -ENODATA; } if (unlikely(frags >= MAX_SKB_FRAGS)) { netdev_err(vif->dev, "Too many frags\n"); netbk_fatal_tx_err(vif); - return -frags; + return -E2BIG; } memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags), @@ -897,7 +897,7 @@ static int netbk_count_requests(struct xenvif *vif, if (txp->size > first->size) { netdev_err(vif->dev, "Frag is bigger than frame.\n"); netbk_fatal_tx_err(vif); - return -frags; + return -EIO; } first->size -= txp->size; @@ -907,7 +907,7 @@ static int netbk_count_requests(struct xenvif *vif, netdev_err(vif->dev, "txp->offset: %x, size: %u\n", txp->offset, txp->size); netbk_fatal_tx_err(vif); - return -frags; + return -EINVAL; } } while ((txp++)->flags & XEN_NETTXF_more_data); return frags; -- GitLab From 29b3bb0be43fea0a49e5235894e1dcbc0ac299dc Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Thu, 14 Feb 2013 03:18:58 +0000 Subject: [PATCH 1739/1799] xen-netback: cancel the credit timer when taking the vif down [ Upstream commit 3e55f8b306cf305832a4ac78aa82e1b40e818ece ] If the credit timer is left armed after calling xen_netbk_remove_xenvif(), then it may fire and attempt to schedule the vif which will then oops as vif->netbk == NULL. This may happen both in the fatal error path and during normal disconnection from the front end. The sequencing during shutdown is critical to ensure that: a) vif->netbk doesn't become unexpectedly NULL; and b) the net device/vif is not freed. 1. Mark as unschedulable (netif_carrier_off()). 2. Synchronously cancel the timer. 3. Remove the vif from the schedule list. 4. Remove it from it netback thread group. 5. Wait for vif->refcnt to become 0. Signed-off-by: David Vrabel Acked-by: Ian Campbell Reported-by: Christopher S. Aker Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/xen-netback/interface.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index b8c5193bd420..221f4265f7d6 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -132,6 +132,7 @@ static void xenvif_up(struct xenvif *vif) static void xenvif_down(struct xenvif *vif) { disable_irq(vif->irq); + del_timer_sync(&vif->credit_timeout); xen_netbk_deschedule_xenvif(vif); xen_netbk_remove_xenvif(vif); } @@ -363,8 +364,6 @@ void xenvif_disconnect(struct xenvif *vif) atomic_dec(&vif->refcnt); wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); - del_timer_sync(&vif->credit_timeout); - if (vif->irq) unbind_from_irqhandler(vif->irq, vif); -- GitLab From 1e6b5fb5ce92028f6c87864712ed7290446a4c11 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Fri, 15 Feb 2013 22:28:25 +0000 Subject: [PATCH 1740/1799] net: fix a compile error when SOCK_REFCNT_DEBUG is enabled [ Upstream commit dec34fb0f5b7873de45132a84a3af29e61084a6b ] When SOCK_REFCNT_DEBUG is enabled, below build error is met: kernel/sysctl_binary.o: In function `sk_refcnt_debug_release': include/net/sock.h:1025: multiple definition of `sk_refcnt_debug_release' kernel/sysctl.o:include/net/sock.h:1025: first defined here kernel/audit.o: In function `sk_refcnt_debug_release': include/net/sock.h:1025: multiple definition of `sk_refcnt_debug_release' kernel/sysctl.o:include/net/sock.h:1025: first defined here make[1]: *** [kernel/built-in.o] Error 1 make: *** [kernel] Error 2 So we decide to make sk_refcnt_debug_release static to eliminate the error. Signed-off-by: Ying Xue Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/sock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/sock.h b/include/net/sock.h index 5878118e3ce6..59a8947a1944 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -944,7 +944,7 @@ static inline void sk_refcnt_debug_dec(struct sock *sk) sk->sk_prot->name, sk, atomic_read(&sk->sk_prot->socks)); } -inline void sk_refcnt_debug_release(const struct sock *sk) +static inline void sk_refcnt_debug_release(const struct sock *sk) { if (atomic_read(&sk->sk_refcnt) != 1) printk(KERN_DEBUG "Destruction of the %s socket %p delayed, refcnt=%d\n", -- GitLab From 785e5dce256ea5bdf4871af13f9908b74264b515 Mon Sep 17 00:00:00 2001 From: Li Wei Date: Thu, 21 Feb 2013 00:09:54 +0000 Subject: [PATCH 1741/1799] ipv4: fix a bug in ping_err(). [ Upstream commit b531ed61a2a2a77eeb2f7c88b49aa5ec7d9880d8 ] We should get 'type' and 'code' from the outer ICMP header. Signed-off-by: Li Wei Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ping.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 50009c787bcd..c234bda5b801 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -321,8 +321,8 @@ void ping_err(struct sk_buff *skb, u32 info) struct iphdr *iph = (struct iphdr *)skb->data; struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2)); struct inet_sock *inet_sock; - int type = icmph->type; - int code = icmph->code; + int type = icmp_hdr(skb)->type; + int code = icmp_hdr(skb)->code; struct net *net = dev_net(skb->dev); struct sock *sk; int harderr; -- GitLab From e5a096aa0aeb1fc8ad8b3d6bd70d322a0d65edc4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 21 Feb 2013 12:18:52 +0000 Subject: [PATCH 1742/1799] ipv6: use a stronger hash for tcp [ Upstream commit 08dcdbf6a7b9d14c2302c5bd0c5390ddf122f664 ] It looks like its possible to open thousands of TCP IPv6 sessions on a server, all landing in a single slot of TCP hash table. Incoming packets have to lookup sockets in a very long list. We should hash all bits from foreign IPv6 addresses, using a salt and hash mix, not a simple XOR. inet6_ehashfn() can also separately use the ports, instead of xoring them. Reported-by: Neal Cardwell Signed-off-by: Eric Dumazet Cc: Yuchung Cheng Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/inet6_hashtables.h | 8 ++++---- include/net/inet_sock.h | 1 + include/net/ipv6.h | 12 ++++++++++++ net/ipv4/af_inet.c | 9 +++++++-- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index 00cbb4384c79..2da45ce8acba 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -28,16 +28,16 @@ struct inet_hashinfo; -/* I have no idea if this is a good hash for v6 or not. -DaveM */ static inline unsigned int inet6_ehashfn(struct net *net, const struct in6_addr *laddr, const u16 lport, const struct in6_addr *faddr, const __be16 fport) { - u32 ports = (lport ^ (__force u16)fport); + u32 ports = (((u32)lport) << 16) | (__force u32)fport; return jhash_3words((__force u32)laddr->s6_addr32[3], - (__force u32)faddr->s6_addr32[3], - ports, inet_ehash_secret + net_hash_mix(net)); + ipv6_addr_jhash(faddr), + ports, + inet_ehash_secret + net_hash_mix(net)); } static inline int inet6_sk_ehashfn(const struct sock *sk) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index ae17e1352d7e..8cd2e1d0ec32 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -202,6 +202,7 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to, extern int inet_sk_rebuild_header(struct sock *sk); extern u32 inet_ehash_secret; +extern u32 ipv6_hash_secret; extern void build_ehash_secret(void); static inline unsigned int inet_ehashfn(struct net *net, diff --git a/include/net/ipv6.h b/include/net/ipv6.h index e4170a22fc6f..12a1bd2e9879 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -390,6 +391,17 @@ struct ip6_create_arg { void ip6_frag_init(struct inet_frag_queue *q, void *a); int ip6_frag_match(struct inet_frag_queue *q, void *a); +/* more secured version of ipv6_addr_hash() */ +static inline u32 ipv6_addr_jhash(const struct in6_addr *a) +{ + u32 v = (__force u32)a->s6_addr32[0] ^ (__force u32)a->s6_addr32[1]; + + return jhash_3words(v, + (__force u32)a->s6_addr32[2], + (__force u32)a->s6_addr32[3], + ipv6_hash_secret); +} + static inline int ipv6_addr_any(const struct in6_addr *a) { return (a->s6_addr32[0] | a->s6_addr32[1] | diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 10e3751466b5..78ec298001c8 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -227,8 +227,12 @@ EXPORT_SYMBOL(inet_listen); u32 inet_ehash_secret __read_mostly; EXPORT_SYMBOL(inet_ehash_secret); +u32 ipv6_hash_secret __read_mostly; +EXPORT_SYMBOL(ipv6_hash_secret); + /* - * inet_ehash_secret must be set exactly once + * inet_ehash_secret must be set exactly once, and to a non nul value + * ipv6_hash_secret must be set exactly once. */ void build_ehash_secret(void) { @@ -238,7 +242,8 @@ void build_ehash_secret(void) get_random_bytes(&rnd, sizeof(rnd)); } while (rnd == 0); - cmpxchg(&inet_ehash_secret, 0, rnd); + if (cmpxchg(&inet_ehash_secret, 0, rnd) == 0) + get_random_bytes(&ipv6_hash_secret, sizeof(ipv6_hash_secret)); } EXPORT_SYMBOL(build_ehash_secret); -- GitLab From 8c2223fc19032e7b8761e46c15e1ed167a252285 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Sat, 23 Feb 2013 01:13:47 +0000 Subject: [PATCH 1743/1799] sock_diag: Fix out-of-bounds access to sock_diag_handlers[] [ Upstream commit 6e601a53566d84e1ffd25e7b6fe0b6894ffd79c0 ] Userland can send a netlink message requesting SOCK_DIAG_BY_FAMILY with a family greater or equal then AF_MAX -- the array size of sock_diag_handlers[]. The current code does not test for this condition therefore is vulnerable to an out-of-bound access opening doors for a privilege escalation. Signed-off-by: Mathias Krause Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/sock_diag.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index b9868e1fd62c..aa74be442dfb 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c @@ -126,6 +126,9 @@ static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (nlmsg_len(nlh) < sizeof(*req)) return -EINVAL; + if (req->sdiag_family >= AF_MAX) + return -EINVAL; + hndl = sock_diag_lock_handler(req->sdiag_family); if (hndl == NULL) err = -ENOENT; -- GitLab From b9bf60ac3e3779d4ffa03daceebf59df7b46c224 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 21 Feb 2013 23:32:27 +0000 Subject: [PATCH 1744/1799] vlan: adjust vlan_set_encap_proto() for its callers [ Upstream commit da8c87241c26aac81a64c7e4d21d438a33018f4e ] There are two places to call vlan_set_encap_proto(): vlan_untag() and __pop_vlan_tci(). vlan_untag() assumes skb->data points after mac addr, otherwise the following code vhdr = (struct vlan_hdr *) skb->data; vlan_tci = ntohs(vhdr->h_vlan_TCI); __vlan_hwaccel_put_tag(skb, vlan_tci); skb_pull_rcsum(skb, VLAN_HLEN); won't be correct. But __pop_vlan_tci() assumes points _before_ mac addr. In vlan_set_encap_proto(), it looks for some magic L2 value after mac addr: rawp = skb->data; if (*(unsigned short *) rawp == 0xFFFF) ... Therefore __pop_vlan_tci() is obviously wrong. A quick fix is avoiding using skb->data in vlan_set_encap_proto(), use 'vhdr+1' is always correct in both cases. Signed-off-by: Cong Wang Cc: David S. Miller Cc: Jesse Gross Acked-by: Jesse Gross Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/if_vlan.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 561e130df0b2..9b0c6142eaed 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -327,7 +327,7 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb, struct vlan_hdr *vhdr) { __be16 proto; - unsigned char *rawp; + unsigned short *rawp; /* * Was a VLAN packet, grab the encapsulated protocol, which the layer @@ -340,8 +340,8 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb, return; } - rawp = skb->data; - if (*(unsigned short *) rawp == 0xFFFF) + rawp = (unsigned short *)(vhdr + 1); + if (*rawp == 0xFFFF) /* * This is a magic hack to spot IPX packets. Older Novell * breaks the protocol design and runs IPX over 802.3 without -- GitLab From 62fb8fe993f3a9060d75bc3d8b6eb9d153d8238c Mon Sep 17 00:00:00 2001 From: Maciej Sosnowski Date: Wed, 23 May 2012 17:27:07 +0200 Subject: [PATCH 1745/1799] dca: check against empty dca_domains list before unregister provider commit c419fcfd071cf34ba00f9f65282583772d2655e7 upstream. When providers get blocked unregister_dca_providers() is called ending up with dca_providers and dca_domain lists emptied. Dca should be prevented from trying to unregister any provider if dca_domain list is found empty. Reported-by: Jiang Liu Tested-by: Gaohuai Han Signed-off-by: Maciej Sosnowski Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/dca/dca-core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index bc6f5faa1e9e..819dfda88236 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c @@ -420,6 +420,11 @@ void unregister_dca_provider(struct dca_provider *dca, struct device *dev) raw_spin_lock_irqsave(&dca_lock, flags); + if (list_empty(&dca_domains)) { + raw_spin_unlock_irqrestore(&dca_lock, flags); + return; + } + list_del(&dca->node); pci_rc = dca_pci_rc_from_dev(dev); -- GitLab From 78b42978accff2b4ccc45f399c47841d697e166f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 23 Jan 2013 10:44:36 +0100 Subject: [PATCH 1746/1799] USB: option: add and update Alcatel modems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f8f0302bbcbd1b14655bef29f6996a2152be559d upstream. Adding three currently unsupported modems based on information from .inf driver files: Diag VID_1BBB&PID_0052&MI_00 AGPS VID_1BBB&PID_0052&MI_01 VOICE VID_1BBB&PID_0052&MI_02 AT VID_1BBB&PID_0052&MI_03 Modem VID_1BBB&PID_0052&MI_05 wwan VID_1BBB&PID_0052&MI_06 Diag VID_1BBB&PID_00B6&MI_00 AT VID_1BBB&PID_00B6&MI_01 Modem VID_1BBB&PID_00B6&MI_02 wwan VID_1BBB&PID_00B6&MI_03 Diag VID_1BBB&PID_00B7&MI_00 AGPS VID_1BBB&PID_00B7&MI_01 VOICE VID_1BBB&PID_00B7&MI_02 AT VID_1BBB&PID_00B7&MI_03 Modem VID_1BBB&PID_00B7&MI_04 wwan VID_1BBB&PID_00B7&MI_05 Updating the blacklist info for the X060S_X200 and X220_X500D, reserving interfaces for a wwan driver, based on wwan VID_1BBB&PID_0000&MI_04 wwan VID_1BBB&PID_0017&MI_06 Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 6c077a174bfd..db976033b026 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -479,6 +479,7 @@ static const struct option_blacklist_info four_g_w14_blacklist = { static const struct option_blacklist_info alcatel_x200_blacklist = { .sendsetup = BIT(0) | BIT(1), + .reserved = BIT(4), }; static const struct option_blacklist_info zte_0037_blacklist = { @@ -1215,7 +1216,14 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist }, - { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, 0x0052), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, 0x00b6), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, 0x00b7), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, -- GitLab From 0457c05d7f770e5b1581ecc1357b4c2b7b336808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Tue, 12 Feb 2013 13:42:24 +0100 Subject: [PATCH 1747/1799] USB: option: add Yota / Megafon M100-1 4g modem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit cd565279e51bedee1b2988e84f9b3bef485adeb6 upstream. Interface layout: 00 CD-ROM 01 debug COM port 02 AP control port 03 modem 04 usb-ethernet Bus=01 Lev=02 Prnt=02 Port=01 Cnt=02 Dev#= 4 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=0408 ProdID=ea42 Rev= 0.00 S: Manufacturer=Qualcomm, Incorporated S: Product=Qualcomm CDMA Technologies MSM S: SerialNumber=353568051xxxxxx C:* #Ifs= 5 Cfg#= 1 Atr=e0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=84(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=86(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms Signed-off-by: Bjørn Mork 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 db976033b026..5e7f5524cea9 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -576,6 +576,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, + { USB_DEVICE(QUANTA_VENDOR_ID, 0xea42), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff), -- GitLab From 9c5879c55ecc7c5b0e54809e011561bde4926d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 13 Feb 2013 23:41:34 +0100 Subject: [PATCH 1748/1799] USB: option: add Huawei "ACM" devices using protocol = vendor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1f3f687722fd9b29a0c2a85b4844e3b2a3585c63 upstream. The USB device descriptor of one identity presented by a few Huawei morphing devices have serial functions with class codes 02/02/ff, indicating CDC ACM with a vendor specific protocol. This combination is often used for MSFT RNDIS functions, and the CDC ACM class driver will therefore ignore such functions. The CDC ACM class driver cannot support functions with only 2 endpoints. The underlying serial functions of these modems are also believed to be the same as for alternate device identities already supported by the option driver. Letting the same driver handle these functions independently of the current identity ensures consistent handling and user experience. There is no need to blacklist these devices in the rndis_host driver. Huawei serial functions will either have only 2 endpoints or a CDC ACM functional descriptor with bmCapabilities != 0, making them correctly ignored as "non RNDIS" by that driver. Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5e7f5524cea9..539247b934aa 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -578,8 +578,12 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, { USB_DEVICE(QUANTA_VENDOR_ID, 0xea42), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c05, USB_CLASS_COMM, 0x02, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1441, USB_CLASS_COMM, 0x02, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1442, USB_CLASS_COMM, 0x02, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff), -- GitLab From 30361160bc12da86b9ce4c7c60bd68ff930eda76 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 14 Feb 2013 17:08:09 +0200 Subject: [PATCH 1749/1799] USB: ehci-omap: Fix autoloading of module commit 04753523266629b1cd0518091da1658755787198 upstream. The module alias should be "ehci-omap" and not "omap-ehci" to match the platform device name. The omap-ehci module should now autoload correctly. Signed-off-by: Roger Quadros Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index e669c6a7e91e..12d3f284998e 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -371,7 +371,7 @@ static const struct hc_driver ehci_omap_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; -MODULE_ALIAS("platform:omap-ehci"); +MODULE_ALIAS("platform:ehci-omap"); MODULE_AUTHOR("Texas Instruments, Inc."); MODULE_AUTHOR("Felipe Balbi "); -- GitLab From 12b64a247ef45dcd865a98d63bbae7355e51633b Mon Sep 17 00:00:00 2001 From: fangxiaozhi Date: Thu, 7 Feb 2013 15:32:07 +0800 Subject: [PATCH 1750/1799] USB: storage: properly handle the endian issues of idProduct commit cd060956c5e97931c3909e4a808508469c0bb9f6 upstream. 1. The idProduct is little endian, so make sure its value to be compatible with the current CPU. Make no break on big endian processors. Signed-off-by: fangxiaozhi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/initializers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 16b0bf055eeb..7ab9046ae0ec 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c @@ -147,7 +147,7 @@ static int usb_stor_huawei_dongles_pid(struct us_data *us) int idProduct; idesc = &us->pusb_intf->cur_altsetting->desc; - idProduct = us->pusb_dev->descriptor.idProduct; + idProduct = le16_to_cpu(us->pusb_dev->descriptor.idProduct); /* The first port is CDROM, * means the dongle in the single port mode, * and a switch command is required to be sent. */ @@ -169,7 +169,7 @@ int usb_stor_huawei_init(struct us_data *us) int result = 0; if (usb_stor_huawei_dongles_pid(us)) { - if (us->pusb_dev->descriptor.idProduct >= 0x1446) + if (le16_to_cpu(us->pusb_dev->descriptor.idProduct) >= 0x1446) result = usb_stor_huawei_scsi_init(us); else result = usb_stor_huawei_feature_init(us); -- GitLab From 616dd23b2e475e61a2974eb112cc88d3cb94d47f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 14 Feb 2013 09:39:09 -0500 Subject: [PATCH 1751/1799] USB: usb-storage: unusual_devs update for Super TOP SATA bridge commit 18e03310b5caa6d11c1a8c61b982c37047693fba upstream. The current entry in unusual_cypress.h for the Super TOP SATA bridge devices seems to be causing corruption on newer revisions of this device. This has been reported in Arch Linux and Fedora. The original patch was tested on devices with bcdDevice of 1.60, whereas the newer devices report bcdDevice as 2.20. Limit the UNUSUAL_DEV entry to devices less than 2.20. This fixes https://bugzilla.redhat.com/show_bug.cgi?id=909591 The Arch Forum post on this is here: https://bbs.archlinux.org/viewtopic.php?id=152011 Reported-by: Carsten S. Tested-by: Carsten S. Signed-off-by: Josh Boyer Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_cypress.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h index 2c8553026222..65a6a75066a8 100644 --- a/drivers/usb/storage/unusual_cypress.h +++ b/drivers/usb/storage/unusual_cypress.h @@ -31,7 +31,7 @@ UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, "Cypress ISD-300LP", USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), -UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x9999, +UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x0219, "Super Top", "USB 2.0 SATA BRIDGE", USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), -- GitLab From 048b6fe6dccb105512147eb47accbb1431b4e54b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 28 Feb 2013 07:01:22 -0800 Subject: [PATCH 1752/1799] Linux 3.4.34 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a26d19a31d97..250be36a8180 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 33 +SUBLEVEL = 34 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab From dd54ec4067a23236736afecbda120030d7ce8fe9 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Fri, 22 Feb 2013 10:16:28 +0100 Subject: [PATCH 1753/1799] ALSA: hda - hdmi: Make jacks phantom, if they're not detectable commit 30efd8debd1ef30be342d374f01e993509f5b76b upstream. Just as for analog codecs, a jack that isn't suitable for detection (in this case, NO_PRESENCE was set) should be a phantom Jack instead of a normal one. Thanks to Raymond Yau for spotting. BugLink: https://bugs.launchpad.net/bugs/961286 BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=903869 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_hdmi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 02a6e3f481ef..fa2ce0cf47de 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1244,6 +1244,9 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) if (pcmdev > 0) sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); + if (!is_jack_detectable(codec, per_pin->pin_nid)) + strncat(hdmi_str, " Phantom", + sizeof(hdmi_str) - strlen(hdmi_str) - 1); return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, 0); } -- GitLab From db6154ead40e0a568982ec4885cfa3fa89e67324 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 24 Jan 2013 23:24:56 -0500 Subject: [PATCH 1754/1799] quota: autoload the quota_v2 module for QFMT_VFS_V1 quota format commit c3ad83d9efdfe6a86efd44945a781f00c879b7b4 upstream. Otherwise, ext4 file systems with the quota featured enable will get a very confusing "No such process" error message if the quota code is built as a module and the quota_v2 module has not been loaded. Signed-off-by: "Theodore Ts'o" Reviewed-by: Carlos Maiolino Acked-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- include/linux/quota.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/quota.h b/include/linux/quota.h index c09fa042b5ea..ffd8607ca4be 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -417,6 +417,7 @@ struct quota_module_name { #define INIT_QUOTA_MODULE_NAMES {\ {QFMT_VFS_OLD, "quota_v1"},\ {QFMT_VFS_V0, "quota_v2"},\ + {QFMT_VFS_V1, "quota_v2"},\ {0, NULL}} #endif /* __KERNEL__ */ -- GitLab From 0c8581863389e969dcbf6d9e79971435a1ecf554 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 6 Feb 2013 12:55:23 +0100 Subject: [PATCH 1755/1799] iommu/amd: Initialize device table after dma_ops commit f528d980c17b8714aedc918ba86e058af914d66b upstream. When dma_ops are initialized the unity mappings are created. The init_device_table_dma() function makes sure DMA from all devices is blocked by default. This opens a short window in time where DMA to unity mapped regions is blocked by the IOMMU. Make sure this does not happen by initializing the device table after dma_ops. Signed-off-by: Joerg Roedel Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/amd_iommu_init.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index ef0ae93500f4..b573f803d84b 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1572,8 +1572,6 @@ int __init amd_iommu_init_hardware(void) if (amd_iommu_pd_alloc_bitmap == NULL) goto free; - /* init the device table */ - init_device_table(); /* * let all alias entries point to itself @@ -1655,6 +1653,7 @@ static int amd_iommu_enable_interrupts(void) */ static int __init amd_iommu_init(void) { + struct amd_iommu *iommu; int ret = 0; ret = amd_iommu_init_hardware(); @@ -1673,6 +1672,12 @@ static int __init amd_iommu_init(void) if (ret) goto free; + /* init the device table */ + init_device_table(); + + for_each_iommu(iommu) + iommu_flush_all_caches(iommu); + amd_iommu_init_api(); x86_platform.iommu_shutdown = disable_iommus; -- GitLab From db3d76a623b8ce429318cc2491881c02b790dab4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 20 Feb 2013 15:24:12 -0800 Subject: [PATCH 1756/1799] posix-timer: Don't call idr_find() with out-of-range ID commit e182bb38d7db7494fa5dcd82da17fe0dedf60ecf upstream. When idr_find() was fed a negative ID, it used to look up the ID ignoring the sign bit before recent ("idr: remove MAX_IDR_MASK and move left MAX_IDR_* into idr.c") patch. Now a negative ID triggers a WARN_ON_ONCE(). __lock_timer() feeds timer_id from userland directly to idr_find() without sanitizing it which can trigger the above malfunctions. Add a range check on @timer_id before invoking idr_find() in __lock_timer(). While timer_t is defined as int by all archs at the moment, Andrew worries that it may be defined as a larger type later on. Make the test cover larger integers too so that it at least is guaranteed to not return the wrong timer. Note that WARN_ON_ONCE() in idr_find() on id < 0 is transitional precaution while moving away from ignoring MSB. Once it's gone we can remove the guard as long as timer_t isn't larger than int. Signed-off-by: Tejun Heo Reported-by: Sasha Levin Cc: Andrew Morton Link: http://lkml.kernel.org/r/20130220232412.GL3570@htj.dyndns.org Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/posix-timers.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 69185ae6b701..e885be1e8a11 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -639,6 +639,13 @@ static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags) { struct k_itimer *timr; + /* + * timer_t could be any type >= int and we want to make sure any + * @timer_id outside positive int range fails lookup. + */ + if ((unsigned long long)timer_id > INT_MAX) + return NULL; + rcu_read_lock(); timr = idr_find(&posix_timers_id, (int)timer_id); if (timr) { -- GitLab From e6842472eb7f8091c27eb43ad934097ce04d3fbb Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Wed, 13 Feb 2013 15:18:38 -0500 Subject: [PATCH 1757/1799] ftrace: Call ftrace cleanup module notifier after all other notifiers commit 8c189ea64eea01ca20d102ddb74d6936dd16c579 upstream. Commit: c1bf08ac "ftrace: Be first to run code modification on modules" changed ftrace module notifier's priority to INT_MAX in order to process the ftrace nops before anything else could touch them (namely kprobes). This was the correct thing to do. Unfortunately, the ftrace module notifier also contains the ftrace clean up code. As opposed to the set up code, this code should be run *after* all the module notifiers have run in case a module is doing correct clean-up and unregisters its ftrace hooks. Basically, ftrace needs to do clean up on module removal, as it needs to know about code being removed so that it doesn't try to modify that code. But after it removes the module from its records, if a ftrace user tries to remove a probe, that removal will fail due as the record of that code segment no longer exists. Nothing really bad happens if the probe removal is called after ftrace did the clean up, but the ftrace removal function will return an error. Correct code (such as kprobes) will produce a WARN_ON() if it fails to remove the probe. As people get annoyed by frivolous warnings, it's best to do the ftrace clean up after everything else. By splitting the ftrace_module_notifier into two notifiers, one that does the module load setup that is run at high priority, and the other that is called for module clean up that is run at low priority, the problem is solved. Reported-by: Frank Ch. Eigler Acked-by: Masami Hiramatsu Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ftrace.c | 46 ++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 6b194d842b18..4a86e6404085 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3841,37 +3841,51 @@ static void ftrace_init_module(struct module *mod, ftrace_process_locs(mod, start, end); } -static int ftrace_module_notify(struct notifier_block *self, - unsigned long val, void *data) +static int ftrace_module_notify_enter(struct notifier_block *self, + unsigned long val, void *data) { struct module *mod = data; - switch (val) { - case MODULE_STATE_COMING: + if (val == MODULE_STATE_COMING) ftrace_init_module(mod, mod->ftrace_callsites, mod->ftrace_callsites + mod->num_ftrace_callsites); - break; - case MODULE_STATE_GOING: + return 0; +} + +static int ftrace_module_notify_exit(struct notifier_block *self, + unsigned long val, void *data) +{ + struct module *mod = data; + + if (val == MODULE_STATE_GOING) ftrace_release_mod(mod); - break; - } return 0; } #else -static int ftrace_module_notify(struct notifier_block *self, - unsigned long val, void *data) +static int ftrace_module_notify_enter(struct notifier_block *self, + unsigned long val, void *data) +{ + return 0; +} +static int ftrace_module_notify_exit(struct notifier_block *self, + unsigned long val, void *data) { return 0; } #endif /* CONFIG_MODULES */ -struct notifier_block ftrace_module_nb = { - .notifier_call = ftrace_module_notify, +struct notifier_block ftrace_module_enter_nb = { + .notifier_call = ftrace_module_notify_enter, .priority = INT_MAX, /* Run before anything that can use kprobes */ }; +struct notifier_block ftrace_module_exit_nb = { + .notifier_call = ftrace_module_notify_exit, + .priority = INT_MIN, /* Run after anything that can remove kprobes */ +}; + extern unsigned long __start_mcount_loc[]; extern unsigned long __stop_mcount_loc[]; @@ -3903,9 +3917,13 @@ void __init ftrace_init(void) __start_mcount_loc, __stop_mcount_loc); - ret = register_module_notifier(&ftrace_module_nb); + ret = register_module_notifier(&ftrace_module_enter_nb); + if (ret) + pr_warning("Failed to register trace ftrace module enter notifier\n"); + + ret = register_module_notifier(&ftrace_module_exit_nb); if (ret) - pr_warning("Failed to register trace ftrace module notifier\n"); + pr_warning("Failed to register trace ftrace module exit notifier\n"); set_ftrace_early_filters(); -- GitLab From 92916fb21cc71f7877c06ab998728f118e2d72cb Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Wed, 20 Feb 2013 20:36:12 +0000 Subject: [PATCH 1758/1799] x86, efi: Make "noefi" really disable EFI runtime serivces commit fb834c7acc5e140cf4f9e86da93a66de8c0514da upstream. commit 1de63d60cd5b ("efi: Clear EFI_RUNTIME_SERVICES rather than EFI_BOOT by "noefi" boot parameter") attempted to make "noefi" true to its documentation and disable EFI runtime services to prevent the bricking bug described in commit e0094244e41c ("samsung-laptop: Disable on EFI hardware"). However, it's not possible to clear EFI_RUNTIME_SERVICES from an early param function because EFI_RUNTIME_SERVICES is set in efi_init() *after* parse_early_param(). This resulted in "noefi" effectively becoming a no-op and no longer providing users with a way to disable EFI, which is bad for those users that have buggy machines. Reported-by: Walt Nelson Jr Cc: Satoru Takeuchi Signed-off-by: Matt Fleming Link: http://lkml.kernel.org/r/1361392572-25657-1-git-send-email-matt@console-pimps.org Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/platform/efi/efi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 3705bb049e54..1e406371a683 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -84,9 +84,10 @@ int efi_enabled(int facility) } EXPORT_SYMBOL(efi_enabled); +static bool disable_runtime = false; static int __init setup_noefi(char *arg) { - clear_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility); + disable_runtime = true; return 0; } early_param("noefi", setup_noefi); @@ -733,7 +734,7 @@ void __init efi_init(void) if (!efi_is_native()) pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); else { - if (efi_runtime_init()) + if (disable_runtime || efi_runtime_init()) return; set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility); } -- GitLab From 938987dc41c19b1683934e0d4e75ae9b04456b80 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 25 Feb 2013 15:54:08 -0500 Subject: [PATCH 1759/1799] doc, xen: Mention 'earlyprintk=xen' in the documentation. commit 2482a92e7d17187301d7313cfe5021b13393a0b4 upstream. The earlyprintk for Xen PV guests utilizes a simple hypercall (console_io) to provide output to Xen emergency console. Note that the Xen hypervisor should be booted with 'loglevel=all' to output said information. Reported-by: H. Peter Anvin Signed-off-by: Konrad Rzeszutek Wilk Link: http://lkml.kernel.org/r/1361825650-14031-2-git-send-email-konrad.wilk@oracle.com Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index c1601e5a8b71..f2e1645a2bda 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -742,6 +742,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. earlyprintk= [X86,SH,BLACKFIN] earlyprintk=vga + earlyprintk=xen earlyprintk=serial[,ttySn[,baudrate]] earlyprintk=ttySn[,baudrate] earlyprintk=dbgp[debugController#] @@ -759,6 +760,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. The VGA output is eventually overwritten by the real console. + The xen output can only be used by Xen PV guests. + ekgdboc= [X86,KGDB] Allow early kernel console debugging ekgdboc=kbd -- GitLab From 2a0887caaf540517017d994d8d1940416a3365da Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 25 Feb 2013 15:54:09 -0500 Subject: [PATCH 1760/1799] doc, kernel-parameters: Document 'console=hvc' commit a2fd6419174470f5ae6383f5037d0ee21ed9833f upstream. Both the PowerPC hypervisor and Xen hypervisor can utilize the hvc driver. Signed-off-by: Konrad Rzeszutek Wilk Link: http://lkml.kernel.org/r/1361825650-14031-3-git-send-email-konrad.wilk@oracle.com Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index f2e1645a2bda..753d18ae0105 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -557,6 +557,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. UART at the specified I/O port or MMIO address, switching to the matching ttyS device later. The options are the same as for ttyS, above. + hvc Use the hypervisor console device . This is for + both Xen and PowerPC hypervisors. If the device connected to the port is not a TTY but a braille device, prepend "brl," before the device type, for instance -- GitLab From 58d7422c654e7720a3920e63dcd6c64052aeec2d Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 27 Feb 2013 12:46:40 -0800 Subject: [PATCH 1761/1799] x86: Make sure we can boot in the case the BDA contains pure garbage commit 7c10093692ed2e6f318387d96b829320aa0ca64c upstream. On non-BIOS platforms it is possible that the BIOS data area contains garbage instead of being zeroed or something equivalent (firmware people: we are talking of 1.5K here, so please do the sane thing.) We need on the order of 20-30K of low memory in order to boot, which may grow up to < 64K in the future. We probably want to avoid the lowest of the low memory. At the same time, it seems extremely unlikely that a legitimate EBDA would ever reach down to the 128K (which would require it to be over half a megabyte in size.) Thus, pick 128K as the cutoff for "this is insane, ignore." We may still end up reserving a bunch of extra memory on the low megabyte, but that is not really a major issue these days. In the worst case we lose 512K of RAM. This code really should be merged with trim_bios_range() in arch/x86/kernel/setup.c, but that is a bigger patch for a later merge window. Reported-by: Darren Hart Signed-off-by: H. Peter Anvin Cc: Matt Fleming Link: http://lkml.kernel.org/n/tip-oebml055yyfm8yxmria09rja@git.kernel.org Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/head.c | 53 +++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c index 48d9d4ea1020..992f442ca155 100644 --- a/arch/x86/kernel/head.c +++ b/arch/x86/kernel/head.c @@ -5,8 +5,6 @@ #include #include -#define BIOS_LOWMEM_KILOBYTES 0x413 - /* * The BIOS places the EBDA/XBDA at the top of conventional * memory, and usually decreases the reported amount of @@ -16,17 +14,30 @@ * chipset: reserve a page before VGA to prevent PCI prefetch * into it (errata #56). Usually the page is reserved anyways, * unless you have no PS/2 mouse plugged in. + * + * This functions is deliberately very conservative. Losing + * memory in the bottom megabyte is rarely a problem, as long + * as we have enough memory to install the trampoline. Using + * memory that is in use by the BIOS or by some DMA device + * the BIOS didn't shut down *is* a big problem. */ + +#define BIOS_LOWMEM_KILOBYTES 0x413 +#define LOWMEM_CAP 0x9f000U /* Absolute maximum */ +#define INSANE_CUTOFF 0x20000U /* Less than this = insane */ + void __init reserve_ebda_region(void) { unsigned int lowmem, ebda_addr; - /* To determine the position of the EBDA and the */ - /* end of conventional memory, we need to look at */ - /* the BIOS data area. In a paravirtual environment */ - /* that area is absent. We'll just have to assume */ - /* that the paravirt case can handle memory setup */ - /* correctly, without our help. */ + /* + * To determine the position of the EBDA and the + * end of conventional memory, we need to look at + * the BIOS data area. In a paravirtual environment + * that area is absent. We'll just have to assume + * that the paravirt case can handle memory setup + * correctly, without our help. + */ if (paravirt_enabled()) return; @@ -37,19 +48,23 @@ void __init reserve_ebda_region(void) /* start of EBDA area */ ebda_addr = get_bios_ebda(); - /* Fixup: bios puts an EBDA in the top 64K segment */ - /* of conventional memory, but does not adjust lowmem. */ - if ((lowmem - ebda_addr) <= 0x10000) - lowmem = ebda_addr; + /* + * Note: some old Dells seem to need 4k EBDA without + * reporting so, so just consider the memory above 0x9f000 + * to be off limits (bugzilla 2990). + */ + + /* If the EBDA address is below 128K, assume it is bogus */ + if (ebda_addr < INSANE_CUTOFF) + ebda_addr = LOWMEM_CAP; - /* Fixup: bios does not report an EBDA at all. */ - /* Some old Dells seem to need 4k anyhow (bugzilla 2990) */ - if ((ebda_addr == 0) && (lowmem >= 0x9f000)) - lowmem = 0x9f000; + /* If lowmem is less than 128K, assume it is bogus */ + if (lowmem < INSANE_CUTOFF) + lowmem = LOWMEM_CAP; - /* Paranoia: should never happen, but... */ - if ((lowmem == 0) || (lowmem >= 0x100000)) - lowmem = 0x9f000; + /* Use the lower of the lowmem and EBDA markers as the cutoff */ + lowmem = min(lowmem, ebda_addr); + lowmem = min(lowmem, LOWMEM_CAP); /* Absolute cap */ /* reserve all memory between lowmem and the 1MB mark */ memblock_reserve(lowmem, 0x100000 - lowmem); -- GitLab From 3fa4f7261d75cb6b35fdf8d329f5fd64e7354c58 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 18 Feb 2013 18:00:33 -0800 Subject: [PATCH 1762/1799] target: Fix lookup of dynamic NodeACLs during cached demo-mode operation commit fcf29481fb8e106daad6688f2e898226ee928992 upstream. This patch fixes a bug in core_tpg_check_initiator_node_acl() -> core_tpg_get_initiator_node_acl() where a dynamically created se_node_acl generated during session login would be skipped during subsequent lookup due to the '!acl->dynamic_node_acl' check, causing a new se_node_acl to be created with a duplicate ->initiatorname. This would occur when a fabric endpoint was configured with TFO->tpg_check_demo_mode()=1 + TPF->tpg_check_demo_mode_cache()=1 preventing the release of an existing se_node_acl during se_session shutdown. Also, drop the unnecessary usage of core_tpg_get_initiator_node_acl() within core_dev_init_initiator_node_lun_acl() that originally required the extra '!acl->dynamic_node_acl' check, and just pass the configfs provided se_node_acl pointer instead. Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_device.c | 13 ++++--------- drivers/target/target_core_fabric_configfs.c | 4 ++-- drivers/target/target_core_internal.h | 2 +- drivers/target/target_core_tpg.c | 10 ++-------- 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 4ecf9d61c221..79d9865a1270 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1483,24 +1483,18 @@ static struct se_lun *core_dev_get_lun(struct se_portal_group *tpg, u32 unpacked struct se_lun_acl *core_dev_init_initiator_node_lun_acl( struct se_portal_group *tpg, + struct se_node_acl *nacl, u32 mapped_lun, - char *initiatorname, int *ret) { struct se_lun_acl *lacl; - struct se_node_acl *nacl; - if (strlen(initiatorname) >= TRANSPORT_IQN_LEN) { + if (strlen(nacl->initiatorname) >= TRANSPORT_IQN_LEN) { pr_err("%s InitiatorName exceeds maximum size.\n", tpg->se_tpg_tfo->get_fabric_name()); *ret = -EOVERFLOW; return NULL; } - nacl = core_tpg_get_initiator_node_acl(tpg, initiatorname); - if (!nacl) { - *ret = -EINVAL; - return NULL; - } lacl = kzalloc(sizeof(struct se_lun_acl), GFP_KERNEL); if (!lacl) { pr_err("Unable to allocate memory for struct se_lun_acl.\n"); @@ -1511,7 +1505,8 @@ struct se_lun_acl *core_dev_init_initiator_node_lun_acl( INIT_LIST_HEAD(&lacl->lacl_list); lacl->mapped_lun = mapped_lun; lacl->se_lun_nacl = nacl; - snprintf(lacl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname); + snprintf(lacl->initiatorname, TRANSPORT_IQN_LEN, "%s", + nacl->initiatorname); return lacl; } diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 817ba7c849e7..1516bda3f759 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -357,8 +357,8 @@ static struct config_group *target_fabric_make_mappedlun( goto out; } - lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun, - config_item_name(acl_ci), &ret); + lacl = core_dev_init_initiator_node_lun_acl(se_tpg, se_nacl, + mapped_lun, &ret); if (!lacl) { ret = -EINVAL; goto out; diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 21c05638f158..17179b1af540 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -61,7 +61,7 @@ struct se_lun *core_dev_add_lun(struct se_portal_group *, struct se_hba *, int core_dev_del_lun(struct se_portal_group *, u32); struct se_lun *core_get_lun_from_tpg(struct se_portal_group *, u32); struct se_lun_acl *core_dev_init_initiator_node_lun_acl(struct se_portal_group *, - u32, char *, int *); + struct se_node_acl *, u32, int *); int core_dev_add_initiator_node_lun_acl(struct se_portal_group *, struct se_lun_acl *, u32, u32); int core_dev_del_initiator_node_lun_acl(struct se_portal_group *, diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index ba537b6fd85e..0e17fa3da01b 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -114,16 +114,10 @@ struct se_node_acl *core_tpg_get_initiator_node_acl( struct se_node_acl *acl; spin_lock_irq(&tpg->acl_node_lock); - list_for_each_entry(acl, &tpg->acl_node_list, acl_list) { - if (!strcmp(acl->initiatorname, initiatorname) && - !acl->dynamic_node_acl) { - spin_unlock_irq(&tpg->acl_node_lock); - return acl; - } - } + acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); spin_unlock_irq(&tpg->acl_node_lock); - return NULL; + return acl; } /* core_tpg_add_node_to_devs(): -- GitLab From 316857e5fe5391057d5a05f215e01d0deff7c473 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 18 Feb 2013 18:31:37 -0800 Subject: [PATCH 1763/1799] target: Add missing mapped_lun bounds checking during make_mappedlun setup commit fbbf8555a986ed31e54f006b6cc637ea4ff1425b upstream. This patch adds missing bounds checking for the configfs provided mapped_lun value during target_fabric_make_mappedlun() setup ahead of se_lun_acl initialization. This addresses a potential OOPs when using a mapped_lun value that exceeds the hardcoded TRANSPORT_MAX_LUNS_PER_TPG-1 value within se_node_acl->device_list[]. Reported-by: Jan Engelhardt Cc: Jan Engelhardt Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman --- drivers/target/target_core_fabric_configfs.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 1516bda3f759..6b79ee711525 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -356,6 +356,14 @@ static struct config_group *target_fabric_make_mappedlun( ret = -EINVAL; goto out; } + if (mapped_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) { + pr_err("Mapped LUN: %lu exceeds TRANSPORT_MAX_LUNS_PER_TPG" + "-1: %u for Target Portal Group: %u\n", mapped_lun, + TRANSPORT_MAX_LUNS_PER_TPG-1, + se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg)); + ret = -EINVAL; + goto out; + } lacl = core_dev_init_initiator_node_lun_acl(se_tpg, se_nacl, mapped_lun, &ret); -- GitLab From fa1c19bbbd6cb82086da10ae3817f8d5d8c6a7ae Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 20 Feb 2013 13:16:39 +1100 Subject: [PATCH 1764/1799] ocfs2: fix possible use-after-free with AIO commit 9b171e0c74ca0549d0610990a862dd895870f04a upstream. Running AIO is pinning inode in memory using file reference. Once AIO is completed using aio_complete(), file reference is put and inode can be freed from memory. So we have to be sure that calling aio_complete() is the last thing we do with the inode. Signed-off-by: Jan Kara Acked-by: Jeff Moyer Acked-by: Joel Becker Cc: Mark Fasheh Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/aops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 657743254eb9..340bd02839be 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -593,9 +593,9 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, level = ocfs2_iocb_rw_locked_level(iocb); ocfs2_rw_unlock(inode, level); + inode_dio_done(inode); if (is_async) aio_complete(iocb, ret, 0); - inode_dio_done(inode); } /* -- GitLab From 0d5b0fcbebada4d74130ea9911c38dad1faacb8c Mon Sep 17 00:00:00 2001 From: Jeff Liu Date: Wed, 27 Feb 2013 17:02:48 -0800 Subject: [PATCH 1765/1799] ocfs2: fix ocfs2_init_security_and_acl() to initialize acl correctly commit 32918dd9f19e5960af4cdfa41190bb843fb2247b upstream. We need to re-initialize the security for a new reflinked inode with its parent dirs if it isn't specified to be preserved for ocfs2_reflink(). However, the code logic is broken at ocfs2_init_security_and_acl() although ocfs2_init_security_get() succeed. As a result, ocfs2_acl_init() does not involked and therefore the default ACL of parent dir was missing on the new inode. Note this was introduced by 9d8f13ba3 ("security: new security_inode_init_security API adds function callback") To reproduce: set default ACL for the parent dir(ocfs2 in this case): $ setfacl -m default:user:jeff:rwx ../ocfs2/ $ getfacl ../ocfs2/ # file: ../ocfs2/ # owner: jeff # group: jeff user::rwx group::r-x other::r-x default:user::rwx default:user:jeff:rwx default:group::r-x default:mask::rwx default:other::r-x $ touch a $ getfacl a # file: a # owner: jeff # group: jeff user::rw- group::rw- other::r-- Before patching, create reflink file b from a, the user default ACL entry(user:jeff:rwx)was missing: $ ./ocfs2_reflink a b $ getfacl b # file: b # owner: jeff # group: jeff user::rw- group::rw- other::r-- In this case, the end user can also observed an error message at syslog: (ocfs2_reflink,3229,2):ocfs2_init_security_and_acl:7193 ERROR: status = 0 After applying this patch, create reflink file c from a: $ ./ocfs2_reflink a c $ getfacl c # file: c # owner: jeff # group: jeff user::rw- user:jeff:rwx #effective:rw- group::r-x #effective:r-- mask::rw- other::r-- Test program: /* Usage: reflink */ #include #include #include #include #include #include #include #include #include static int reflink_file(char const *src_name, char const *dst_name, bool preserve_attrs) { int fd; #ifndef REFLINK_ATTR_NONE # define REFLINK_ATTR_NONE 0 #endif #ifndef REFLINK_ATTR_PRESERVE # define REFLINK_ATTR_PRESERVE 1 #endif #ifndef OCFS2_IOC_REFLINK struct reflink_arguments { uint64_t old_path; uint64_t new_path; uint64_t preserve; }; # define OCFS2_IOC_REFLINK _IOW ('o', 4, struct reflink_arguments) #endif struct reflink_arguments args = { .old_path = (unsigned long) src_name, .new_path = (unsigned long) dst_name, .preserve = preserve_attrs ? REFLINK_ATTR_PRESERVE : REFLINK_ATTR_NONE, }; fd = open(src_name, O_RDONLY); if (fd < 0) { fprintf(stderr, "Failed to open %s: %s\n", src_name, strerror(errno)); return -1; } if (ioctl(fd, OCFS2_IOC_REFLINK, &args) < 0) { fprintf(stderr, "Failed to reflink %s to %s: %s\n", src_name, dst_name, strerror(errno)); return -1; } } int main(int argc, char *argv[]) { if (argc != 3) { fprintf(stdout, "Usage: %s source dest\n", argv[0]); return 1; } return reflink_file(argv[1], argv[2], 0); } Signed-off-by: Jie Liu Reviewed-by: Tao Ma Cc: Mimi Zohar Cc: Joel Becker Cc: Mark Fasheh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/xattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 0ba9ea1e7961..2e3ea308c144 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -7189,7 +7189,7 @@ int ocfs2_init_security_and_acl(struct inode *dir, struct buffer_head *dir_bh = NULL; ret = ocfs2_init_security_get(inode, dir, qstr, NULL); - if (!ret) { + if (ret) { mlog_errno(ret); goto leave; } -- GitLab From 5978ac7c68e30bd9a322aa62efc411581263f881 Mon Sep 17 00:00:00 2001 From: "Xiaowei.Hu" Date: Wed, 27 Feb 2013 17:02:49 -0800 Subject: [PATCH 1766/1799] ocfs2: ac->ac_allow_chain_relink=0 won't disable group relink commit 309a85b6861fedbb48a22d45e0e079d1be993b3a upstream. ocfs2_block_group_alloc_discontig() disables chain relink by setting ac->ac_allow_chain_relink = 0 because it grabs clusters from multiple cluster groups. It doesn't keep the credits for all chain relink,but ocfs2_claim_suballoc_bits overrides this in this call trace: ocfs2_block_group_claim_bits()->ocfs2_claim_clusters()-> __ocfs2_claim_clusters()->ocfs2_claim_suballoc_bits() ocfs2_claim_suballoc_bits set ac->ac_allow_chain_relink = 1; then call ocfs2_search_chain() one time and disable it again, and then we run out of credits. Fix is to allow relink by default and disable it in ocfs2_block_group_alloc_discontig. Without this patch, End-users will run into a crash due to run out of credits, backtrace like this: RIP: 0010:[] [] jbd2_journal_dirty_metadata+0x164/0x170 [jbd2] RSP: 0018:ffff8801b919b5b8 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff88022139ddc0 RCX: ffff880159f652d0 RDX: ffff880178aa3000 RSI: ffff880159f652d0 RDI: ffff880087f09bf8 RBP: ffff8801b919b5e8 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000001e00 R11: 00000000000150b0 R12: ffff880159f652d0 R13: ffff8801a0cae908 R14: ffff880087f09bf8 R15: ffff88018d177800 FS: 00007fc9b0b6b6e0(0000) GS:ffff88022fd40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 000000000040819c CR3: 0000000184017000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process dd (pid: 9945, threadinfo ffff8801b919a000, task ffff880149a264c0) Call Trace: ocfs2_journal_dirty+0x2f/0x70 [ocfs2] ocfs2_relink_block_group+0x111/0x480 [ocfs2] ocfs2_search_chain+0x455/0x9a0 [ocfs2] ... Signed-off-by: Xiaowei.Hu Reviewed-by: Srinivas Eeda Cc: Mark Fasheh Cc: Joel Becker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/suballoc.c | 7 +++---- fs/ocfs2/suballoc.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index f169da4624fd..b7e74b580c0f 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -642,7 +642,7 @@ ocfs2_block_group_alloc_discontig(handle_t *handle, * cluster groups will be staying in cache for the duration of * this operation. */ - ac->ac_allow_chain_relink = 0; + ac->ac_disable_chain_relink = 1; /* Claim the first region */ status = ocfs2_block_group_claim_bits(osb, handle, ac, min_bits, @@ -1823,7 +1823,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, * Do this *after* figuring out how many bits we're taking out * of our target group. */ - if (ac->ac_allow_chain_relink && + if (!ac->ac_disable_chain_relink && (prev_group_bh) && (ocfs2_block_group_reasonably_empty(bg, res->sr_bits))) { status = ocfs2_relink_block_group(handle, alloc_inode, @@ -1928,7 +1928,6 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac, victim = ocfs2_find_victim_chain(cl); ac->ac_chain = victim; - ac->ac_allow_chain_relink = 1; status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits, res, &bits_left); @@ -1947,7 +1946,7 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac, * searching each chain in order. Don't allow chain relinking * because we only calculate enough journal credits for one * relink per alloc. */ - ac->ac_allow_chain_relink = 0; + ac->ac_disable_chain_relink = 1; for (i = 0; i < le16_to_cpu(cl->cl_next_free_rec); i ++) { if (i == victim) continue; diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h index b8afabfeede4..a36d0aa50911 100644 --- a/fs/ocfs2/suballoc.h +++ b/fs/ocfs2/suballoc.h @@ -49,7 +49,7 @@ struct ocfs2_alloc_context { /* these are used by the chain search */ u16 ac_chain; - int ac_allow_chain_relink; + int ac_disable_chain_relink; group_search_t *ac_group_search; u64 ac_last_group; -- GitLab From 6ee1df3bff435d169d0ab93420bd02b4f9392e66 Mon Sep 17 00:00:00 2001 From: Tomas Henzl Date: Wed, 27 Feb 2013 17:03:32 -0800 Subject: [PATCH 1767/1799] block: fix ext_devt_idr handling commit 7b74e912785a11572da43292786ed07ada7e3e0c upstream. While adding and removing a lot of disks disks and partitions this sometimes shows up: WARNING: at fs/sysfs/dir.c:512 sysfs_add_one+0xc9/0x130() (Not tainted) Hardware name: sysfs: cannot create duplicate filename '/dev/block/259:751' Modules linked in: raid1 autofs4 bnx2fc cnic uio fcoe libfcoe libfc 8021q scsi_transport_fc scsi_tgt garp stp llc sunrpc cpufreq_ondemand powernow_k8 freq_table mperf ipv6 dm_mirror dm_region_hash dm_log power_meter microcode dcdbas serio_raw amd64_edac_mod edac_core edac_mce_amd i2c_piix4 i2c_core k10temp bnx2 sg ixgbe dca mdio ext4 mbcache jbd2 dm_round_robin sr_mod cdrom sd_mod crc_t10dif ata_generic pata_acpi pata_atiixp ahci mptsas mptscsih mptbase scsi_transport_sas dm_multipath dm_mod [last unloaded: scsi_wait_scan] Pid: 44103, comm: async/16 Not tainted 2.6.32-195.el6.x86_64 #1 Call Trace: warn_slowpath_common+0x87/0xc0 warn_slowpath_fmt+0x46/0x50 sysfs_add_one+0xc9/0x130 sysfs_do_create_link+0x12b/0x170 sysfs_create_link+0x13/0x20 device_add+0x317/0x650 idr_get_new+0x13/0x50 add_partition+0x21c/0x390 rescan_partitions+0x32b/0x470 sd_open+0x81/0x1f0 [sd_mod] __blkdev_get+0x1b6/0x3c0 blkdev_get+0x10/0x20 register_disk+0x155/0x170 add_disk+0xa6/0x160 sd_probe_async+0x13b/0x210 [sd_mod] add_wait_queue+0x46/0x60 async_thread+0x102/0x250 default_wake_function+0x0/0x20 async_thread+0x0/0x250 kthread+0x96/0xa0 child_rip+0xa/0x20 kthread+0x0/0xa0 child_rip+0x0/0x20 This most likely happens because dev_t is freed while the number is still used and idr_get_new() is not protected on every use. The fix adds a mutex where it wasn't before and moves the dev_t free function so it is called after device del. Signed-off-by: Tomas Henzl Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 6 +++++- block/partition-generic.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 9cf5583c90ff..9433636b88bb 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -420,14 +420,18 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt) do { if (!idr_pre_get(&ext_devt_idr, GFP_KERNEL)) return -ENOMEM; + mutex_lock(&ext_devt_mutex); rc = idr_get_new(&ext_devt_idr, part, &idx); + mutex_unlock(&ext_devt_mutex); } while (rc == -EAGAIN); if (rc) return rc; if (idx > MAX_EXT_DEVT) { + mutex_lock(&ext_devt_mutex); idr_remove(&ext_devt_idr, idx); + mutex_unlock(&ext_devt_mutex); return -EBUSY; } @@ -644,7 +648,6 @@ void del_gendisk(struct gendisk *disk) disk_part_iter_exit(&piter); invalidate_partition(disk, 0); - blk_free_devt(disk_to_dev(disk)->devt); set_capacity(disk, 0); disk->flags &= ~GENHD_FL_UP; @@ -662,6 +665,7 @@ void del_gendisk(struct gendisk *disk) if (!sysfs_deprecated) sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk))); device_del(disk_to_dev(disk)); + blk_free_devt(disk_to_dev(disk)->devt); } EXPORT_SYMBOL(del_gendisk); diff --git a/block/partition-generic.c b/block/partition-generic.c index 6df5d6928a44..7b8b8d17764c 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c @@ -249,11 +249,11 @@ void delete_partition(struct gendisk *disk, int partno) if (!part) return; - blk_free_devt(part_devt(part)); rcu_assign_pointer(ptbl->part[partno], NULL); rcu_assign_pointer(ptbl->last_lookup, NULL); kobject_put(part->holder_dir); device_del(part_to_dev(part)); + blk_free_devt(part_devt(part)); hd_struct_put(part); } -- GitLab From f8cf1124a8f6cdd4ebc834ec3d848508e229e1d4 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 20 Dec 2012 10:31:11 +0000 Subject: [PATCH 1768/1799] xen-blkback: do not leak mode property commit 9d092603cc306ee6edfe917bf9ab8beb5f32d7bc upstream. "be->mode" is obtained from xenbus_read(), which does a kmalloc() for the message body. The short string is never released, so do it along with freeing "be" itself, and make sure the string isn't kept when backend_changed() doesn't complete successfully (which made it desirable to slightly re-structure that function, so that the error cleanup can be done in one place). Reported-by: Olaf Hering Signed-off-by: Jan Beulich Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/block/xen-blkback/xenbus.c | 49 +++++++++++++++--------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 4f66171c6683..a155254f1338 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -367,6 +367,7 @@ static int xen_blkbk_remove(struct xenbus_device *dev) be->blkif = NULL; } + kfree(be->mode); kfree(be); dev_set_drvdata(&dev->dev, NULL); return 0; @@ -502,6 +503,7 @@ static void backend_changed(struct xenbus_watch *watch, = container_of(watch, struct backend_info, backend_watch); struct xenbus_device *dev = be->dev; int cdrom = 0; + unsigned long handle; char *device_type; DPRINTK(""); @@ -521,10 +523,10 @@ static void backend_changed(struct xenbus_watch *watch, return; } - if ((be->major || be->minor) && - ((be->major != major) || (be->minor != minor))) { - pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n", - be->major, be->minor, major, minor); + if (be->major | be->minor) { + if (be->major != major || be->minor != minor) + pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n", + be->major, be->minor, major, minor); return; } @@ -542,36 +544,33 @@ static void backend_changed(struct xenbus_watch *watch, kfree(device_type); } - if (be->major == 0 && be->minor == 0) { - /* Front end dir is a number, which is used as the handle. */ - - char *p = strrchr(dev->otherend, '/') + 1; - long handle; - err = strict_strtoul(p, 0, &handle); - if (err) - return; + /* Front end dir is a number, which is used as the handle. */ + err = strict_strtoul(strrchr(dev->otherend, '/') + 1, 0, &handle); + if (err) + return; - be->major = major; - be->minor = minor; + be->major = major; + be->minor = minor; - err = xen_vbd_create(be->blkif, handle, major, minor, - (NULL == strchr(be->mode, 'w')), cdrom); - if (err) { - be->major = 0; - be->minor = 0; - xenbus_dev_fatal(dev, err, "creating vbd structure"); - return; - } + err = xen_vbd_create(be->blkif, handle, major, minor, + !strchr(be->mode, 'w'), cdrom); + if (err) + xenbus_dev_fatal(dev, err, "creating vbd structure"); + else { err = xenvbd_sysfs_addif(dev); if (err) { xen_vbd_free(&be->blkif->vbd); - be->major = 0; - be->minor = 0; xenbus_dev_fatal(dev, err, "creating sysfs entries"); - return; } + } + if (err) { + kfree(be->mode); + be->mode = NULL; + be->major = 0; + be->minor = 0; + } else { /* We're potentially connected now */ xen_update_blkif_status(be->blkif); } -- GitLab From c93c85196e2c7001daa8a04b83a9d6dd4febfb59 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 16 Jan 2013 11:36:23 -0500 Subject: [PATCH 1769/1799] xen/blkback: Don't trust the handle from the frontend. commit 01c681d4c70d64cb72142a2823f27c4146a02e63 upstream. The 'handle' is the device that the request is from. For the life-time of the ring we copy it from a request to a response so that the frontend is not surprised by it. But we do not need it - when we start processing I/Os we have our own 'struct phys_req' which has only most essential information about the request. In fact the 'vbd_translate' ends up over-writing the preq.dev with a value from the backend. This assignment of preq.dev with the 'handle' value is superfluous so lets not do it. Acked-by: Jan Beulich Acked-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/block/xen-blkback/blkback.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index c6decb901e5e..73d8c9276b9b 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -623,7 +623,6 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, goto fail_response; } - preq.dev = req->u.rw.handle; preq.sector_number = req->u.rw.sector_number; preq.nr_sects = 0; -- GitLab From a8aa6d32035120fdfef09ccb88c694047013eb7b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 27 Feb 2013 17:03:34 -0800 Subject: [PATCH 1770/1799] idr: fix a subtle bug in idr_get_next() commit 6cdae7416a1c45c2ce105a78187d9b7e8feb9e24 upstream. The iteration logic of idr_get_next() is borrowed mostly verbatim from idr_for_each(). It walks down the tree looking for the slot matching the current ID. If the matching slot is not found, the ID is incremented by the distance of single slot at the given level and repeats. The implementation assumes that during the whole iteration id is aligned to the layer boundaries of the level closest to the leaf, which is true for all iterations starting from zero or an existing element and thus is fine for idr_for_each(). However, idr_get_next() may be given any point and if the starting id hits in the middle of a non-existent layer, increment to the next layer will end up skipping the same offset into it. For example, an IDR with IDs filled between [64, 127] would look like the following. [ 0 64 ... ] /----/ | | | NULL [ 64 ... 127 ] If idr_get_next() is called with 63 as the starting point, it will try to follow down the pointer from 0. As it is NULL, it will then try to proceed to the next slot in the same level by adding the slot distance at that level which is 64 - making the next try 127. It goes around the loop and finds and returns 127 skipping [64, 126]. Note that this bug also triggers in idr_for_each_entry() loop which deletes during iteration as deletions can make layers go away leaving the iteration with unaligned ID into missing layers. Fix it by ensuring proceeding to the next slot doesn't carry over the unaligned offset - ie. use round_up(id + 1, slot_distance) instead of id += slot_distance. Signed-off-by: Tejun Heo Reported-by: David Teigland Cc: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- lib/idr.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/idr.c b/lib/idr.c index 4046e29c0a99..e90d2d05d784 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -625,7 +625,14 @@ void *idr_get_next(struct idr *idp, int *nextidp) return p; } - id += 1 << n; + /* + * Proceed to the next layer at the current level. Unlike + * idr_for_each(), @id isn't guaranteed to be aligned to + * layer boundary at this point and adding 1 << n may + * incorrectly skip IDs. Make sure we jump to the + * beginning of the next layer using round_up(). + */ + id = round_up(id + 1, 1 << n); while (n < fls(id)) { n += IDR_BITS; p = *--paa; -- GitLab From 303ee54c72f488b90c2355977c1619a08db6ed9c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 27 Feb 2013 17:03:56 -0800 Subject: [PATCH 1771/1799] block: fix synchronization and limit check in blk_alloc_devt() commit ce23bba842aee98092225d9576dba47c82352521 upstream. idr allocation in blk_alloc_devt() wasn't synchronized against lookup and removal, and its limit check was off by one - 1 << MINORBITS is the number of minors allowed, not the maximum allowed minor. Add locking and rename MAX_EXT_DEVT to NR_EXT_DEVT and fix limit checking. Signed-off-by: Tejun Heo Acked-by: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 9433636b88bb..60108d9fa04f 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -25,7 +25,7 @@ static DEFINE_MUTEX(block_class_lock); struct kobject *block_depr; /* for extended dynamic devt allocation, currently only one major is used */ -#define MAX_EXT_DEVT (1 << MINORBITS) +#define NR_EXT_DEVT (1 << MINORBITS) /* For extended devt allocation. ext_devt_mutex prevents look up * results from going away underneath its user. @@ -422,19 +422,16 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt) return -ENOMEM; mutex_lock(&ext_devt_mutex); rc = idr_get_new(&ext_devt_idr, part, &idx); + if (!rc && idx >= NR_EXT_DEVT) { + idr_remove(&ext_devt_idr, idx); + rc = -EBUSY; + } mutex_unlock(&ext_devt_mutex); } while (rc == -EAGAIN); if (rc) return rc; - if (idx > MAX_EXT_DEVT) { - mutex_lock(&ext_devt_mutex); - idr_remove(&ext_devt_idr, idx); - mutex_unlock(&ext_devt_mutex); - return -EBUSY; - } - *devt = MKDEV(BLOCK_EXT_MAJOR, blk_mangle_minor(idx)); return 0; } -- GitLab From ef7a6c344031cd99e16a116a7984d9428dce8401 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 27 Feb 2013 17:04:04 -0800 Subject: [PATCH 1772/1799] firewire: add minor number range check to fw_device_init() commit 3bec60d511179853138836ae6e1b61fe34d9235f upstream. fw_device_init() didn't check whether the allocated minor number isn't too large. Fail if it goes overflows MINORBITS. Signed-off-by: Tejun Heo Suggested-by: Stefan Richter Acked-by: Stefan Richter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/firewire/core-device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index 68109e9bb04e..04ebeaf8cffe 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -999,6 +999,10 @@ static void fw_device_init(struct work_struct *work) ret = idr_pre_get(&fw_device_idr, GFP_KERNEL) ? idr_get_new(&fw_device_idr, device, &minor) : -ENOMEM; + if (minor >= 1 << MINORBITS) { + idr_remove(&fw_device_idr, minor); + minor = -ENOSPC; + } up_write(&fw_device_rwsem); if (ret < 0) -- GitLab From d48e3a8dc45d9eac3e2be330ef4df663a6f54dfc Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 27 Feb 2013 17:05:21 -0800 Subject: [PATCH 1773/1799] sysctl: fix null checking in bin_dn_node_address() commit df1778be1a33edffa51d094eeda87c858ded6560 upstream. The null check of `strchr() + 1' is broken, which is always non-null, leading to OOB read. Instead, check the result of strchr(). Signed-off-by: Xi Wang Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/sysctl_binary.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c index a650694883a1..9f9aa3205973 100644 --- a/kernel/sysctl_binary.c +++ b/kernel/sysctl_binary.c @@ -1194,9 +1194,10 @@ static ssize_t bin_dn_node_address(struct file *file, /* Convert the decnet address to binary */ result = -EIO; - nodep = strchr(buf, '.') + 1; + nodep = strchr(buf, '.'); if (!nodep) goto out; + ++nodep; area = simple_strtoul(buf, NULL, 10); node = simple_strtoul(nodep, NULL, 10); -- GitLab From 0f600ee1431404eb87d36b84a66ccc004c5ace9b Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 30 Jan 2013 00:28:01 +0100 Subject: [PATCH 1774/1799] fs: Fix possible use-after-free with AIO commit 54c807e71d5ac59dee56c685f2b66e27cd54c475 upstream. Running AIO is pinning inode in memory using file reference. Once AIO is completed using aio_complete(), file reference is put and inode can be freed from memory. So we have to be sure that calling aio_complete() is the last thing we do with the inode. Acked-by: Jeff Moyer CC: Christoph Hellwig CC: Jens Axboe CC: Jeff Moyer Signed-off-by: Jan Kara Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- fs/direct-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/direct-io.c b/fs/direct-io.c index f4aadd15b613..29c4fdab29db 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -305,9 +305,9 @@ static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret, bool is dio->end_io(dio->iocb, offset, transferred, dio->private, ret, is_async); } else { + inode_dio_done(dio->inode); if (is_async) aio_complete(dio->iocb, ret, 0); - inode_dio_done(dio->inode); } return ret; -- GitLab From f74e995c9ba5963cd8d6ef91abe8f49d9614b423 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 27 Nov 2012 13:35:09 -0300 Subject: [PATCH 1775/1799] media: rc: unlock on error in show_protocols() commit 30ebc5e44d057a1619ad63fe32c8c1670c37c4b8 upstream. We recently introduced a new return -ENODEV in this function but we need to unlock before returning. [mchehab@redhat.com: found two patches with the same fix. Merged SOB's/acks into one patch] Acked-by: Herton R. Krzesinski Signed-off-by: Dan Carpenter Signed-off-by: Douglas Bagnall Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/rc/rc-main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index cabc19c10515..cec1f8c05e67 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -778,8 +778,10 @@ static ssize_t show_protocols(struct device *device, } else if (dev->raw) { enabled = dev->raw->enabled_protocols; allowed = ir_raw_get_allowed_protocols(); - } else + } else { + mutex_unlock(&dev->lock); return -ENODEV; + } IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", (long long)allowed, -- GitLab From ced2decfe31ba7b7b97cce2de010f75e8a90b412 Mon Sep 17 00:00:00 2001 From: Eryu Guan Date: Sat, 12 Jan 2013 16:33:25 -0500 Subject: [PATCH 1776/1799] ext4: check bh in ext4_read_block_bitmap() commit 15b49132fc972c63894592f218ea5a9a61b1a18f upstream. Validate the bh pointer before using it, since ext4_read_block_bitmap_nowait() might return NULL. I've seen this in fsfuzz testing. EXT4-fs error (device loop0): ext4_read_block_bitmap_nowait:385: comm touch: Cannot get buffer for block bitmap - block_group = 0, block_bitmap = 3925999616 BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] ext4_wait_block_bitmap+0x25/0xe0 ... Call Trace: [] ext4_read_block_bitmap+0x35/0x60 [] ext4_free_blocks+0x236/0xb80 [] ? __getblk+0x36/0x70 [] ? __find_get_block+0x8f/0x210 [] ? kmem_cache_free+0x33/0x140 [] ext4_xattr_release_block+0x1b5/0x1d0 [] ext4_xattr_delete_inode+0xbe/0x100 [] ext4_free_inode+0x7c/0x4d0 [] ? ext4_mark_inode_dirty+0x88/0x230 [] ext4_evict_inode+0x32c/0x490 [] evict+0xa7/0x1c0 [] iput_final+0xe3/0x170 [] iput+0x3e/0x50 [] ext4_add_nondir+0x4d/0x90 [] ext4_create+0xeb/0x170 [] vfs_create+0xac/0xd0 [] lookup_open+0x185/0x1c0 [] ? selinux_inode_permission+0xa9/0x170 [] do_last+0x2d4/0x7a0 [] path_openat+0xb3/0x480 [] ? handle_mm_fault+0x251/0x3b0 [] do_filp_open+0x49/0xa0 [] ? __alloc_fd+0xdd/0x150 [] do_sys_open+0x108/0x1f0 [] sys_open+0x21/0x30 [] system_call_fastpath+0x16/0x1b Also fix comment for ext4_read_block_bitmap_nowait() Signed-off-by: Eryu Guan Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/balloc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index df76291d692b..bb74d7f0f353 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -326,7 +326,7 @@ static int ext4_valid_block_bitmap(struct super_block *sb, return 0; } /** - * ext4_read_block_bitmap() + * ext4_read_block_bitmap_nowait() * @sb: super block * @block_group: given block group * @@ -422,6 +422,8 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group) struct buffer_head *bh; bh = ext4_read_block_bitmap_nowait(sb, block_group); + if (!bh) + return NULL; if (ext4_wait_block_bitmap(sb, block_group, bh)) { put_bh(bh); return NULL; -- GitLab From 51e26006d1c9d5a2609d1bb6b7899cd86f92eed9 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Fri, 1 Feb 2013 21:31:27 -0500 Subject: [PATCH 1777/1799] ext4: fix race in ext4_mb_add_n_trim() commit f1167009711032b0d747ec89a632a626c901a1ad upstream. In ext4_mb_add_n_trim(), lg_prealloc_lock should be taken when changing the lg_prealloc_list. Signed-off-by: Niu Yawei Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/mballoc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index e77c4fe665a0..3122ece15147 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4126,7 +4126,7 @@ static void ext4_mb_add_n_trim(struct ext4_allocation_context *ac) /* The max size of hash table is PREALLOC_TB_SIZE */ order = PREALLOC_TB_SIZE - 1; /* Add the prealloc space to lg */ - rcu_read_lock(); + spin_lock(&lg->lg_prealloc_lock); list_for_each_entry_rcu(tmp_pa, &lg->lg_prealloc_list[order], pa_inode_list) { spin_lock(&tmp_pa->pa_lock); @@ -4150,12 +4150,12 @@ static void ext4_mb_add_n_trim(struct ext4_allocation_context *ac) if (!added) list_add_tail_rcu(&pa->pa_inode_list, &lg->lg_prealloc_list[order]); - rcu_read_unlock(); + spin_unlock(&lg->lg_prealloc_lock); /* Now trim the list to be not more than 8 elements */ if (lg_prealloc_count > 8) { ext4_mb_discard_lg_preallocations(sb, lg, - order, lg_prealloc_count); + order, lg_prealloc_count); return; } return ; -- GitLab From 19c9740ba7362357bde91267a0aa5109a809cd3e Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Mon, 18 Feb 2013 12:12:07 -0500 Subject: [PATCH 1778/1799] ext4: fix xattr block allocation/release with bigalloc commit 1231b3a1eb5740192aeebf5344dd6d6da000febf upstream. Currently when new xattr block is created or released we we would call dquot_free_block() or dquot_alloc_block() respectively, among the else decrementing or incrementing the number of blocks assigned to the inode by one block. This however does not work for bigalloc file system because we always allocate/free the whole cluster so we have to count with that in dquot_free_block() and dquot_alloc_block() as well. Use the clusters-to-blocks conversion EXT4_C2B() when passing number of blocks to the dquot_alloc/free functions to fix the problem. The problem has been revealed by xfstests #117 (and possibly others). Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" Reviewed-by: Eric Sandeen Signed-off-by: Greg Kroah-Hartman --- fs/ext4/xattr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index e88748e55c0f..e712a8cb1653 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -495,7 +495,7 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, error = ext4_handle_dirty_metadata(handle, inode, bh); if (IS_SYNC(inode)) ext4_handle_sync(handle); - dquot_free_block(inode, 1); + dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1)); ea_bdebug(bh, "refcount now=%d; releasing", le32_to_cpu(BHDR(bh)->h_refcount)); } @@ -784,7 +784,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, else { /* The old block is released after updating the inode. */ - error = dquot_alloc_block(inode, 1); + error = dquot_alloc_block(inode, + EXT4_C2B(EXT4_SB(sb), 1)); if (error) goto cleanup; error = ext4_journal_get_write_access(handle, @@ -880,7 +881,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, return error; cleanup_dquot: - dquot_free_block(inode, 1); + dquot_free_block(inode, EXT4_C2B(EXT4_SB(sb), 1)); goto cleanup; bad_block: -- GitLab From 4234fb29a8c0a5c5eaee6de38fe3cba674daecd0 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Fri, 22 Feb 2013 15:27:52 -0500 Subject: [PATCH 1779/1799] ext4: fix free clusters calculation in bigalloc filesystem commit 304e220f0879198b1f5309ad6f0be862b4009491 upstream. ext4_has_free_clusters() should tell us whether there is enough free clusters to allocate, however number of free clusters in the file system is converted to blocks using EXT4_C2B() which is not only wrong use of the macro (we should have used EXT4_NUM_B2C) but it's also completely wrong concept since everything else is in cluster units. Moreover when calculating number of root clusters we should be using macro EXT4_NUM_B2C() instead of EXT4_B2C() otherwise the result might be off by one. However r_blocks_count should always be a multiple of the cluster ratio so doing a plain bit shift should be enough here. We avoid using EXT4_B2C() because it's confusing. As a result of the first problem number of free clusters is much bigger than it should have been and ext4_has_free_clusters() would return 1 even if there is really not enough free clusters available. Fix this by removing the EXT4_C2B() conversion of free clusters and using bit shift when calculating number of root clusters. This bug affects number of xfstests tests covering file system ENOSPC situation handling. With this patch most of the ENOSPC problems with bigalloc file system disappear, especially the errors caused by delayed allocation not having enough space when the actual allocation is finally requested. Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/balloc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index bb74d7f0f353..3e1018ace702 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -449,11 +449,16 @@ static int ext4_has_free_clusters(struct ext4_sb_info *sbi, free_clusters = percpu_counter_read_positive(fcc); dirty_clusters = percpu_counter_read_positive(dcc); - root_clusters = EXT4_B2C(sbi, ext4_r_blocks_count(sbi->s_es)); + + /* + * r_blocks_count should always be multiple of the cluster ratio so + * we are safe to do a plane bit shift only. + */ + root_clusters = ext4_r_blocks_count(sbi->s_es) >> sbi->s_cluster_bits; if (free_clusters - (nclusters + root_clusters + dirty_clusters) < EXT4_FREECLUSTERS_WATERMARK) { - free_clusters = EXT4_C2B(sbi, percpu_counter_sum_positive(fcc)); + free_clusters = percpu_counter_sum_positive(fcc); dirty_clusters = percpu_counter_sum_positive(dcc); } /* Check whether we have space after accounting for current -- GitLab From 5623a7cc4e3f0f461586b10b78967bb5f53fa096 Mon Sep 17 00:00:00 2001 From: majianpeng Date: Tue, 29 Jan 2013 13:16:06 +0800 Subject: [PATCH 1780/1799] nfsd: Fix memleak commit 2d32b29a1c2830f7c42caa8258c714acd983961f upstream. When free nfs-client, it must free the ->cl_stateids. Signed-off-by: Jianpeng Ma Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4state.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 537731e4c160..abd785e5fd2d 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1053,6 +1053,8 @@ free_client(struct nfs4_client *clp) put_group_info(clp->cl_cred.cr_group_info); kfree(clp->cl_principal); kfree(clp->cl_name.data); + idr_remove_all(&clp->cl_stateids); + idr_destroy(&clp->cl_stateids); kfree(clp); } -- GitLab From 7e5e167c5c1b44f408fa8f8a8f062f234cd0f0d6 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Sun, 10 Feb 2013 11:33:48 -0500 Subject: [PATCH 1781/1799] svcrpc: make svc_age_temp_xprts enqueue under sv_lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e75bafbff2270993926abcc31358361db74a9bc2 upstream. svc_age_temp_xprts expires xprts in a two-step process: first it takes the sv_lock and moves the xprts to expire off their server-wide list (sv_tempsocks or sv_permsocks) to a local list. Then it drops the sv_lock and enqueues and puts each one. I see no reason for this: svc_xprt_enqueue() will take sp_lock, but the sv_lock and sp_lock are not otherwise nested anywhere (and documentation at the top of this file claims it's correct to nest these with sp_lock inside.) Tested-by: Jason Tibbitts Tested-by: Paweł Sikora Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/svc_xprt.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index fd9b2889aa94..aec7dbb9d3dd 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -817,7 +817,6 @@ static void svc_age_temp_xprts(unsigned long closure) struct svc_serv *serv = (struct svc_serv *)closure; struct svc_xprt *xprt; struct list_head *le, *next; - LIST_HEAD(to_be_aged); dprintk("svc_age_temp_xprts\n"); @@ -838,25 +837,15 @@ static void svc_age_temp_xprts(unsigned long closure) if (atomic_read(&xprt->xpt_ref.refcount) > 1 || test_bit(XPT_BUSY, &xprt->xpt_flags)) continue; - svc_xprt_get(xprt); - list_move(le, &to_be_aged); + list_del_init(le); set_bit(XPT_CLOSE, &xprt->xpt_flags); set_bit(XPT_DETACHED, &xprt->xpt_flags); - } - spin_unlock_bh(&serv->sv_lock); - - while (!list_empty(&to_be_aged)) { - le = to_be_aged.next; - /* fiddling the xpt_list node is safe 'cos we're XPT_DETACHED */ - list_del_init(le); - xprt = list_entry(le, struct svc_xprt, xpt_list); - dprintk("queuing xprt %p for closing\n", xprt); /* a thread will dequeue and close it soon */ svc_xprt_enqueue(xprt); - svc_xprt_put(xprt); } + spin_unlock_bh(&serv->sv_lock); mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ); } -- GitLab From 94dcb26bbbed1851e0a7fb16165207c2c61e545f Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 26 Nov 2012 05:57:27 +0000 Subject: [PATCH 1782/1799] vhost: fix length for cross region descriptor commit bd97120fc3d1a11f3124c7c9ba1d91f51829eb85 upstream. If a single descriptor crosses a region, the second chunk length should be decremented by size translated so far, instead it includes the full descriptor length. Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/vhost/vhost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 51e4c1eeec4f..1a9e2a9b8560 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1074,7 +1074,7 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len, } _iov = iov + ret; size = reg->memory_size - addr + reg->guest_phys_addr; - _iov->iov_len = min((u64)len, size); + _iov->iov_len = min((u64)len - s, size); _iov->iov_base = (void __user *)(unsigned long) (reg->userspace_addr + addr - reg->guest_phys_addr); s += size; -- GitLab From 146207bbadeb4578334d6e26b9b690df8aeb1a3d Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 4 Feb 2013 15:57:42 +0100 Subject: [PATCH 1783/1799] fuse: don't WARN when nlink is zero commit dfca7cebc2679f3d129f8e680a8f199a7ad16e38 upstream. drop_nlink() warns if nlink is already zero. This is triggerable by a buggy userspace filesystem. The cure, I think, is worse than the disease so disable the warning. Reported-by: Tero Roponen Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman --- fs/fuse/dir.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index bc438320cac5..d48478a864b0 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -645,7 +645,14 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) spin_lock(&fc->lock); fi->attr_version = ++fc->attr_version; - drop_nlink(inode); + /* + * If i_nlink == 0 then unlink doesn't make sense, yet this can + * happen if userspace filesystem is careless. It would be + * difficult to enforce correct nlink usage so just ignore this + * condition here + */ + if (inode->i_nlink > 0) + drop_nlink(inode); spin_unlock(&fc->lock); fuse_invalidate_attr(inode); fuse_invalidate_attr(dir); -- GitLab From 57ef0d83d393b0f1f378a6b18a7394c62caadafa Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 4 Feb 2013 19:39:52 +0000 Subject: [PATCH 1784/1799] unbreak automounter support on 64-bit kernel with 32-bit userspace (v2) commit 4f4ffc3a5398ef9bdbb32db04756d7d34e356fcf upstream. automount-support is broken on the parisc architecture, because the existing #if list does not include a check for defined(__hppa__). The HPPA (parisc) architecture is similiar to other 64bit Linux targets where we have to define autofs_wqt_t (which is passed back and forth to user space) as int type which has a size of 32bit across 32 and 64bit kernels. During the discussion on the mailing list, H. Peter Anvin suggested to invert the #if list since only specific platforms (specifically those who do not have a 32bit userspace, like IA64 and Alpha) should have autofs_wqt_t as unsigned long type. This suggestion is probably the best way to go, since Arm64 (and maybe others?) seems to have a non-working automounter. So in the long run even for other new upcoming architectures this inverted check seem to be the best solution, since it will not require them to change this #if again (unless they are 64bit only). Signed-off-by: Helge Deller Acked-by: H. Peter Anvin Acked-by: Ian Kent Acked-by: Catalin Marinas CC: James Bottomley CC: Rolf Eike Beer Signed-off-by: Greg Kroah-Hartman --- include/linux/auto_fs.h | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/include/linux/auto_fs.h b/include/linux/auto_fs.h index da64e15004b6..6cdabb422de6 100644 --- a/include/linux/auto_fs.h +++ b/include/linux/auto_fs.h @@ -31,25 +31,16 @@ #define AUTOFS_MIN_PROTO_VERSION AUTOFS_PROTO_VERSION /* - * Architectures where both 32- and 64-bit binaries can be executed - * on 64-bit kernels need this. This keeps the structure format - * uniform, and makes sure the wait_queue_token isn't too big to be - * passed back down to the kernel. - * - * This assumes that on these architectures: - * mode 32 bit 64 bit - * ------------------------- - * int 32 bit 32 bit - * long 32 bit 64 bit - * - * If so, 32-bit user-space code should be backwards compatible. + * The wait_queue_token (autofs_wqt_t) is part of a structure which is passed + * back to the kernel via ioctl from userspace. On architectures where 32- and + * 64-bit userspace binaries can be executed it's important that the size of + * autofs_wqt_t stays constant between 32- and 64-bit Linux kernels so that we + * do not break the binary ABI interface by changing the structure size. */ - -#if defined(__sparc__) || defined(__mips__) || defined(__x86_64__) \ - || defined(__powerpc__) || defined(__s390__) -typedef unsigned int autofs_wqt_t; -#else +#if defined(__ia64__) || defined(__alpha__) /* pure 64bit architectures */ typedef unsigned long autofs_wqt_t; +#else +typedef unsigned int autofs_wqt_t; #endif /* Packet types */ -- GitLab From 06f924f163e4426ce6a8d4cf61b45f2fc8eaeecc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 20 Jan 2013 21:55:20 +0100 Subject: [PATCH 1785/1799] ath9k_hw: fix calibration issues on chainmask that don't include chain 0 commit 4a8f199508d79ff8a7d1e22f47b912baaf225336 upstream. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: CAI Qian Reviewed-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 2 ++ drivers/net/wireless/ath/ath9k/ar9003_phy.c | 2 +- drivers/net/wireless/ath/ath9k/hw.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 63089cc1fafd..9284bca6e16e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -938,6 +938,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, AR_PHY_CL_TAB_1, AR_PHY_CL_TAB_2 }; + ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); + if (rtt) { if (!ar9003_hw_rtt_restore(ah, chan)) run_rtt_cal = true; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 600aca9fe6b1..f86ee0c7f314 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -543,7 +543,7 @@ static void ar9003_hw_init_bb(struct ath_hw *ah, udelay(synthDelay + BASE_ACTIVATE_DELAY); } -static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) +void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) { switch (rx) { case 0x5: diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index f8e1fbbbfc5e..d5c5dca3d367 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -1014,6 +1014,7 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); int ar9003_paprd_init_table(struct ath_hw *ah); bool ar9003_paprd_is_done(struct ath_hw *ah); void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains); +void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); /* Hardware family op attach helpers */ void ar5008_hw_attach_phy_ops(struct ath_hw *ah); -- GitLab From 68412b1718c488e58783d1c576d0aeb34012092d Mon Sep 17 00:00:00 2001 From: Seiji Aguchi Date: Fri, 11 Jan 2013 18:09:41 +0000 Subject: [PATCH 1786/1799] pstore: Avoid deadlock in panic and emergency-restart path commit 9f244e9cfd70c7c0f82d3c92ce772ab2a92d9f64 upstream. [Issue] When pstore is in panic and emergency-restart paths, it may be blocked in those paths because it simply takes spin_lock. This is an example scenario which pstore may hang up in a panic path: - cpuA grabs psinfo->buf_lock - cpuB panics and calls smp_send_stop - smp_send_stop sends IRQ to cpuA - after 1 second, cpuB gives up on cpuA and sends an NMI instead - cpuA is now in an NMI handler while still holding buf_lock - cpuB is deadlocked This case may happen if a firmware has a bug and cpuA is stuck talking with it more than one second. Also, this is a similar scenario in an emergency-restart path: - cpuA grabs psinfo->buf_lock and stucks in a firmware - cpuB kicks emergency-restart via either sysrq-b or hangcheck timer. And then, cpuB is deadlocked by taking psinfo->buf_lock again. [Solution] This patch avoids the deadlocking issues in both panic and emergency_restart paths by introducing a function, is_non_blocking_path(), to check if a cpu can be blocked in current path. With this patch, pstore is not blocked even if another cpu has taken a spin_lock, in those paths by changing from spin_lock_irqsave to spin_trylock_irqsave. In addition, according to a comment of emergency_restart() in kernel/sys.c, spin_lock shouldn't be taken in an emergency_restart path to avoid deadlock. This patch fits the comment below. /** * emergency_restart - reboot the system * * Without shutting down any hardware or taking any locks * reboot the system. This is called when we know we are in * trouble so this is our best effort to reboot. This is * safe to call in interrupt context. */ void emergency_restart(void) Signed-off-by: Seiji Aguchi Acked-by: Don Zickus Signed-off-by: Tony Luck Cc: CAI Qian Signed-off-by: Greg Kroah-Hartman --- fs/pstore/platform.c | 35 +++++++++++++++++++++++++++++------ include/linux/pstore.h | 6 ++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 82c585f715e3..4a66a5c4a63f 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -88,6 +88,27 @@ static const char *get_reason_str(enum kmsg_dump_reason reason) } } +bool pstore_cannot_block_path(enum kmsg_dump_reason reason) +{ + /* + * In case of NMI path, pstore shouldn't be blocked + * regardless of reason. + */ + if (in_nmi()) + return true; + + switch (reason) { + /* In panic case, other cpus are stopped by smp_send_stop(). */ + case KMSG_DUMP_PANIC: + /* Emergency restart shouldn't be blocked by spin lock. */ + case KMSG_DUMP_EMERG: + return true; + default: + return false; + } +} +EXPORT_SYMBOL_GPL(pstore_cannot_block_path); + /* * callback from kmsg_dump. (s2,l2) has the most recently * written bytes, older bytes are in (s1,l1). Save as much @@ -111,10 +132,12 @@ static void pstore_dump(struct kmsg_dumper *dumper, why = get_reason_str(reason); - if (in_nmi()) { - is_locked = spin_trylock(&psinfo->buf_lock); - if (!is_locked) - pr_err("pstore dump routine blocked in NMI, may corrupt error record\n"); + if (pstore_cannot_block_path(reason)) { + is_locked = spin_trylock_irqsave(&psinfo->buf_lock, flags); + if (!is_locked) { + pr_err("pstore dump routine blocked in %s path, may corrupt error record\n" + , in_nmi() ? "NMI" : why); + } } else spin_lock_irqsave(&psinfo->buf_lock, flags); oopscount++; @@ -145,9 +168,9 @@ static void pstore_dump(struct kmsg_dumper *dumper, total += l1_cpy + l2_cpy; part++; } - if (in_nmi()) { + if (pstore_cannot_block_path(reason)) { if (is_locked) - spin_unlock(&psinfo->buf_lock); + spin_unlock_irqrestore(&psinfo->buf_lock, flags); } else spin_unlock_irqrestore(&psinfo->buf_lock, flags); } diff --git a/include/linux/pstore.h b/include/linux/pstore.h index e1461e143be2..318cca1dee9b 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -54,12 +54,18 @@ struct pstore_info { #ifdef CONFIG_PSTORE extern int pstore_register(struct pstore_info *); +extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason); #else static inline int pstore_register(struct pstore_info *psi) { return -ENODEV; } +static inline bool +pstore_cannot_block_path(enum kmsg_dump_reason reason) +{ + return false; +} #endif #endif /*_LINUX_PSTORE_H*/ -- GitLab From a74e9a386f6e775f88061f7958b8b34c6742f926 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Fri, 25 Jan 2013 16:08:01 +0800 Subject: [PATCH 1787/1799] cpuset: fix cpuset_print_task_mems_allowed() vs rename() race commit 63f43f55c9bbc14f76b582644019b8a07dc8219a upstream. rename() will change dentry->d_name. The result of this race can be worse than seeing partially rewritten name, but we might access a stale pointer because rename() will re-allocate memory to hold a longer name. It's safe in the protection of dentry->d_lock. v2: check NULL dentry before acquiring dentry lock. Signed-off-by: Li Zefan Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- kernel/cpuset.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 5fc1570e64c1..8fe6f6b65006 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2479,8 +2479,16 @@ void cpuset_print_task_mems_allowed(struct task_struct *tsk) dentry = task_cs(tsk)->css.cgroup->dentry; spin_lock(&cpuset_buffer_lock); - snprintf(cpuset_name, CPUSET_NAME_LEN, - dentry ? (const char *)dentry->d_name.name : "/"); + + if (!dentry) { + strcpy(cpuset_name, "/"); + } else { + spin_lock(&dentry->d_lock); + strlcpy(cpuset_name, (const char *)dentry->d_name.name, + CPUSET_NAME_LEN); + spin_unlock(&dentry->d_lock); + } + nodelist_scnprintf(cpuset_nodelist, CPUSET_NODELIST_LEN, tsk->mems_allowed); printk(KERN_INFO "%s cpuset=%s mems_allowed=%s\n", -- GitLab From 916b6c67cd471fafa3e5e53ce8389c36749ed6f1 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Thu, 24 Jan 2013 14:43:28 +0800 Subject: [PATCH 1788/1799] cgroup: fix exit() vs rmdir() race commit 71b5707e119653039e6e95213f00479668c79b75 upstream. In cgroup_exit() put_css_set_taskexit() is called without any lock, which might lead to accessing a freed cgroup: thread1 thread2 --------------------------------------------- exit() cgroup_exit() put_css_set_taskexit() atomic_dec(cgrp->count); rmdir(); /* not safe !! */ check_for_release(cgrp); rcu_read_lock() can be used to make sure the cgroup is alive. Signed-off-by: Li Zefan Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- kernel/cgroup.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index a5dccd4c2360..a4c47d1b3cec 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -378,12 +378,20 @@ static void __put_css_set(struct css_set *cg, int taskexit) struct cgroup *cgrp = link->cgrp; list_del(&link->cg_link_list); list_del(&link->cgrp_link_list); + + /* + * We may not be holding cgroup_mutex, and if cgrp->count is + * dropped to 0 the cgroup can be destroyed at any time, hence + * rcu_read_lock is used to keep it alive. + */ + rcu_read_lock(); if (atomic_dec_and_test(&cgrp->count) && notify_on_release(cgrp)) { if (taskexit) set_bit(CGRP_RELEASABLE, &cgrp->flags); check_for_release(cgrp); } + rcu_read_unlock(); kfree(link); } -- GitLab From f9a8884a35a74f1fb9f12a17f62331bdc6eac2af Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 17 Jan 2013 14:21:53 +0000 Subject: [PATCH 1789/1799] ab8500-chargalg: Only root should have write permission on sysfs file commit e3455002d04276c256a531f7175dce0f7d1cb78a upstream. Only root should have write permission on sysfs file ab8500_chargalg/chargalg. Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/power/abx500_chargalg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c index 804b88c760d6..d8cd1517c842 100644 --- a/drivers/power/abx500_chargalg.c +++ b/drivers/power/abx500_chargalg.c @@ -1698,7 +1698,7 @@ static ssize_t abx500_chargalg_sysfs_charger(struct kobject *kobj, static struct attribute abx500_chargalg_en_charger = \ { .name = "chargalg", - .mode = S_IWUGO, + .mode = S_IWUSR, }; static struct attribute *abx500_chargalg_chg[] = { -- GitLab From 7eb0fad53ef76201d81a2e9e1bad5b68a457e4e3 Mon Sep 17 00:00:00 2001 From: "Rajanikanth H.V" Date: Wed, 23 Jan 2013 09:56:45 +0530 Subject: [PATCH 1790/1799] ab8500_btemp: Demote initcall sequence commit eeb0751c99522a4d1bbcc7b6bc1460cd07d07488 upstream. Power supply subsystem creates thermal zone device for the property 'POWER_SUPPLY_PROP_TEMP' which requires thermal subsystem to be ready before 'ab8500 battery temperature monitor' driver is initialized. ab8500 btemp driver is initialized with subsys_initcall whereas thermal subsystem is initialized with fs_initcall which causes thermal_zone_device_register(...) to crash since the required structure 'thermal_class' is not initialized yet: Unable to handle kernel NULL pointer dereference at virtual address 000000a4 pgd = c0004000 [000000a4] *pgd=00000000 Internal error: Oops: 5 [#1] PREEMPT SMP ARM Modules linked in: CPU: 0 Tainted: G W (3.8.0-rc4-00001-g632fda8-dirty #1) PC is at _raw_spin_lock+0x18/0x54 LR is at get_device_parent+0x50/0x1b8 pc : [] lr : [] psr: 60000013 sp : ef04bdc8 ip : 00000000 fp : c0446180 r10: ef216e38 r9 : c03af5d0 r8 : ef275c18 r7 : 00000000 r6 : c0476c14 r5 : ef275c18 r4 : ef095840 r3 : ef04a000 r2 : 00000001 r1 : 00000000 r0 : 000000a4 Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel Control: 10c5787d Table: 0000404a DAC: 00000015 Process swapper/0 (pid: 1, stack limit = 0xef04a238) Stack: (0xef04bdc8 to 0xef04c000) [...] [] (_raw_spin_lock+0x18/0x54) from [] (get_device_parent+0x50/0x1b8) [] (get_device_parent+0x50/0x1b8) from [] (device_add+0xa4/0x574) [] (device_add+0xa4/0x574) from [] (thermal_zone_device_register+0x118/0x938) [] (thermal_zone_device_register+0x118/0x938) from [] (power_supply_register+0x170/0x1f8) [] (power_supply_register+0x170/0x1f8) from [] (ab8500_btemp_probe+0x208/0x47c) [] (ab8500_btemp_probe+0x208/0x47c) from [] (platform_drv_probe+0x14/0x18) [] (platform_drv_probe+0x14/0x18) from [] (driver_probe_device+0x74/0x20c) [] (driver_probe_device+0x74/0x20c) from [] (__driver_attach+0x8c/0x90) [] (__driver_attach+0x8c/0x90) from [] (bus_for_each_dev+0x4c/0x80) [] (bus_for_each_dev+0x4c/0x80) from [] (bus_add_driver+0x16c/0x23c) [] (bus_add_driver+0x16c/0x23c) from [] (driver_register+0x78/0x14c) [] (driver_register+0x78/0x14c) from [] (do_one_initcall+0xfc/0x164) [] (do_one_initcall+0xfc/0x164) from [] (kernel_init+0x120/0x2b8) [] (kernel_init+0x120/0x2b8) from [] (ret_from_fork+0x14/0x3c) Code: e3c3303f e5932004 e2822001 e5832004 (e1903f9f) ---[ end trace ed9df72941b5bada ]--- Signed-off-by: Rajanikanth H.V Signed-off-by: Anton Vorontsov Signed-off-by: Greg Kroah-Hartman --- drivers/power/ab8500_btemp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index d8bb99394ac0..2a6bf76baac4 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c @@ -1115,7 +1115,7 @@ static void __exit ab8500_btemp_exit(void) platform_driver_unregister(&ab8500_btemp_driver); } -subsys_initcall_sync(ab8500_btemp_init); +device_initcall(ab8500_btemp_init); module_exit(ab8500_btemp_exit); MODULE_LICENSE("GPL v2"); -- GitLab From 427e85ba0d2e3811c130714eea3fec0800ef2fcd Mon Sep 17 00:00:00 2001 From: Joseph Salisbury Date: Tue, 5 Feb 2013 00:16:29 +0000 Subject: [PATCH 1791/1799] ACPI: Add DMI entry for Sony VGN-FW41E_H commit 66f2fda93b67fa744d406e6dcf443f67bac204b6 upstream. This patch adds a quirk to allow the Sony VGN-FW41E_H to suspend/resume properly. References: http://bugs.launchpad.net/bugs/1113547 Signed-off-by: Joseph Salisbury Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/sleep.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index aa0a904e5631..189c704a950f 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -186,6 +186,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { }, { .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-FW41E_H", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW41E_H"), + }, + }, + { + .callback = init_nvs_nosave, .ident = "Sony Vaio VGN-FW21E", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), -- GitLab From 1e05b9964644382e9994e62dc5c8eb815e5225fa Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 27 Feb 2013 12:52:45 +0000 Subject: [PATCH 1792/1799] staging: comedi: ni_labpc: correct differential channel sequence for AI commands Commit 4c4bc25d0fa6beaf054c0b4c3b324487f266c820 upstream. Tuomas reported problems getting meaningful output from a Lab-PC+ in differential mode for AI cmds, but AI insn reads gave correct readings. He tracked it down to two problems, one of which is addressed by this patch. It seems the setting of the channel bits for particular scanning modes was incorrect for differential mode. (Only half the number of channels are available in differential mode; comedi refers to them as channels 0, 1, 2 and 3, but the hardware documentation refers to them as channels 0, 2, 4 and 6.) In differential mode, the setting of the channel enable bits in the command1 register should depend on whether the scan enable bit is set. Effectively, we need to double the comedi channel number when the scan enable bit is not set in differential mode. The scan enable bit gets set when the AI scan mode is `MODE_MULT_CHAN_UP` or `MODE_MULT_CHAN_DOWN`, and gets cleared when the AI scan mode is `MODE_SINGLE_CHAN` or `MODE_SINGLE_CHAN_INTERVAL`. The existing test for whether the comedi channel number needs to be doubled in differential mode is incorrect in `labpc_ai_cmd()`. This patch corrects the test. Thanks to Tuomas for suggesting the fix. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 721b2be22500..9b876e0ab245 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -1264,7 +1264,9 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) else channel = CR_CHAN(cmd->chanlist[0]); /* munge channel bits for differential / scan disabled mode */ - if (labpc_ai_scan_mode(cmd) != MODE_SINGLE_CHAN && aref == AREF_DIFF) + if ((labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN || + labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN_INTERVAL) && + aref == AREF_DIFF) channel *= 2; devpriv->command1_bits |= ADC_CHAN_BITS(channel); devpriv->command1_bits |= thisboard->ai_range_code[range]; -- GitLab From e4cd1e4dba29c756272c2ee9d06b094b4319b90a Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 27 Feb 2013 12:52:46 +0000 Subject: [PATCH 1793/1799] staging: comedi: ni_labpc: set up command4 register *after* command3 Commit 22056e2b46246d97ff0f7c6e21a77b8daa07f02c upstream. Tuomas reported problems getting meaningful output from a Lab-PC+ in differential mode for AI cmds, but AI insn reads gave correct readings. He tracked it down to two problems, one of which is addressed by this patch. It seems that writing to the command3 register after writing to the command4 register in `labpc_ai_cmd()` messes up the differential reference bit setting in the command4 register. Set up the command4 register after the command3 register (as in `labpc_ai_rinsn()`) to avoid the problem. Thanks to Tuomas for suggesting the fix. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 31 ++++++++++++----------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 9b876e0ab245..0517a2315efc 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -1282,21 +1282,6 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG); } - /* setup any external triggering/pacing (command4 register) */ - devpriv->command4_bits = 0; - if (cmd->convert_src != TRIG_EXT) - devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT; - /* XXX should discard first scan when using interval scanning - * since manual says it is not synced with scan clock */ - if (labpc_use_continuous_mode(cmd) == 0) { - devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT; - if (cmd->scan_begin_src == TRIG_EXT) - devpriv->command4_bits |= EXT_SCAN_EN_BIT; - } - /* single-ended/differential */ - if (aref == AREF_DIFF) - devpriv->command4_bits |= ADC_DIFF_BIT; - devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG); devpriv->write_byte(cmd->chanlist_len, dev->iobase + INTERVAL_COUNT_REG); @@ -1376,6 +1361,22 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->command3_bits &= ~ADC_FNE_INTR_EN_BIT; devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); + /* setup any external triggering/pacing (command4 register) */ + devpriv->command4_bits = 0; + if (cmd->convert_src != TRIG_EXT) + devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT; + /* XXX should discard first scan when using interval scanning + * since manual says it is not synced with scan clock */ + if (labpc_use_continuous_mode(cmd) == 0) { + devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT; + if (cmd->scan_begin_src == TRIG_EXT) + devpriv->command4_bits |= EXT_SCAN_EN_BIT; + } + /* single-ended/differential */ + if (aref == AREF_DIFF) + devpriv->command4_bits |= ADC_DIFF_BIT; + devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG); + /* startup acquisition */ /* command2 reg */ -- GitLab From 0685b5924819447dad0413312b508e68168a1ee2 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 27 Feb 2013 10:56:19 +0000 Subject: [PATCH 1794/1799] staging: comedi: check s->async for poll(), read() and write() commit cc400e185c07c15a42d2635995f422de5b94b696 upstream. Some low-level comedi drivers (incorrectly) point `dev->read_subdev` or `dev->write_subdev` to a subdevice that does not support asynchronous commands. Comedi's poll(), read() and write() file operation handlers assume these subdevices do support asynchronous commands. In particular, they assume `s->async` is valid (where `s` points to the read or write subdevice), which it won't be if it has been set incorrectly. This can lead to a NULL pointer dereference. Check `s->async` is non-NULL in `comedi_poll()`, `comedi_read()` and `comedi_write()` to avoid the bug. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index cf67ce54f46f..3799cf1c2b64 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1577,7 +1577,7 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait) mask = 0; read_subdev = comedi_get_read_subdevice(dev_file_info); - if (read_subdev) { + if (read_subdev && read_subdev->async) { poll_wait(file, &read_subdev->async->wait_head, wait); if (!read_subdev->busy || comedi_buf_read_n_available(read_subdev->async) > 0 @@ -1587,7 +1587,7 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait) } } write_subdev = comedi_get_write_subdevice(dev_file_info); - if (write_subdev) { + if (write_subdev && write_subdev->async) { poll_wait(file, &write_subdev->async->wait_head, wait); comedi_buf_write_alloc(write_subdev->async, write_subdev->async->prealloc_bufsz); @@ -1629,7 +1629,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, } s = comedi_get_write_subdevice(dev_file_info); - if (s == NULL) { + if (s == NULL || s->async == NULL) { retval = -EIO; goto done; } @@ -1740,7 +1740,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, } s = comedi_get_read_subdevice(dev_file_info); - if (s == NULL) { + if (s == NULL || s->async == NULL) { retval = -EIO; goto done; } -- GitLab From 3f14f68ff0121c770930b061fe23008af45006a2 Mon Sep 17 00:00:00 2001 From: Vinson Lee Date: Tue, 26 Feb 2013 18:30:30 -0800 Subject: [PATCH 1795/1799] perf tools: Fix build with bison 2.3 and older. commit 85df3b3769222894e9692b383c7af124b7721086 upstream. The %name-prefix "prefix" syntax is not available on bison 2.3 and older. Substitute with the -p "prefix" command-line option for compatibility with older versions of bison. This patch fixes this build error with older versions of bison. CC util/sysfs.o BISON util/pmu-bison.c util/pmu.y:2.14-24: syntax error, unexpected string, expecting = make: *** [util/pmu-bison.c] Error 1 Signed-off-by: Vinson Lee Tested-by: Li Zefan Cc: Ingo Molnar Cc: Jiri Olsa Cc: Li Zefan Cc: Namhyung Kim Cc: Paul Mackerras Cc: Pekka Enberg Link: http://lkml.kernel.org/r/1360792138-29186-1-git-send-email-vlee@twitter.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Greg Kroah-Hartman --- tools/perf/Makefile | 4 ++-- tools/perf/util/parse-events.y | 1 - tools/perf/util/pmu.y | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index c3dd3d4424fe..2db7ba001c63 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -241,13 +241,13 @@ $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c: util/parse-events.y - $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c + $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c -p parse_events_ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c: util/pmu.y - $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c + $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_ $(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index d9637da7333c..3f35ea3f5047 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -1,5 +1,4 @@ -%name-prefix "parse_events_" %parse-param {struct list_head *list_all} %parse-param {struct list_head *list_event} %parse-param {int *idx} diff --git a/tools/perf/util/pmu.y b/tools/perf/util/pmu.y index 20ea77e93169..522943f7bfdf 100644 --- a/tools/perf/util/pmu.y +++ b/tools/perf/util/pmu.y @@ -1,5 +1,4 @@ -%name-prefix "perf_pmu_" %parse-param {struct list_head *format} %parse-param {char *name} -- GitLab From 78b6767929e77f40b455b115d1643b82678b6a26 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Fri, 25 Jan 2013 11:57:05 -0800 Subject: [PATCH 1796/1799] ata_piix: IDE-mode SATA patch for Intel Avoton DeviceIDs commit aaa515277db9585eeb4fdeb4637b9f9df50a1dd9 upstream. This patch adds the IDE-mode SATA DeviceIDs for the Intel Avoton SOC. Signed-off-by: Seth Heasley 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 3c809bfbccf5..00a01be1e502 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -331,6 +331,14 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (DH89xxCC) */ { 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Avoton) */ + { 0x8086, 0x1f20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Avoton) */ + { 0x8086, 0x1f21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Avoton) */ + { 0x8086, 0x1f30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Avoton) */ + { 0x8086, 0x1f31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, { } /* terminate list */ }; -- GitLab From a059654e30e7f0d0aaba17a44165332443d3f48e Mon Sep 17 00:00:00 2001 From: James Ralston Date: Fri, 8 Feb 2013 17:24:12 -0800 Subject: [PATCH 1797/1799] ata_piix: Add Device IDs for Intel Wellsburg PCH commit 3aee8bc52c415aba8148f144e5e5359b0fd75dd1 upstream. This patch adds the IDE-mode SATA Device IDs for the Intel Wellsburg PCH Signed-off-by: James Ralston Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ata_piix.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 00a01be1e502..88f6908c31fe 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -339,6 +339,15 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x1f30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (Avoton) */ { 0x8086, 0x1f31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Wellsburg) */ + { 0x8086, 0x8d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Wellsburg) */ + { 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Wellsburg) */ + { 0x8086, 0x8d60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Wellsburg) */ + { 0x8086, 0x8d68, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + { } /* terminate list */ }; -- GitLab From e7e24f96cacd091ecd6ed0a4c10c83daae28f3c4 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Mon, 12 Nov 2012 02:57:03 -0300 Subject: [PATCH 1798/1799] usb hid quirks for Masterkit MA901 usb radio commit 0322bd3980b3ebf7dde8474e22614cb443d6479a upstream. Don't let Masterkit MA901 USB radio be handled by usb hid drivers. This device will be handled by radio-ma901.c driver. Signed-off-by: Alexey Klimov Acked-by: Hans Verkuil Acked-by: Jiri Kosina Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 1a92a271adb6..ff73d60cfc7f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1922,6 +1922,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) }, { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) }, { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MASTERKIT, USB_DEVICE_ID_MASTERKIT_MA901RADIO) }, { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) }, { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 55838995eca3..02f4664478bd 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -520,6 +520,9 @@ #define USB_VENDOR_ID_MADCATZ 0x0738 #define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540 +#define USB_VENDOR_ID_MASTERKIT 0x16c0 +#define USB_DEVICE_ID_MASTERKIT_MA901RADIO 0x05df + #define USB_VENDOR_ID_MCC 0x09db #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a -- GitLab From 2713e2797a78a0fdda765bc5ad7fed41e94818ba Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 4 Mar 2013 06:07:21 +0800 Subject: [PATCH 1799/1799] Linux 3.4.35 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 250be36a8180..282e8da323d3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 34 +SUBLEVEL = 35 EXTRAVERSION = NAME = Saber-toothed Squirrel -- GitLab