From 7f77897ef2b6a5ee4eb8bc24fe8b1f3eab254328 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Tue, 24 May 2011 11:43:18 +0200 Subject: [PATCH 001/595] HID: hiddev: fix potential use-after-free Commit 6cb4b040795 ("HID: hiddev: fix race between hiddev_disconnect and hiddev_release") made it possible to access hiddev (for unlocking the existance mutex) once hiddev has been kfreed. Change the order so that this can not happen (always unlock the mutex first, it is needed only to protect access to ->exist and ->open). Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index ff3c644888b1..4985f485932f 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -923,10 +923,11 @@ void hiddev_disconnect(struct hid_device *hid) usb_deregister_dev(usbhid->intf, &hiddev_class); if (hiddev->open) { + mutex_unlock(&hiddev->existancelock); usbhid_close(hiddev->hid); wake_up_interruptible(&hiddev->wait); } else { + mutex_unlock(&hiddev->existancelock); kfree(hiddev); } - mutex_unlock(&hiddev->existancelock); } From e23be0a27dcc9297ff0495360d89bc5b0bf12383 Mon Sep 17 00:00:00 2001 From: Jimmy Hon Date: Fri, 20 May 2011 17:59:19 -0400 Subject: [PATCH 002/595] HID: add quirk for HyperPen 10000U Add 5543:0064 UC-Logic Technology Corp. Aiptek HyperPen 10000U to quirks with HID_QUIRK_MULTI_INPUT. Originally the device is reporting the x,y coordinates on Z and RX. By adding this quirk, there will be two kernel devices. The first one is muted and the second device will report coordinates on X and Y. Signed-off-by: Jimmy Hon Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 0b374a6d6db0..2bbaad70d76d 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -622,6 +622,7 @@ #define USB_VENDOR_ID_UCLOGIC 0x5543 #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 +#define USB_DEVICE_ID_UCLOGIC_TABLET_TWA60 0x0064 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 0e30b140edca..621959d5cc42 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -74,6 +74,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, From 8c127f0717b438e6abc3d92d4ae248c4224b9dcb Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Wed, 25 May 2011 09:24:32 -0700 Subject: [PATCH 003/595] Input: properly assign return value of clamp() macro. [dtor@mail.ru: added mousedev changes] Signed-off-by: Hans Petter Selasky Cc: stable@kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 2 +- drivers/input/mousedev.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/input/input.c b/drivers/input/input.c index 75e11c7b70fd..da38d97a51b1 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1756,7 +1756,7 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev) } else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) { mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum - dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1, - clamp(mt_slots, 2, 32); + mt_slots = clamp(mt_slots, 2, 32); } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) { mt_slots = 2; } else { diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 257e033986e4..0110b5a3a167 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -187,7 +187,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, if (size == 0) size = xres ? : 1; - clamp(value, min, max); + value = clamp(value, min, max); mousedev->packet.x = ((value - min) * xres) / size; mousedev->packet.abs_event = 1; @@ -201,7 +201,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, if (size == 0) size = yres ? : 1; - clamp(value, min, max); + value = clamp(value, min, max); mousedev->packet.y = yres - ((value - min) * yres) / size; mousedev->packet.abs_event = 1; From 5c699d7d3f94ee1dd934edea889b32f8279a4e65 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 26 May 2011 11:49:16 +0300 Subject: [PATCH 004/595] HID: hiddev: fix use after free in hiddev_release There are a couple use after free bugs here. Signed-off-by: Dan Carpenter [jkosina@suse.cz: removed already fixed hunk] Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 4985f485932f..7c1188b53c3e 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -248,12 +248,15 @@ static int hiddev_release(struct inode * inode, struct file * file) usbhid_close(list->hiddev->hid); usbhid_put_power(list->hiddev->hid); } else { + mutex_unlock(&list->hiddev->existancelock); kfree(list->hiddev); + kfree(list); + return 0; } } - kfree(list); mutex_unlock(&list->hiddev->existancelock); + kfree(list); return 0; } From 0f7e4c33eb2c40b1e9cc24d2eab6de5921bc619c Mon Sep 17 00:00:00 2001 From: Kohei Kaigai Date: Thu, 26 May 2011 14:59:25 -0400 Subject: [PATCH 005/595] selinux: fix case of names with whitespace/multibytes on /selinux/create I submit the patch again, according to patch submission convension. This patch enables to accept percent-encoded object names as forth argument of /selinux/create interface to avoid possible bugs when we give an object name including whitespace or multibutes. E.g) if and when a userspace object manager tries to create a new object named as "resolve.conf but fake", it shall give this name as the forth argument of the /selinux/create. But sscanf() logic in kernel space fetches only the part earlier than the first whitespace. In this case, selinux may unexpectedly answer a default security context configured to "resolve.conf", but it is bug. Although I could not test this patch on named TYPE_TRANSITION rules actually, But debug printk() message seems to me the logic works correctly. I assume the libselinux provides an interface to apply this logic transparently, so nothing shall not be changed from the viewpoint of application. Signed-off-by: KaiGai Kohei Signed-off-by: Eric Paris --- security/selinux/selinuxfs.c | 37 +++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index fde4e9d64bfd..19489042fdf7 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -29,6 +29,7 @@ #include #include #include +#include /* selinuxfs pseudo filesystem for exporting the security policy API. Based on the proc code and the fs/nfsd/nfsctl.c code. */ @@ -751,6 +752,14 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) return length; } +static inline int hexcode_to_int(int code) { + if (code == '\0' || !isxdigit(code)) + return -1; + if (isdigit(code)) + return code - '0'; + return tolower(code) - 'a' + 10; +} + static ssize_t sel_write_create(struct file *file, char *buf, size_t size) { char *scon = NULL, *tcon = NULL; @@ -785,8 +794,34 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) nargs = sscanf(buf, "%s %s %hu %s", scon, tcon, &tclass, namebuf); if (nargs < 3 || nargs > 4) goto out; - if (nargs == 4) + if (nargs == 4) { + /* + * If and when the name of new object to be queried contains + * either whitespace or multibyte characters, they shall be + * encoded based on the percentage-encoding rule. + * If not encoded, the sscanf logic picks up only left-half + * of the supplied name; splitted by a whitespace unexpectedly. + */ + char *r, *w; + int c1, c2; + + r = w = namebuf; + do { + c1 = *r++; + if (c1 == '+') + c1 = ' '; + else if (c1 == '%') { + if ((c1 = hexcode_to_int(*r++)) < 0) + goto out; + if ((c2 = hexcode_to_int(*r++)) < 0) + goto out; + c1 = (c1 << 4) | c2; + } + *w++ = c1; + } while (c1 != '\0'); + objname = namebuf; + } length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); if (length) From 27721a52d6c8e33327ec3cae9f730204be99d251 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Mon, 30 May 2011 10:24:47 +0900 Subject: [PATCH 006/595] gpio: Fix gpio-exynos4 build fails in mainline After the GPIO driver move, some symbols became selectable when they shouldn't be. Tighten the dependencies. Reported-by: Randy Dunlap Signed-off-by: Grant Likely --- drivers/gpio/Kconfig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 4a7f63143455..317199796c5f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -88,29 +88,29 @@ config GPIO_IT8761E config GPIO_EXYNOS4 bool "Samsung Exynos4 GPIO library support" - default y if CPU_EXYNOS4210 - depends on ARM + default y + depends on ARM && CPU_EXYNOS4210 help Say yes here to support Samsung Exynos4 series SoCs GPIO library config GPIO_PLAT_SAMSUNG bool "Samsung SoCs GPIO library support" - default y if SAMSUNG_GPIOLIB_4BIT - depends on ARM + default y + depends on ARM && SAMSUNG_GPIOLIB_4BIT help Say yes here to support Samsung SoCs GPIO library config GPIO_S5PC100 bool "Samsung S5PC100 GPIO library support" - default y if CPU_S5PC100 - depends on ARM + default y + depends on ARM && CPU_S5PC100 help Say yes here to support Samsung S5PC100 SoCs GPIO library config GPIO_S5PV210 bool "Samsung S5PV210/S5PC110 GPIO library support" - default y if CPU_S5PV210 - depends on ARM + default y + depends on ARM && CPU_S5PV210 help Say yes here to support Samsung S5PV210/S5PC110 SoCs GPIO library From cbf74cea070fa1f705de4712e25d9e56ae6543c7 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 30 May 2011 16:31:11 +0200 Subject: [PATCH 007/595] oprofile, x86: Add comments to IBS LVT offset initialization Adding a comment in the code as IBS LVT setup is not obvious at all ... Signed-off-by: Robert Richter --- arch/x86/kernel/apic/apic.c | 3 ++- arch/x86/oprofile/op_model_amd.c | 13 +++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index fabf01eff771..a0bf78a0918c 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -390,7 +390,8 @@ static unsigned int reserve_eilvt_offset(int offset, unsigned int new) /* * If mask=1, the LVT entry does not generate interrupts while mask=0 - * enables the vector. See also the BKDGs. + * enables the vector. See also the BKDGs. Must be called with + * preemption disabled. */ int setup_APIC_eilvt(u8 offset, u8 vector, u8 msg_type, u8 mask) diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 9fd8a567fe1e..9cbb710dc94b 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -609,16 +609,21 @@ static int setup_ibs_ctl(int ibs_eilvt_off) return 0; } +/* + * This runs only on the current cpu. We try to find an LVT offset and + * setup the local APIC. For this we must disable preemption. On + * success we initialize all nodes with this offset. This updates then + * the offset in the IBS_CTL per-node msr. The per-core APIC setup of + * the IBS interrupt vector is called from op_amd_setup_ctrs()/op_- + * amd_cpu_shutdown() using the new offset. + */ static int force_ibs_eilvt_setup(void) { int offset; int ret; - /* - * find the next free available EILVT entry, skip offset 0, - * pin search to this cpu - */ preempt_disable(); + /* find the next free available EILVT entry, skip offset 0 */ for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) { if (get_eilvt(offset)) break; From f01114cb59d670e9b4f2c335930dd57db96e9360 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 31 May 2011 12:26:55 +0200 Subject: [PATCH 008/595] sched: Fix cross-cpu clock sync on remote wakeups Markus reported that commit 317f394160e ("sched: Move the second half of ttwu() to the remote cpu") caused some accounting funnies on his AMD Phenom II X4, such as weird 'top' results. It turns out that this is due to non-synced TSC and the queued remote wakeups stopped coupeling the two relevant cpu clocks, which leads to wakeups seeing time jumps, which in turn lead to skewed runtime stats. Add an explicit call to sched_clock_cpu() to couple the per-cpu clocks to restore the normal flow of time. Reported-and-tested-by: Markus Trippelsdorf Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1306835745.2353.3.camel@twins Signed-off-by: Ingo Molnar --- kernel/sched.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/sched.c b/kernel/sched.c index cbb3a0eee58e..49cc70b152cf 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2600,6 +2600,7 @@ static void ttwu_queue(struct task_struct *p, int cpu) #if defined(CONFIG_SMP) if (sched_feat(TTWU_QUEUE) && cpu != smp_processor_id()) { + sched_clock_cpu(cpu); /* sync clocks x-cpu */ ttwu_queue_remote(p, cpu); return; } From f339b9dc1f03591761d5d930800db24bc0eda1e1 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 31 May 2011 10:49:20 +0200 Subject: [PATCH 009/595] sched: Fix schedstat.nr_wakeups_migrate While looking over the code I found that with the ttwu rework the nr_wakeups_migrate test broke since we now switch cpus prior to calling ttwu_stat(), hence the test is always true. Cure this by passing the migration state in wake_flags. Also move the whole test under CONFIG_SMP, its hard to migrate tasks on UP :-) Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-pwwxl7gdqs5676f1d4cx6pj7@git.kernel.org Signed-off-by: Ingo Molnar --- include/linux/sched.h | 1 + kernel/sched.c | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 8da84b7bc1b8..483c1ed5bc4d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1063,6 +1063,7 @@ struct sched_domain; */ #define WF_SYNC 0x01 /* waker goes to sleep after wakup */ #define WF_FORK 0x02 /* child wakeup after fork */ +#define WF_MIGRATED 0x04 /* internal use, task got migrated */ #define ENQUEUE_WAKEUP 1 #define ENQUEUE_HEAD 2 diff --git a/kernel/sched.c b/kernel/sched.c index 49cc70b152cf..2fe98ed474da 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2447,6 +2447,10 @@ ttwu_stat(struct task_struct *p, int cpu, int wake_flags) } rcu_read_unlock(); } + + if (wake_flags & WF_MIGRATED) + schedstat_inc(p, se.statistics.nr_wakeups_migrate); + #endif /* CONFIG_SMP */ schedstat_inc(rq, ttwu_count); @@ -2455,9 +2459,6 @@ ttwu_stat(struct task_struct *p, int cpu, int wake_flags) if (wake_flags & WF_SYNC) schedstat_inc(p, se.statistics.nr_wakeups_sync); - if (cpu != task_cpu(p)) - schedstat_inc(p, se.statistics.nr_wakeups_migrate); - #endif /* CONFIG_SCHEDSTATS */ } @@ -2675,8 +2676,10 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) p->sched_class->task_waking(p); cpu = select_task_rq(p, SD_BALANCE_WAKE, wake_flags); - if (task_cpu(p) != cpu) + if (task_cpu(p) != cpu) { + wake_flags |= WF_MIGRATED; set_task_cpu(p, cpu); + } #endif /* CONFIG_SMP */ ttwu_queue(p, cpu); From 74c355fbdfedd3820046dba4f537876cea54c207 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 30 May 2011 16:48:06 +0200 Subject: [PATCH 010/595] perf, cgroups: Fix up for new API Ben changed the cgroup API in commit f780bdb7c1c (cgroups: add per-thread subsystem callbacks) in an incompatible way, but forgot to convert the perf cgroup bits. Avoid compile warnings and runtime splats and convert perf too ;-) Acked-by: Ben Blum Cc: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1306767651.1200.2990.camel@twins Signed-off-by: Ingo Molnar --- kernel/events/core.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index c09767f7db3e..8a15944bf9d2 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7394,26 +7394,12 @@ static int __perf_cgroup_move(void *info) return 0; } -static void perf_cgroup_move(struct task_struct *task) +static void +perf_cgroup_attach_task(struct cgroup *cgrp, struct task_struct *task) { task_function_call(task, __perf_cgroup_move, task); } -static void perf_cgroup_attach(struct cgroup_subsys *ss, struct cgroup *cgrp, - struct cgroup *old_cgrp, struct task_struct *task, - bool threadgroup) -{ - perf_cgroup_move(task); - if (threadgroup) { - struct task_struct *c; - rcu_read_lock(); - list_for_each_entry_rcu(c, &task->thread_group, thread_group) { - perf_cgroup_move(c); - } - rcu_read_unlock(); - } -} - static void perf_cgroup_exit(struct cgroup_subsys *ss, struct cgroup *cgrp, struct cgroup *old_cgrp, struct task_struct *task) { @@ -7425,7 +7411,7 @@ static void perf_cgroup_exit(struct cgroup_subsys *ss, struct cgroup *cgrp, if (!(task->flags & PF_EXITING)) return; - perf_cgroup_move(task); + perf_cgroup_attach_task(cgrp, task); } struct cgroup_subsys perf_subsys = { @@ -7434,6 +7420,6 @@ struct cgroup_subsys perf_subsys = { .create = perf_cgroup_create, .destroy = perf_cgroup_destroy, .exit = perf_cgroup_exit, - .attach = perf_cgroup_attach, + .attach_task = perf_cgroup_attach_task, }; #endif /* CONFIG_CGROUP_PERF */ From 6ac6519b93065625119a347be1cbcc1b89edb773 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 26 May 2011 18:22:54 +0200 Subject: [PATCH 011/595] oprofile: Free potentially owned tasks in case of errors After registering the task free notifier we possibly have tasks in our dying_tasks list. Free them after unregistering the notifier in case of an error. Cc: # .36+ Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index a3984f4ef192..04250aa16f51 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -141,6 +141,13 @@ static struct notifier_block module_load_nb = { .notifier_call = module_load_notify, }; +static void free_all_tasks(void) +{ + /* make sure we don't leak task structs */ + process_task_mortuary(); + process_task_mortuary(); +} + int sync_start(void) { int err; @@ -174,6 +181,7 @@ int sync_start(void) profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); out2: task_handoff_unregister(&task_free_nb); + free_all_tasks(); out1: free_cpumask_var(marked_cpus); goto out; @@ -192,10 +200,7 @@ void sync_stop(void) mutex_unlock(&buffer_mutex); flush_cpu_work(); - /* make sure we don't leak task structs */ - process_task_mortuary(); - process_task_mortuary(); - + free_all_tasks(); free_cpumask_var(marked_cpus); } From 130c5ce716c9bfd1c2a2ec840a746eb7ff9ce1e6 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 26 May 2011 18:39:35 +0200 Subject: [PATCH 012/595] oprofile: Fix locking dependency in sync_start() This fixes the A->B/B->A locking dependency, see the warning below. The function task_exit_notify() is called with (task_exit_notifier) .rwsem set and then calls sync_buffer() which locks buffer_mutex. In sync_start() the buffer_mutex was set to prevent notifier functions to be started before sync_start() is finished. But when registering the notifier, (task_exit_notifier).rwsem is locked too, but now in different order than in sync_buffer(). In theory this causes a locking dependency, what does not occur in practice since task_exit_notify() is always called after the notifier is registered which means the lock is already released. However, after checking the notifier functions it turned out the buffer_mutex in sync_start() is unnecessary. This is because sync_buffer() may be called from the notifiers even if sync_start() did not finish yet, the buffers are already allocated but empty. No need to protect this with the mutex. So we fix this theoretical locking dependency by removing buffer_mutex in sync_start(). This is similar to the implementation before commit: 750d857 oprofile: fix crash when accessing freed task structs which introduced the locking dependency. Lockdep warning: oprofiled/4447 is trying to acquire lock: (buffer_mutex){+.+...}, at: [] sync_buffer+0x31/0x3ec [oprofile] but task is already holding lock: ((task_exit_notifier).rwsem){++++..}, at: [] __blocking_notifier_call_chain+0x39/0x67 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 ((task_exit_notifier).rwsem){++++..}: [] lock_acquire+0xf8/0x11e [] down_write+0x44/0x67 [] blocking_notifier_chain_register+0x52/0x8b [] profile_event_register+0x2d/0x2f [] sync_start+0x47/0xc6 [oprofile] [] oprofile_setup+0x60/0xa5 [oprofile] [] event_buffer_open+0x59/0x8c [oprofile] [] __dentry_open+0x1eb/0x308 [] nameidata_to_filp+0x60/0x67 [] do_last+0x5be/0x6b2 [] path_openat+0xc7/0x360 [] do_filp_open+0x3d/0x8c [] do_sys_open+0x110/0x1a9 [] sys_open+0x20/0x22 [] system_call_fastpath+0x16/0x1b -> #0 (buffer_mutex){+.+...}: [] __lock_acquire+0x1085/0x1711 [] lock_acquire+0xf8/0x11e [] mutex_lock_nested+0x63/0x309 [] sync_buffer+0x31/0x3ec [oprofile] [] task_exit_notify+0x16/0x1a [oprofile] [] notifier_call_chain+0x37/0x63 [] __blocking_notifier_call_chain+0x50/0x67 [] blocking_notifier_call_chain+0x14/0x16 [] profile_task_exit+0x1a/0x1c [] do_exit+0x2a/0x6fc [] do_group_exit+0x83/0xae [] sys_exit_group+0x17/0x1b [] system_call_fastpath+0x16/0x1b other info that might help us debug this: 1 lock held by oprofiled/4447: #0: ((task_exit_notifier).rwsem){++++..}, at: [] __blocking_notifier_call_chain+0x39/0x67 stack backtrace: Pid: 4447, comm: oprofiled Not tainted 2.6.39-00007-gcf4d8d4 #10 Call Trace: [] print_circular_bug+0xae/0xbc [] __lock_acquire+0x1085/0x1711 [] ? sync_buffer+0x31/0x3ec [oprofile] [] lock_acquire+0xf8/0x11e [] ? sync_buffer+0x31/0x3ec [oprofile] [] ? mark_lock+0x42f/0x552 [] ? sync_buffer+0x31/0x3ec [oprofile] [] mutex_lock_nested+0x63/0x309 [] ? sync_buffer+0x31/0x3ec [oprofile] [] sync_buffer+0x31/0x3ec [oprofile] [] ? __blocking_notifier_call_chain+0x39/0x67 [] ? __blocking_notifier_call_chain+0x39/0x67 [] task_exit_notify+0x16/0x1a [oprofile] [] notifier_call_chain+0x37/0x63 [] __blocking_notifier_call_chain+0x50/0x67 [] blocking_notifier_call_chain+0x14/0x16 [] profile_task_exit+0x1a/0x1c [] do_exit+0x2a/0x6fc [] ? retint_swapgs+0xe/0x13 [] do_group_exit+0x83/0xae [] sys_exit_group+0x17/0x1b [] system_call_fastpath+0x16/0x1b Reported-by: Marcin Slusarz Cc: Carl Love Cc: # .36+ Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 04250aa16f51..f34b5b29fb95 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -155,8 +155,6 @@ int sync_start(void) if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL)) return -ENOMEM; - mutex_lock(&buffer_mutex); - err = task_handoff_register(&task_free_nb); if (err) goto out1; @@ -173,7 +171,6 @@ int sync_start(void) start_cpu_work(); out: - mutex_unlock(&buffer_mutex); return err; out4: profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); @@ -190,14 +187,13 @@ int sync_start(void) void sync_stop(void) { - /* flush buffers */ - mutex_lock(&buffer_mutex); end_cpu_work(); unregister_module_notifier(&module_load_nb); profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); task_handoff_unregister(&task_free_nb); - mutex_unlock(&buffer_mutex); + barrier(); /* do all of the above first */ + flush_cpu_work(); free_all_tasks(); From fe47ae7f53e179d2ef6771024feb000cbb86640f Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 31 May 2011 12:35:41 +0200 Subject: [PATCH 013/595] oprofile, dcookies: Fix possible circular locking dependency The lockdep warning below detects a possible A->B/B->A locking dependency of mm->mmap_sem and dcookie_mutex. The order in sync_buffer() is mm->mmap_sem/dcookie_mutex, while in sys_lookup_dcookie() it is vice versa. Fixing it in sys_lookup_dcookie() by unlocking dcookie_mutex before copy_to_user(). oprofiled/4432 is trying to acquire lock: (&mm->mmap_sem){++++++}, at: [] might_fault+0x53/0xa3 but task is already holding lock: (dcookie_mutex){+.+.+.}, at: [] sys_lookup_dcookie+0x45/0x149 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (dcookie_mutex){+.+.+.}: [] lock_acquire+0xf8/0x11e [] mutex_lock_nested+0x63/0x309 [] get_dcookie+0x30/0x144 [] sync_buffer+0x196/0x3ec [oprofile] [] task_exit_notify+0x16/0x1a [oprofile] [] notifier_call_chain+0x37/0x63 [] __blocking_notifier_call_chain+0x50/0x67 [] blocking_notifier_call_chain+0x14/0x16 [] profile_task_exit+0x1a/0x1c [] do_exit+0x2a/0x6fc [] do_group_exit+0x83/0xae [] sys_exit_group+0x17/0x1b [] system_call_fastpath+0x16/0x1b -> #0 (&mm->mmap_sem){++++++}: [] __lock_acquire+0x1085/0x1711 [] lock_acquire+0xf8/0x11e [] might_fault+0x80/0xa3 [] sys_lookup_dcookie+0x104/0x149 [] system_call_fastpath+0x16/0x1b other info that might help us debug this: 1 lock held by oprofiled/4432: #0: (dcookie_mutex){+.+.+.}, at: [] sys_lookup_dcookie+0x45/0x149 stack backtrace: Pid: 4432, comm: oprofiled Not tainted 2.6.39-00008-ge5a450d #9 Call Trace: [] print_circular_bug+0xae/0xbc [] __lock_acquire+0x1085/0x1711 [] ? get_parent_ip+0x11/0x42 [] ? might_fault+0x53/0xa3 [] lock_acquire+0xf8/0x11e [] ? might_fault+0x53/0xa3 [] ? path_put+0x22/0x27 [] might_fault+0x80/0xa3 [] ? might_fault+0x53/0xa3 [] sys_lookup_dcookie+0x104/0x149 [] system_call_fastpath+0x16/0x1b References: https://bugzilla.kernel.org/show_bug.cgi?id=13809 Cc: # .27+ Signed-off-by: Robert Richter --- fs/dcookies.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/dcookies.c b/fs/dcookies.c index a21cabdbd87b..dda0dc702d1b 100644 --- a/fs/dcookies.c +++ b/fs/dcookies.c @@ -178,6 +178,8 @@ SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len) /* FIXME: (deleted) ? */ path = d_path(&dcs->path, kbuf, PAGE_SIZE); + mutex_unlock(&dcookie_mutex); + if (IS_ERR(path)) { err = PTR_ERR(path); goto out_free; @@ -194,6 +196,7 @@ SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len) out_free: kfree(kbuf); + return err; out: mutex_unlock(&dcookie_mutex); return err; From e5ac0bda96c495321dbad9b57a4b1a93a5a72e7f Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 25 May 2011 12:33:23 +0100 Subject: [PATCH 014/595] xen: use the trigger info we already have to choose the irq handler Do not use pirq_needs_eoi to decide which irq handler to use because Xen always returns true if the guest does not support pirq_eoi_map. Use the trigger information we already have from MP-tables and ACPI. Signed-off-by: Stefano Stabellini Reported-by: Thomas Goetz Tested-by: Thomas Goetz Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/events.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 3ff822b48145..553da68bd510 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -626,6 +626,9 @@ int xen_allocate_pirq_gsi(unsigned gsi) * * Note: We don't assign an event channel until the irq actually started * up. Return an existing irq if we've already got one for the gsi. + * + * Shareable implies level triggered, not shareable implies edge + * triggered here. */ int xen_bind_pirq_gsi_to_irq(unsigned gsi, unsigned pirq, int shareable, char *name) @@ -664,16 +667,13 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, pirq_query_unmask(irq); /* We try to use the handler with the appropriate semantic for the - * type of interrupt: if the interrupt doesn't need an eoi - * (pirq_needs_eoi returns false), we treat it like an edge - * triggered interrupt so we use handle_edge_irq. - * As a matter of fact this only happens when the corresponding - * physical interrupt is edge triggered or an msi. + * type of interrupt: if the interrupt is an edge triggered + * interrupt we use handle_edge_irq. * - * On the other hand if the interrupt needs an eoi (pirq_needs_eoi - * returns true) we treat it like a level triggered interrupt so we - * use handle_fasteoi_irq like the native code does for this kind of + * On the other hand if the interrupt is level triggered we use + * handle_fasteoi_irq like the native code does for this kind of * interrupts. + * * Depending on the Xen version, pirq_needs_eoi might return true * not only for level triggered interrupts but for edge triggered * interrupts too. In any case Xen always honors the eoi mechanism, @@ -681,7 +681,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, * hasn't received an eoi yet. Therefore using the fasteoi handler * is the right choice either way. */ - if (pirq_needs_eoi(irq)) + if (shareable) irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_fasteoi_irq, name); else From ebf30dc91cc8592cd72b004219cfc276b3ad2854 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 31 May 2011 16:10:00 -0700 Subject: [PATCH 015/595] msm: timer: Fix SMP build error Fix build breakage on SMP=y builds due to 0f7b332 (ARM: consolidate SMP cross call implementation, 2011-04-03) arch/arm/mach-msm/timer.c: In function 'local_timer_setup': arch/arm/mach-msm/timer.c:295: error: implicit declaration of function 'gic_enable_ppi' Signed-off-by: Stephen Boyd Signed-off-by: David Brown --- arch/arm/mach-msm/timer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 38b95e949d13..9bfdd5ad2441 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -23,6 +23,8 @@ #include #include +#include + #include #include From 9d2b909544bcdac337340a4b44d8c50d4da62bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Sun, 22 May 2011 04:56:32 -0300 Subject: [PATCH 016/595] [media] gspca - ov519: Fix a regression for ovfx2 webcams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By git commit c42cedbb658b, the bulk transfer size was changed to a lower value for resolutions != 1600x1200, but the image extraction routine still worked with the previous value, giving bad truncated images. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov519.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 36a46fc78734..5ac2f3c53710 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -4478,7 +4478,7 @@ static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, data, len); /* A short read signals EOF */ - if (len < OVFX2_BULK_SIZE) { + if (len < gspca_dev->cam.bulk_size) { /* If the frame is short, and it is one of the first ones the sensor and bridge are still syncing, so drop it. */ if (sd->first_frame) { From 9cf208e844d41441b3ad393d1da4f41fa3426795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Sun, 22 May 2011 05:05:11 -0300 Subject: [PATCH 017/595] [media] gspca - ov519: Change the ovfx2 bulk transfer size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'normal' bulk transfer size did not work for 800x600. By git commit c42cedbb658b, this 'normal' size was used for 1600x1200 only. It will now be used back again for all resolutions but 800x600. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov519.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 5ac2f3c53710..caf438ab88ff 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -609,7 +609,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { * buffers, there are some pretty strict real time constraints for * isochronous transfer for larger frame sizes). */ -/*jfm: this value works well for 1600x1200, but not 800x600 - see isoc_init */ +/*jfm: this value does not work for 800x600 - see isoc_init */ #define OVFX2_BULK_SIZE (13 * 4096) /* I2C registers */ @@ -3511,7 +3511,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev) switch (sd->bridge) { case BRIDGE_OVFX2: - if (gspca_dev->width == 1600) + if (gspca_dev->width != 800) gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE; else gspca_dev->cam.bulk_size = 7 * 4096; From 0e44173b1246261c8e29fe637017944a19a79869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Sun, 22 May 2011 05:36:33 -0300 Subject: [PATCH 018/595] [media] gspca: Remove coarse_expo_autogain.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This file is replaced by autogain_functions.h. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- .../media/video/gspca/coarse_expo_autogain.h | 116 ------------------ 1 file changed, 116 deletions(-) delete mode 100644 drivers/media/video/gspca/coarse_expo_autogain.h diff --git a/drivers/media/video/gspca/coarse_expo_autogain.h b/drivers/media/video/gspca/coarse_expo_autogain.h deleted file mode 100644 index 1cb9d941eaf6..000000000000 --- a/drivers/media/video/gspca/coarse_expo_autogain.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Auto gain algorithm for camera's with a coarse exposure control - * - * Copyright (C) 2010 Hans de Goede - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Autogain + exposure algorithm for cameras with a coarse exposure control - (usually this means we can only control the clockdiv to change exposure) - As changing the clockdiv so that the fps drops from 30 to 15 fps for - example, will lead to a huge exposure change (it effectively doubles), - this algorithm normally tries to only adjust the gain (between 40 and - 80 %) and if that does not help, only then changes exposure. This leads - to a much more stable image then using the knee algorithm which at - certain points of the knee graph will only try to adjust exposure, - which leads to oscilating as one exposure step is huge. - - Note this assumes that the sd struct for the cam in question has - exp_too_high_cnt and exp_too_high_cnt int members for use by this function. - - Returns 0 if no changes were made, 1 if the gain and or exposure settings - where changed. */ -static int gspca_coarse_grained_expo_autogain(struct gspca_dev *gspca_dev, - int avg_lum, int desired_avg_lum, int deadzone) -{ - int i, steps, gain, orig_gain, exposure, orig_exposure; - int gain_low, gain_high; - const struct ctrl *gain_ctrl = NULL; - const struct ctrl *exposure_ctrl = NULL; - struct sd *sd = (struct sd *) gspca_dev; - int retval = 0; - - for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { - if (gspca_dev->ctrl_dis & (1 << i)) - continue; - if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN) - gain_ctrl = &gspca_dev->sd_desc->ctrls[i]; - if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE) - exposure_ctrl = &gspca_dev->sd_desc->ctrls[i]; - } - if (!gain_ctrl || !exposure_ctrl) { - PDEBUG(D_ERR, "Error: gspca_coarse_grained_expo_autogain " - "called on cam without gain or exposure"); - return 0; - } - - if (gain_ctrl->get(gspca_dev, &gain) || - exposure_ctrl->get(gspca_dev, &exposure)) - return 0; - - orig_gain = gain; - orig_exposure = exposure; - gain_low = - (gain_ctrl->qctrl.maximum - gain_ctrl->qctrl.minimum) / 5 * 2; - gain_low += gain_ctrl->qctrl.minimum; - gain_high = - (gain_ctrl->qctrl.maximum - gain_ctrl->qctrl.minimum) / 5 * 4; - gain_high += gain_ctrl->qctrl.minimum; - - /* If we are of a multiple of deadzone, do multiple steps to reach the - desired lumination fast (with the risc of a slight overshoot) */ - steps = (desired_avg_lum - avg_lum) / deadzone; - - PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d", - avg_lum, desired_avg_lum, steps); - - if ((gain + steps) > gain_high && - sd->exposure < exposure_ctrl->qctrl.maximum) { - gain = gain_high; - sd->exp_too_low_cnt++; - } else if ((gain + steps) < gain_low && - sd->exposure > exposure_ctrl->qctrl.minimum) { - gain = gain_low; - sd->exp_too_high_cnt++; - } else { - gain += steps; - if (gain > gain_ctrl->qctrl.maximum) - gain = gain_ctrl->qctrl.maximum; - else if (gain < gain_ctrl->qctrl.minimum) - gain = gain_ctrl->qctrl.minimum; - sd->exp_too_high_cnt = 0; - sd->exp_too_low_cnt = 0; - } - - if (sd->exp_too_high_cnt > 3) { - exposure--; - sd->exp_too_high_cnt = 0; - } else if (sd->exp_too_low_cnt > 3) { - exposure++; - sd->exp_too_low_cnt = 0; - } - - if (gain != orig_gain) { - gain_ctrl->set(gspca_dev, gain); - retval = 1; - } - if (exposure != orig_exposure) { - exposure_ctrl->set(gspca_dev, exposure); - retval = 1; - } - - return retval; -} From 5ff01d54fe218be1b7e50fec30e111eb1bc224ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Mon, 23 May 2011 04:51:10 -0300 Subject: [PATCH 019/595] [media] gspca - stv06xx: Set a lower default value of gain for hdcs sensors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Many users said that the default gain value (128) was giving white images. The value which was in the original qc-usb driver (50) is better. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h index b538dce96f78..a14a84a5079b 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h @@ -125,7 +125,7 @@ #define HDCS_SLEEP_MODE (1 << 1) #define HDCS_DEFAULT_EXPOSURE 48 -#define HDCS_DEFAULT_GAIN 128 +#define HDCS_DEFAULT_GAIN 50 static int hdcs_probe_1x00(struct sd *sd); static int hdcs_probe_1020(struct sd *sd); From c8ef0a5b70a9821b3d75097aba672f531619231b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Mon, 23 May 2011 06:08:49 -0300 Subject: [PATCH 020/595] [media] gspca - ov519: Set the default frame rate to 15 fps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The frame rate variable was not initialized, so, the lowest frame rate was used for most webcams. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov519.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index caf438ab88ff..057e287b9152 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -3307,6 +3307,7 @@ static int sd_config(struct gspca_dev *gspca_dev, gspca_dev->cam.ctrls = sd->ctrls; sd->quality = QUALITY_DEF; + sd->frame_rate = 15; return 0; } @@ -3469,7 +3470,6 @@ static int sd_init(struct gspca_dev *gspca_dev) ARRAY_SIZE(init_519_ov7660)); write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660)); sd->gspca_dev.curr_mode = 1; /* 640x480 */ - sd->frame_rate = 15; ov519_set_mode(sd); ov519_set_fr(sd); sd->ctrls[COLORS].max = 4; /* 0..4 */ From 21d2e938d34d201276de3470587a3aa2047c77a1 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 24 May 2011 06:04:08 -0300 Subject: [PATCH 021/595] [media] anysee: return EOPNOTSUPP for unsupported I2C messages Check I2C messages and return error properly. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/anysee.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 4dc1ca333236..7c327b54308e 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -60,8 +60,6 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, int act_len, ret; u8 buf[64]; - if (slen > sizeof(buf)) - slen = sizeof(buf); memcpy(&buf[0], sbuf, slen); buf[60] = state->seq++; @@ -180,30 +178,37 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, { struct dvb_usb_device *d = i2c_get_adapdata(adap); int ret = 0, inc, i = 0; + u8 buf[52]; /* 4 + 48 (I2C WR USB command header + I2C WR max) */ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; while (i < num) { if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { - u8 buf[6]; + if (msg[i].len > 2 || msg[i+1].len > 60) { + ret = -EOPNOTSUPP; + break; + } buf[0] = CMD_I2C_READ; buf[1] = (msg[i].addr << 1) | 0x01; buf[2] = msg[i].buf[0]; buf[3] = msg[i].buf[1]; buf[4] = msg[i].len-1; buf[5] = msg[i+1].len; - ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf, + ret = anysee_ctrl_msg(d, buf, 6, msg[i+1].buf, msg[i+1].len); inc = 2; } else { - u8 buf[4+msg[i].len]; + if (msg[i].len > 48) { + ret = -EOPNOTSUPP; + break; + } buf[0] = CMD_I2C_WRITE; buf[1] = (msg[i].addr << 1); buf[2] = msg[i].len; buf[3] = 0x01; memcpy(&buf[4], msg[i].buf, msg[i].len); - ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); + ret = anysee_ctrl_msg(d, buf, 4 + msg[i].len, NULL, 0); inc = 1; } if (ret) From 7700a0d293ad8b1b1759ad06ac868f9a42fd0951 Mon Sep 17 00:00:00 2001 From: Ian Armstrong Date: Sun, 29 May 2011 20:09:24 -0300 Subject: [PATCH 022/595] [media] ivtv: Make two ivtv_msleep_timeout calls uninterruptable Two ivtv_msleep_timeout() calls are incorrectly flagged as interruptable. The first is in the init sequence for a capture and is required for stable hardware setup. The second is at the end of the capture and used to handle the last data transfer. Failure to wait for this last transfer can result in stale data being read at the start of the next capture. Signed-off-by: Ian Armstrong Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-streams.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 942683336555..e7794dc1330e 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -589,7 +589,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1); /* Avoid unpredictable PCI bus hang - disable video clocks */ v4l2_subdev_call(itv->sd_video, video, s_stream, 0); - ivtv_msleep_timeout(300, 1); + ivtv_msleep_timeout(300, 0); ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); v4l2_subdev_call(itv->sd_video, video, s_stream, 1); } @@ -834,7 +834,7 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) } /* Handle any pending interrupts */ - ivtv_msleep_timeout(100, 1); + ivtv_msleep_timeout(100, 0); } atomic_dec(&itv->capturing); From 5d9c08dea0c13c09408f97fe61d34c198c4f3277 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 25 May 2011 06:41:23 -0300 Subject: [PATCH 023/595] [media] ivtvfb: use display information in info not in var for panning We must not use any information in the passed var besides xoffset, yoffset and vmode as otherwise applications might abuse it. Also use the aligned fix.line_length and not the (possible) unaligned xres_virtual. Signed-off-by: Laurent Pinchart Reviewed-by: Ian Armstrong Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtvfb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index 17247451c693..2d5a97431c0a 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -836,7 +836,8 @@ static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *inf u32 osd_pan_index; struct ivtv *itv = (struct ivtv *) info->par; - osd_pan_index = (var->xoffset + (var->yoffset * var->xres_virtual))*var->bits_per_pixel/8; + osd_pan_index = var->yoffset * info->fix.line_length + + var->xoffset * info->var.bits_per_pixel / 8; write_reg(osd_pan_index, 0x02A0C); /* Pass this info back the yuv handler */ From 6600cc301d0762e3db8bd2b44d2d5fef36a4fd68 Mon Sep 17 00:00:00 2001 From: Ian Armstrong Date: Sat, 28 May 2011 22:15:41 -0300 Subject: [PATCH 024/595] [media] ivtvfb: Add sanity check to ivtvfb_pan_display() Add sanity check to ivtvfb_pan_display() to ensure only valid values are used to pan the display. Invalid values are rejected with -EINVAL Signed-off-by: Ian Armstrong Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtvfb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index 2d5a97431c0a..5dec2e4012bd 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -836,6 +836,10 @@ static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *inf u32 osd_pan_index; struct ivtv *itv = (struct ivtv *) info->par; + if (var->yoffset + info->var.yres > info->var.yres_virtual || + var->xoffset + info->var.xres > info->var.xres_virtual) + return -EINVAL; + osd_pan_index = var->yoffset * info->fix.line_length + var->xoffset * info->var.bits_per_pixel / 8; write_reg(osd_pan_index, 0x02A0C); From c5874c9245d298c65f81c2f91f89e1da8ea66409 Mon Sep 17 00:00:00 2001 From: Ian Armstrong Date: Sun, 29 May 2011 21:33:17 -0300 Subject: [PATCH 025/595] [media] ivtv: Internally separate encoder & decoder standard setting Internally separates the setting of the broadcast standard for the encoder & decoder. Externally there's no change in functionality. [awalls@md.metrocast.net: Edited to fix a checkpatch gripe about multiple assignment and to remove a now unused DEFINE_WAIT() due to this patch] Signed-off-by: Ian Armstrong Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-driver.c | 10 +- drivers/media/video/ivtv/ivtv-firmware.c | 11 +- drivers/media/video/ivtv/ivtv-ioctl.c | 129 ++++++++++++----------- drivers/media/video/ivtv/ivtv-ioctl.h | 3 +- drivers/media/video/ivtv/ivtv-vbi.c | 2 +- drivers/media/video/ivtv/ivtvfb.c | 26 ++--- 6 files changed, 99 insertions(+), 82 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index a4e4dfdbc2f2..0fb75524484d 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -1328,6 +1328,8 @@ int ivtv_init_on_first_open(struct ivtv *itv) if (!itv->has_cx23415) write_reg_sync(0x03, IVTV_REG_DMACONTROL); + ivtv_s_std_enc(itv, &itv->tuner_std); + /* Default interrupts enabled. For the PVR350 this includes the decoder VSYNC interrupt, which is always on. It is not only used during decoding but also by the OSD. @@ -1336,12 +1338,10 @@ int ivtv_init_on_first_open(struct ivtv *itv) if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC); ivtv_set_osd_alpha(itv); - } - else + ivtv_s_std_dec(itv, &itv->tuner_std); + } else { ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT); - - /* For cards with video out, this call needs interrupts enabled */ - ivtv_s_std(NULL, &fh, &itv->tuner_std); + } /* Setup initial controls */ cx2341x_handler_setup(&itv->cxhdl); diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c index 14a1cea1d70d..02c5adebf517 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ b/drivers/media/video/ivtv/ivtv-firmware.c @@ -280,8 +280,6 @@ int ivtv_firmware_restart(struct ivtv *itv) { int rc = 0; v4l2_std_id std; - struct ivtv_open_id fh; - fh.itv = itv; if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) /* Display test image during restart */ @@ -301,14 +299,19 @@ int ivtv_firmware_restart(struct ivtv *itv) /* Allow settings to reload */ ivtv_mailbox_cache_invalidate(itv); - /* Restore video standard */ + /* Restore encoder video standard */ std = itv->std; itv->std = 0; - ivtv_s_std(NULL, &fh, &std); + ivtv_s_std_enc(itv, &std); if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { ivtv_init_mpeg_decoder(itv); + /* Restore decoder video standard */ + std = itv->std_out; + itv->std_out = 0; + ivtv_s_std_dec(itv, &std); + /* Restore framebuffer if active */ if (itv->ivtvfb_restore) itv->ivtvfb_restore(itv); diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 1689783cd19a..f9e347dae739 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1071,28 +1071,8 @@ static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std) return 0; } -int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) +void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std) { - DEFINE_WAIT(wait); - struct ivtv *itv = fh2id(fh)->itv; - struct yuv_playback_info *yi = &itv->yuv_info; - int f; - - if ((*std & V4L2_STD_ALL) == 0) - return -EINVAL; - - if (*std == itv->std) - return 0; - - if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) || - atomic_read(&itv->capturing) > 0 || - atomic_read(&itv->decoding) > 0) { - /* Switching standard would turn off the radio or mess - with already running streams, prevent that by - returning EBUSY. */ - return -EBUSY; - } - itv->std = *std; itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0; itv->is_50hz = !itv->is_60hz; @@ -1106,48 +1086,79 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) if (itv->hw_flags & IVTV_HW_CX25840) itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284; - IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std); - /* Tuner */ ivtv_call_all(itv, core, s_std, itv->std); +} - if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { - /* set display standard */ - itv->std_out = *std; - itv->is_out_60hz = itv->is_60hz; - itv->is_out_50hz = itv->is_50hz; - ivtv_call_all(itv, video, s_std_output, itv->std_out); - - /* - * The next firmware call is time sensitive. Time it to - * avoid risk of a hard lock, by trying to ensure the call - * happens within the first 100 lines of the top field. - * Make 4 attempts to sync to the decoder before giving up. - */ - for (f = 0; f < 4; f++) { - prepare_to_wait(&itv->vsync_waitq, &wait, - TASK_UNINTERRUPTIBLE); - if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100) - break; - schedule_timeout(msecs_to_jiffies(25)); - } - finish_wait(&itv->vsync_waitq, &wait); - - if (f == 4) - IVTV_WARN("Mode change failed to sync to decoder\n"); - - ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); - itv->main_rect.left = itv->main_rect.top = 0; - itv->main_rect.width = 720; - itv->main_rect.height = itv->cxhdl.height; - ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, - 720, itv->main_rect.height, 0, 0); - yi->main_rect = itv->main_rect; - if (!itv->osd_info) { - yi->osd_full_w = 720; - yi->osd_full_h = itv->is_out_50hz ? 576 : 480; - } +void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std) +{ + struct yuv_playback_info *yi = &itv->yuv_info; + DEFINE_WAIT(wait); + int f; + + /* set display standard */ + itv->std_out = *std; + itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0; + itv->is_out_50hz = !itv->is_out_60hz; + ivtv_call_all(itv, video, s_std_output, itv->std_out); + + /* + * The next firmware call is time sensitive. Time it to + * avoid risk of a hard lock, by trying to ensure the call + * happens within the first 100 lines of the top field. + * Make 4 attempts to sync to the decoder before giving up. + */ + for (f = 0; f < 4; f++) { + prepare_to_wait(&itv->vsync_waitq, &wait, + TASK_UNINTERRUPTIBLE); + if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100) + break; + schedule_timeout(msecs_to_jiffies(25)); } + finish_wait(&itv->vsync_waitq, &wait); + + if (f == 4) + IVTV_WARN("Mode change failed to sync to decoder\n"); + + ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); + itv->main_rect.left = 0; + itv->main_rect.top = 0; + itv->main_rect.width = 720; + itv->main_rect.height = itv->is_out_50hz ? 576 : 480; + ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, + 720, itv->main_rect.height, 0, 0); + yi->main_rect = itv->main_rect; + if (!itv->osd_info) { + yi->osd_full_w = 720; + yi->osd_full_h = itv->is_out_50hz ? 576 : 480; + } +} + +int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) +{ + struct ivtv *itv = fh2id(fh)->itv; + + if ((*std & V4L2_STD_ALL) == 0) + return -EINVAL; + + if (*std == itv->std) + return 0; + + if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) || + atomic_read(&itv->capturing) > 0 || + atomic_read(&itv->decoding) > 0) { + /* Switching standard would mess with already running + streams, prevent that by returning EBUSY. */ + return -EBUSY; + } + + IVTV_DEBUG_INFO("Switching standard to %llx.\n", + (unsigned long long)itv->std); + + ivtv_s_std_enc(itv, std); + if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) + ivtv_s_std_dec(itv, std); + return 0; } diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/video/ivtv/ivtv-ioctl.h index 58f003412afd..89185caeafae 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.h +++ b/drivers/media/video/ivtv/ivtv-ioctl.h @@ -27,7 +27,8 @@ u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt); void ivtv_set_osd_alpha(struct ivtv *itv); int ivtv_set_speed(struct ivtv *itv, int speed); void ivtv_set_funcs(struct video_device *vdev); -int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std); +void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std); +void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std); int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf); int ivtv_s_input(struct file *file, void *fh, unsigned int inp); long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index b6eb51ce7735..293db806d936 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -71,7 +71,7 @@ static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) Turning this signal on and off can confuse certain TVs. As far as I can tell there is no reason not to transmit this signal. */ - if ((itv->std & V4L2_STD_625_50) && !enabled) { + if ((itv->std_out & V4L2_STD_625_50) && !enabled) { enabled = 1; mode = 0x08; /* 4x3 full format */ } diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index 5dec2e4012bd..6b7c9c823330 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -247,7 +247,7 @@ static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window) { - int osd_height_limit = itv->is_50hz ? 576 : 480; + int osd_height_limit = itv->is_out_50hz ? 576 : 480; /* Only fail if resolution too high, otherwise fudge the start coords. */ if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH)) @@ -471,9 +471,9 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC; trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16; - if (itv->is_50hz && trace > 312) + if (itv->is_out_50hz && trace > 312) trace -= 312; - else if (itv->is_60hz && trace > 262) + else if (itv->is_out_60hz && trace > 262) trace -= 262; if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING; @@ -656,7 +656,7 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv) IVTVFB_DEBUG_INFO("ivtvfb_check_var\n"); /* Set base references for mode calcs. */ - if (itv->is_50hz) { + if (itv->is_out_50hz) { pixclock = 84316; hlimit = 776; vlimit = 591; @@ -784,12 +784,12 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv) If the margins are too large, just center the screen (enforcing margins causes too many problems) */ - if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1) { + if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1) var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2); - } - if (var->upper_margin + var->yres > (itv->is_50hz ? 577 : 481)) { - var->upper_margin = 1 + (((itv->is_50hz ? 576 : 480) - var->yres) / 2); - } + + if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481)) + var->upper_margin = 1 + (((itv->is_out_50hz ? 576 : 480) - + var->yres) / 2); /* Maintain overall 'size' for a constant refresh rate */ var->right_margin = hlimit - var->left_margin - var->xres; @@ -1008,19 +1008,21 @@ static int ivtvfb_init_vidmode(struct ivtv *itv) /* Hardware coords start at 0, user coords start at 1. */ osd_left--; - start_window.left = osd_left >= 0 ? osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2); + start_window.left = osd_left >= 0 ? + osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2); oi->display_byte_stride = start_window.width * oi->bytes_per_pixel; /* Vertical size & position */ - max_height = itv->is_50hz ? 576 : 480; + max_height = itv->is_out_50hz ? 576 : 480; if (osd_yres > max_height) osd_yres = max_height; - start_window.height = osd_yres ? osd_yres : itv->is_50hz ? 480 : 400; + start_window.height = osd_yres ? + osd_yres : itv->is_out_50hz ? 480 : 400; /* Check vertical start (osd_upper). */ if (osd_upper + start_window.height > max_height + 1) { From 6e3ea0e711b1c4dca3c4f87ef0ab5c896c940c81 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 2 May 2011 16:21:03 -0300 Subject: [PATCH 026/595] [media] v4l: Fix media_entity_to_video_device macro argument name The name 'entity' is used twice in the macro body, once as the macro argument, and once as a structure field name. This breaks compilation if the macro is called with its argument not named 'entity'. Fix this by renaming the macro argument '__e'. This should avoid namespace clashes. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-dev.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 93e96fb93452..c7c40f1d2624 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -128,8 +128,8 @@ struct video_device struct mutex *lock; }; -#define media_entity_to_video_device(entity) \ - container_of(entity, struct video_device, entity) +#define media_entity_to_video_device(__e) \ + container_of(__e, struct video_device, entity) /* dev to video-device */ #define to_video_device(cd) container_of(cd, struct video_device, dev) From 6c20c635b8bb110d5c610bf19233462dcfa3b39b Mon Sep 17 00:00:00 2001 From: Sanjeev Premi Date: Wed, 18 May 2011 13:06:51 -0300 Subject: [PATCH 027/595] [media] omap3isp: fix compiler warning This patch fixes this compiler warning: drivers/media/video/omap3isp/isp.c: In function 'isp_isr_dbg': drivers/media/video/omap3isp/isp.c:392:2: warning: zero-length gnu_printf format string Signed-off-by: Sanjeev Premi Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap3isp/isp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/omap3isp/isp.c b/drivers/media/video/omap3isp/isp.c index 472a69359e60..c9fd04ee70a8 100644 --- a/drivers/media/video/omap3isp/isp.c +++ b/drivers/media/video/omap3isp/isp.c @@ -391,7 +391,7 @@ static inline void isp_isr_dbg(struct isp_device *isp, u32 irqstatus) }; int i; - dev_dbg(isp->dev, ""); + dev_dbg(isp->dev, "ISP IRQ: "); for (i = 0; i < ARRAY_SIZE(name); i++) { if ((1 << i) & irqstatus) From 67e27c741339faedcc8e9c2c613487745d1c4b8b Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Mon, 23 May 2011 08:09:18 -0300 Subject: [PATCH 028/595] [media] Make nchg variable signed because the code compares this variable against negative values The sonixj driver compares the value for nchg with: if (sd->nchg < -6 || sd->nchg >= 12) { With u8, negative values won't work. Signed-off-by: Hans Petter Selasky Acked-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 6415aff5cbd1..81b8a600783b 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -60,7 +60,7 @@ struct sd { u32 pktsz; /* (used by pkt_scan) */ u16 npkt; - u8 nchg; + s8 nchg; s8 short_mark; u8 quality; /* image quality */ From 8c89ddd536bbe97c1e50424778a139abbf5763c3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 30 May 2011 15:45:47 -0300 Subject: [PATCH 029/595] [media] media: Fix media device minor registration The find_next_zero_bit() is called with the from and to arguments in the wrong order. This results in the function always returning 0, and all media devices being registered with minor 0. Furthermore, mdev->minor is then used before being assigned with the find_next_zero_bit() return value. This really makes sure we'll always use minor 0. Fix this and let the system support more than one media device. Signed-off-by: Laurent Pinchart Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-devnode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c index af5263c6625a..7b42ace419d9 100644 --- a/drivers/media/media-devnode.c +++ b/drivers/media/media-devnode.c @@ -213,14 +213,14 @@ int __must_check media_devnode_register(struct media_devnode *mdev) /* Part 1: Find a free minor number */ mutex_lock(&media_devnode_lock); - minor = find_next_zero_bit(media_devnode_nums, 0, MEDIA_NUM_DEVICES); + minor = find_next_zero_bit(media_devnode_nums, MEDIA_NUM_DEVICES, 0); if (minor == MEDIA_NUM_DEVICES) { mutex_unlock(&media_devnode_lock); printk(KERN_ERR "could not get a free minor\n"); return -ENFILE; } - set_bit(mdev->minor, media_devnode_nums); + set_bit(minor, media_devnode_nums); mutex_unlock(&media_devnode_lock); mdev->minor = minor; From 76df01eacd5fa41b607426a8cb091fb21ae35554 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 1 Jun 2011 14:44:41 -0300 Subject: [PATCH 030/595] [media] uvc_entity: initialize return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/video/uvc/uvc_entity.c: In function ‘uvc_mc_register_entities’: drivers/media/video/uvc/uvc_entity.c:33: warning: ‘ret’ may be used uninitialized in this function Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_entity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/video/uvc/uvc_entity.c index ede7852bb1df..c3ab0c813be2 100644 --- a/drivers/media/video/uvc/uvc_entity.c +++ b/drivers/media/video/uvc/uvc_entity.c @@ -30,7 +30,7 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain, struct uvc_entity *remote; unsigned int i; u8 remote_pad; - int ret; + int ret = 0; for (i = 0; i < entity->num_pads; ++i) { struct media_entity *source; From d364ee4fdb33a329b16cdf9342e9770b4d4ddc83 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 1 Jun 2011 15:03:56 -0300 Subject: [PATCH 031/595] [media] soc_camera: preserve const attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/video/soc_camera.c: In function ‘soc_camera_video_start’: drivers/media/video/soc_camera.c:1515: warning: initialization discards qualifiers from pointer target type Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/soc_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 398864370267..4e4d4122d9a6 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -1512,7 +1512,7 @@ static int video_dev_create(struct soc_camera_device *icd) */ static int soc_camera_video_start(struct soc_camera_device *icd) { - struct device_type *type = icd->vdev->dev.type; + const struct device_type *type = icd->vdev->dev.type; int ret; if (!icd->dev.parent) From d62fa31123d557bca9a1e3b5da9672e8cc9753db Mon Sep 17 00:00:00 2001 From: Jonghwan Choi Date: Thu, 12 May 2011 18:31:20 +0900 Subject: [PATCH 032/595] ARM: S5PV210: Fix possible null pointer dereference Signed-off-by: Jonghwan Choi Signed-off-by: Kukjin Kim --- arch/arm/mach-s5pv210/cpufreq.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-s5pv210/cpufreq.c b/arch/arm/mach-s5pv210/cpufreq.c index 22046e2f53c2..153af8b359ec 100644 --- a/arch/arm/mach-s5pv210/cpufreq.c +++ b/arch/arm/mach-s5pv210/cpufreq.c @@ -101,12 +101,14 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq) unsigned long tmp, tmp1; void __iomem *reg = NULL; - if (ch == DMC0) + if (ch == DMC0) { reg = (S5P_VA_DMC0 + 0x30); - else if (ch == DMC1) + } else if (ch == DMC1) { reg = (S5P_VA_DMC1 + 0x30); - else + } else { printk(KERN_ERR "Cannot find DMC port\n"); + return; + } /* Find current DRAM frequency */ tmp = s5pv210_dram_conf[ch].freq; From 457d4fe85138c0d313c92ef34ea892c73b0fe2f5 Mon Sep 17 00:00:00 2001 From: Padmavathi Venna Date: Tue, 31 May 2011 14:10:51 -0700 Subject: [PATCH 033/595] ARM: S5P64X0: Fix SPI platform device name Changed the SPI platform device name from S5P6450 to S5P64x0 as it is defined common for both S5p6440 and S5P6450 in dev-spi.c of S5P64x0. Signed-off-by: Padmavathi Venna Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/include/plat/devs.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index b61b8ee7cc52..4af108ff4112 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -75,10 +75,8 @@ extern struct platform_device s5pc100_device_spi1; extern struct platform_device s5pc100_device_spi2; extern struct platform_device s5pv210_device_spi0; extern struct platform_device s5pv210_device_spi1; -extern struct platform_device s5p6440_device_spi0; -extern struct platform_device s5p6440_device_spi1; -extern struct platform_device s5p6450_device_spi0; -extern struct platform_device s5p6450_device_spi1; +extern struct platform_device s5p64x0_device_spi0; +extern struct platform_device s5p64x0_device_spi1; extern struct platform_device s3c_device_hwmon; From 08115a139229ca84adfef4d5983c3c186b9d1c30 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Wed, 1 Jun 2011 15:09:05 -0700 Subject: [PATCH 034/595] ARM: S5P: Should be S3C_VA_USB_HSPHY instead of S5P_VA_XX Basically, other S3C SoCs and S5PC100 use 'S3C_VA_USB_HSPHY' commonly. It should be changed to 'S3C_VA_USB_HSPHY' for common usage and others. Now happens build error on S5PC100. Cc: Greg Kroah-Hartman Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos4/cpu.c | 2 +- arch/arm/mach-exynos4/include/mach/regs-usb-phy.h | 2 +- arch/arm/plat-s5p/include/plat/map-s5p.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c index 08813a6f66b1..9babe4473e88 100644 --- a/arch/arm/mach-exynos4/cpu.c +++ b/arch/arm/mach-exynos4/cpu.c @@ -98,7 +98,7 @@ static struct map_desc exynos4_iodesc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, { - .virtual = (unsigned long)S5P_VA_USB_HSPHY, + .virtual = (unsigned long)S3C_VA_USB_HSPHY, .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY), .length = SZ_4K, .type = MT_DEVICE, diff --git a/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h b/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h index 703118d5173c..c337cf3a71bf 100644 --- a/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h +++ b/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h @@ -11,7 +11,7 @@ #ifndef __PLAT_S5P_REGS_USB_PHY_H #define __PLAT_S5P_REGS_USB_PHY_H -#define EXYNOS4_HSOTG_PHYREG(x) ((x) + S5P_VA_USB_HSPHY) +#define EXYNOS4_HSOTG_PHYREG(x) ((x) + S3C_VA_USB_HSPHY) #define EXYNOS4_PHYPWR EXYNOS4_HSOTG_PHYREG(0x00) #define PHY1_HSIC_NORMAL_MASK (0xf << 9) diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h index a6c3d327ce72..d973d39666a3 100644 --- a/arch/arm/plat-s5p/include/plat/map-s5p.h +++ b/arch/arm/plat-s5p/include/plat/map-s5p.h @@ -39,7 +39,7 @@ #define S5P_VA_TWD S5P_VA_COREPERI(0x600) #define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000) -#define S5P_VA_USB_HSPHY S3C_ADDR(0x02900000) +#define S3C_VA_USB_HSPHY S3C_ADDR(0x02900000) #define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) #define VA_VIC0 VA_VIC(0) From f69753140d5c95087a3352710ae5edd541710da6 Mon Sep 17 00:00:00 2001 From: Matt Evans Date: Wed, 1 Jun 2011 13:01:01 +1000 Subject: [PATCH 035/595] xhci: Bigendian fix for skip_isoc_td() Commit 926008c9386dde09b015753b6681c502177baa30 "USB: xhci: simplify logic of skipping missed isoc TDs" added a small endian bug. This patch fixes skip_isoc_td() to read the DMA pointer correctly. Signed-off-by: Matt Evans Signed-off-by: Sarah Sharp --- 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 cc1485bfed38..800f417c7309 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1782,7 +1782,7 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, struct usb_iso_packet_descriptor *frame; int idx; - ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); + ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); urb_priv = td->urb->hcpriv; idx = urb_priv->td_cnt; frame = &td->urb->iso_frame_desc[idx]; From e23ef227d10878ff3f323a1dfed10205a1825b71 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 29 May 2011 22:53:12 +0300 Subject: [PATCH 036/595] ptp: Return -EFAULT on copy_to_user() errors copy_to_user() returns the number of bytes remaining, but we want a negative error code in ptp_ioctl. Signed-off-by: Dan Carpenter Acked-by: Richard Cochran Signed-off-by: John Stultz --- drivers/ptp/ptp_chardev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c index a8d03aeb4051..93fa22de5977 100644 --- a/drivers/ptp/ptp_chardev.c +++ b/drivers/ptp/ptp_chardev.c @@ -46,7 +46,8 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg) caps.n_ext_ts = ptp->info->n_ext_ts; caps.n_per_out = ptp->info->n_per_out; caps.pps = ptp->info->pps; - err = copy_to_user((void __user *)arg, &caps, sizeof(caps)); + if (copy_to_user((void __user *)arg, &caps, sizeof(caps))) + err = -EFAULT; break; case PTP_EXTTS_REQUEST: From fb5a18cf7c771a12c3f42a5eb4b476eed68b77cb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 29 May 2011 22:54:07 +0300 Subject: [PATCH 037/595] ptp: Fix some locking bugs in ptp_read() In ptp_read there is an unlock missing on an error path, and a double unlock on another error path. Signed-off-by: Dan Carpenter Acked-by: Richard Cochran Signed-off-by: John Stultz --- drivers/ptp/ptp_chardev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c index 93fa22de5977..e7f301da2902 100644 --- a/drivers/ptp/ptp_chardev.c +++ b/drivers/ptp/ptp_chardev.c @@ -130,8 +130,10 @@ ssize_t ptp_read(struct posix_clock *pc, return -ERESTARTSYS; } - if (ptp->defunct) + if (ptp->defunct) { + mutex_unlock(&ptp->tsevq_mux); return -ENODEV; + } spin_lock_irqsave(&queue->lock, flags); @@ -151,10 +153,8 @@ ssize_t ptp_read(struct posix_clock *pc, mutex_unlock(&ptp->tsevq_mux); - if (copy_to_user(buf, event, cnt)) { - mutex_unlock(&ptp->tsevq_mux); + if (copy_to_user(buf, event, cnt)) return -EFAULT; - } return cnt; } From e17fd4ba2a81f1d29875b20464e4899185a3c946 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 31 May 2011 23:26:11 -0700 Subject: [PATCH 038/595] rtc: Fix ioctl error path return Bryan Henderson noticed that the "RTC: Fix rtc driver ioctl specific shortcutting" commit has a small bug: When an ioctl is called with an invalid command code and the clock driver does not have an "ioctl" method, the ioctl returns rc 0 instead of -ENOTTY. This patch fixes the issue. CC: Bryan Henderson CC: Gabor Z. Papp Reported-by: Bryan Henderson Signed-off-by: John Stultz --- drivers/rtc/rtc-dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index d0e06edb14c5..cace6d3aed9a 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -421,7 +421,8 @@ static long rtc_dev_ioctl(struct file *file, err = ops->ioctl(rtc->dev.parent, cmd, arg); if (err == -ENOIOCTLCMD) err = -ENOTTY; - } + } else + err = -ENOTTY; break; } From d576fe49ca5c238e99d2d010a410480cb2aa29a0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 1 Jun 2011 11:13:16 +0100 Subject: [PATCH 039/595] rtc: Staticize non-exported __rtc_set_alarm() It's not referenced outside this file so there's no need for it to be in the global namespace and sparse warns about that. Signed-off-by: Mark Brown Signed-off-by: John Stultz --- drivers/rtc/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index ef6316acec43..df68618f6dbb 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -318,7 +318,7 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) } EXPORT_SYMBOL_GPL(rtc_read_alarm); -int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) +static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { struct rtc_time tm; long now, scheduled; From a3623239ad941c7fa5440231f601e8f6de1f2a54 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 2 Jun 2011 11:18:53 -0500 Subject: [PATCH 040/595] powerpc/fsl_rio: Fix compile error when CONFIG_FSL_RIO not set arch/powerpc/kernel/built-in.o: In function `machine_check_e500mc': arch/powerpc/kernel/traps.c:429: undefined reference to `fsl_rio_mcheck_exception' arch/powerpc/kernel/built-in.o: In function `machine_check_e500': arch/powerpc/kernel/traps.c:519: undefined reference to `fsl_rio_mcheck_exception' make: *** [.tmp_vmlinux1] Error 1 Reported-by: Timur Tabi Signed-off-by: Kumar Gala --- arch/powerpc/include/asm/rio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/rio.h b/arch/powerpc/include/asm/rio.h index d902abd33995..b1d2deceeedb 100644 --- a/arch/powerpc/include/asm/rio.h +++ b/arch/powerpc/include/asm/rio.h @@ -14,7 +14,7 @@ #define ASM_PPC_RIO_H extern void platform_rio_init(void); -#ifdef CONFIG_RAPIDIO +#ifdef CONFIG_FSL_RIO extern int fsl_rio_mcheck_exception(struct pt_regs *); #else static inline int fsl_rio_mcheck_exception(struct pt_regs *regs) {return 0; } From fb9be2349f099d7c68b706e04fd62c478d3c0ed2 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 2 Jun 2011 11:26:13 -0500 Subject: [PATCH 041/595] powerpc/book3e: Fix CPU feature handling on e5500 in 32-bit mode We are missing FPU feature bit that user space may require. In the 64-bit mode this gets set since we pull it in via COMMON_USER_PPC64. We just explicitly set it so user space will be happy again. Signed-off-by: Kumar Gala --- arch/powerpc/kernel/cputable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 34d2722b9451..9fb933248ab6 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -1979,7 +1979,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .pvr_value = 0x80240000, .cpu_name = "e5500", .cpu_features = CPU_FTRS_E5500, - .cpu_user_features = COMMON_USER_BOOKE, + .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS | MMU_FTR_USE_TLBILX, .icache_bsize = 64, From cfe3af5dde34a019c1bd2485b1dc0f2d7a326ccd Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Mon, 23 May 2011 21:04:46 +0000 Subject: [PATCH 042/595] sparc32: added CONFIG_PCIC_PCI Kconfig setting Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 5 +++++ arch/sparc/include/asm/pcic.h | 2 +- arch/sparc/kernel/Makefile | 2 +- arch/sparc/kernel/entry.S | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index af32e17fa170..09b1d8e80399 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -528,6 +528,11 @@ config PCI_DOMAINS config PCI_SYSCALL def_bool PCI +config PCIC_PCI + bool + depends on PCI && !SPARC_LEON + default y + source "drivers/pci/Kconfig" source "drivers/pcmcia/Kconfig" diff --git a/arch/sparc/include/asm/pcic.h b/arch/sparc/include/asm/pcic.h index 7eb5d78f5211..6676cbcc8b6a 100644 --- a/arch/sparc/include/asm/pcic.h +++ b/arch/sparc/include/asm/pcic.h @@ -29,7 +29,7 @@ struct linux_pcic { int pcic_imdim; }; -#ifdef CONFIG_PCI +#ifdef CONFIG_PCIC_PCI extern int pcic_present(void); extern int pcic_probe(void); extern void pci_time_init(void); diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 9cff2709a96d..59a2256aee38 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -73,7 +73,7 @@ obj-$(CONFIG_SPARC64_SMP) += cpumap.o obj-y += dma.o -obj-$(CONFIG_SPARC32_PCI) += pcic.o +obj-$(CONFIG_PCIC_PCI) += pcic.o obj-$(CONFIG_SMP) += trampoline_$(BITS).o smp_$(BITS).o obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 8341963f4c84..c4e616711348 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -1604,7 +1604,7 @@ restore_current: retl nop -#ifdef CONFIG_PCI +#ifdef CONFIG_PCIC_PCI #include .align 4 @@ -1650,7 +1650,7 @@ pcic_nmi_trap_patch: rd %psr, %l0 .word 0 -#endif /* CONFIG_PCI */ +#endif /* CONFIG_PCIC_PCI */ .globl flushw_all flushw_all: From 26893c1368aeb96e06e4f9dce61bbde3351d5e9f Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Mon, 23 May 2011 21:04:47 +0000 Subject: [PATCH 043/595] sparc32,leon: added LEON-common low-level PCI routines The LEON architecture does not have a BIOS or bootloader that initializes PCI for us, instead Linux generic PCI layer is used to set up resources and IRQ. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 5 + arch/sparc/include/asm/leon_pci.h | 21 +++ arch/sparc/include/asm/pci_32.h | 24 +++ arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/leon_pci.c | 253 ++++++++++++++++++++++++++++++ drivers/pci/Makefile | 1 + 6 files changed, 305 insertions(+) create mode 100644 arch/sparc/include/asm/leon_pci.h create mode 100644 arch/sparc/kernel/leon_pci.c diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 09b1d8e80399..ec748c4c16ce 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -533,6 +533,11 @@ config PCIC_PCI depends on PCI && !SPARC_LEON default y +config LEON_PCI + bool + depends on PCI && SPARC_LEON + default y + source "drivers/pci/Kconfig" source "drivers/pcmcia/Kconfig" diff --git a/arch/sparc/include/asm/leon_pci.h b/arch/sparc/include/asm/leon_pci.h new file mode 100644 index 000000000000..42b4b31a82fe --- /dev/null +++ b/arch/sparc/include/asm/leon_pci.h @@ -0,0 +1,21 @@ +/* + * asm/leon_pci.h + * + * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom + */ + +#ifndef _ASM_LEON_PCI_H_ +#define _ASM_LEON_PCI_H_ + +/* PCI related definitions */ +struct leon_pci_info { + struct pci_ops *ops; + struct resource io_space; + struct resource mem_space; + int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin); +}; + +extern void leon_pci_init(struct platform_device *ofdev, + struct leon_pci_info *info); + +#endif /* _ASM_LEON_PCI_H_ */ diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h index 332ac9ab36bc..862e3ce92b15 100644 --- a/arch/sparc/include/asm/pci_32.h +++ b/arch/sparc/include/asm/pci_32.h @@ -47,7 +47,31 @@ extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev); #endif /* __KERNEL__ */ +#ifndef CONFIG_LEON_PCI /* generic pci stuff */ #include +#else +/* + * On LEON PCI Memory space is mapped 1:1 with physical address space. + * + * I/O space is located at low 64Kbytes in PCI I/O space. The I/O addresses + * are converted into CPU addresses to virtual addresses that are mapped with + * MMU to the PCI Host PCI I/O space window which are translated to the low + * 64Kbytes by the Host controller. + */ + +extern void +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res); + +extern void +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region); + +static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) +{ + return PCI_IRQ_NONE; +} +#endif #endif /* __SPARC_PCI_H */ diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 59a2256aee38..b02d2e3f36bc 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -74,6 +74,7 @@ obj-$(CONFIG_SPARC64_SMP) += cpumap.o obj-y += dma.o obj-$(CONFIG_PCIC_PCI) += pcic.o +obj-$(CONFIG_LEON_PCI) += leon_pci.o obj-$(CONFIG_SMP) += trampoline_$(BITS).o smp_$(BITS).o obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c new file mode 100644 index 000000000000..a8a9a275037d --- /dev/null +++ b/arch/sparc/kernel/leon_pci.c @@ -0,0 +1,253 @@ +/* + * leon_pci.c: LEON Host PCI support + * + * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom + * + * Code is partially derived from pcic.c + */ + +#include +#include +#include +#include +#include + +/* The LEON architecture does not rely on a BIOS or bootloader to setup + * PCI for us. The Linux generic routines are used to setup resources, + * reset values of confuration-space registers settings ae preseved. + */ +void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info) +{ + struct pci_bus *root_bus; + + root_bus = pci_scan_bus_parented(&ofdev->dev, 0, info->ops, info); + if (root_bus) { + root_bus->resource[0] = &info->io_space; + root_bus->resource[1] = &info->mem_space; + root_bus->resource[2] = NULL; + + /* Init all PCI devices into PCI tree */ + pci_bus_add_devices(root_bus); + + /* Setup IRQs of all devices using custom routines */ + pci_fixup_irqs(pci_common_swizzle, info->map_irq); + + /* Assign devices with resources */ + pci_assign_unassigned_resources(); + } +} + +/* PCI Memory and Prefetchable Memory is direct-mapped. However I/O Space is + * accessed through a Window which is translated to low 64KB in PCI space, the + * first 4KB is not used so 60KB is available. + * + * This function is used by generic code to translate resource addresses into + * PCI addresses. + */ +void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res) +{ + struct leon_pci_info *info = dev->bus->sysdata; + + region->start = res->start; + region->end = res->end; + + if (res->flags & IORESOURCE_IO) { + region->start -= (info->io_space.start - 0x1000); + region->end -= (info->io_space.start - 0x1000); + } +} +EXPORT_SYMBOL(pcibios_resource_to_bus); + +/* see pcibios_resource_to_bus() comment */ +void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region) +{ + struct leon_pci_info *info = dev->bus->sysdata; + + res->start = region->start; + res->end = region->end; + + if (res->flags & IORESOURCE_IO) { + res->start += (info->io_space.start - 0x1000); + res->end += (info->io_space.start - 0x1000); + } +} +EXPORT_SYMBOL(pcibios_bus_to_resource); + +void __devinit pcibios_fixup_bus(struct pci_bus *pbus) +{ + struct leon_pci_info *info = pbus->sysdata; + struct pci_dev *dev; + int i, has_io, has_mem; + u16 cmd; + + /* Generic PCI bus probing sets these to point at + * &io{port,mem}_resouce which is wrong for us. + */ + if (pbus->self == NULL) { + pbus->resource[0] = &info->io_space; + pbus->resource[1] = &info->mem_space; + pbus->resource[2] = NULL; + } + + list_for_each_entry(dev, &pbus->devices, bus_list) { + /* + * We can not rely on that the bootloader has enabled I/O + * or memory access to PCI devices. Instead we enable it here + * if the device has BARs of respective type. + */ + has_io = has_mem = 0; + for (i = 0; i < PCI_ROM_RESOURCE; i++) { + unsigned long f = dev->resource[i].flags; + if (f & IORESOURCE_IO) + has_io = 1; + else if (f & IORESOURCE_MEM) + has_mem = 1; + } + /* ROM BARs are mapped into 32-bit memory space */ + if (dev->resource[PCI_ROM_RESOURCE].end != 0) { + dev->resource[PCI_ROM_RESOURCE].flags |= + IORESOURCE_ROM_ENABLE; + has_mem = 1; + } + pci_bus_read_config_word(pbus, dev->devfn, PCI_COMMAND, &cmd); + if (has_io && !(cmd & PCI_COMMAND_IO)) { +#ifdef CONFIG_PCI_DEBUG + printk(KERN_INFO "LEONPCI: Enabling I/O for dev %s\n", + pci_name(dev)); +#endif + cmd |= PCI_COMMAND_IO; + pci_bus_write_config_word(pbus, dev->devfn, PCI_COMMAND, + cmd); + } + if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) { +#ifdef CONFIG_PCI_DEBUG + printk(KERN_INFO "LEONPCI: Enabling MEMORY for dev" + "%s\n", pci_name(dev)); +#endif + cmd |= PCI_COMMAND_MEMORY; + pci_bus_write_config_word(pbus, dev->devfn, PCI_COMMAND, + cmd); + } + } +} + +/* + * Other archs parse arguments here. + */ +char * __devinit pcibios_setup(char *str) +{ + return str; +} + +resource_size_t pcibios_align_resource(void *data, const struct resource *res, + resource_size_t size, resource_size_t align) +{ + return res->start; +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + return pci_enable_resources(dev, mask); +} + +struct device_node *pci_device_to_OF_node(struct pci_dev *pdev) +{ + /* + * Currently the OpenBoot nodes are not connected with the PCI device, + * this is because the LEON PROM does not create PCI nodes. Eventually + * this will change and the same approach as pcic.c can be used to + * match PROM nodes with pci devices. + */ + return NULL; +} +EXPORT_SYMBOL(pci_device_to_OF_node); + +void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) +{ +#ifdef CONFIG_PCI_DEBUG + printk(KERN_DEBUG "LEONPCI: Assigning IRQ %02d to %s\n", irq, + pci_name(dev)); +#endif + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + +/* in/out routines taken from pcic.c + * + * This probably belongs here rather than ioport.c because + * we do not want this crud linked into SBus kernels. + * Also, think for a moment about likes of floppy.c that + * include architecture specific parts. They may want to redefine ins/outs. + * + * We do not use horrible macros here because we want to + * advance pointer by sizeof(size). + */ +void outsb(unsigned long addr, const void *src, unsigned long count) +{ + while (count) { + count -= 1; + outb(*(const char *)src, addr); + src += 1; + /* addr += 1; */ + } +} +EXPORT_SYMBOL(outsb); + +void outsw(unsigned long addr, const void *src, unsigned long count) +{ + while (count) { + count -= 2; + outw(*(const short *)src, addr); + src += 2; + /* addr += 2; */ + } +} +EXPORT_SYMBOL(outsw); + +void outsl(unsigned long addr, const void *src, unsigned long count) +{ + while (count) { + count -= 4; + outl(*(const long *)src, addr); + src += 4; + /* addr += 4; */ + } +} +EXPORT_SYMBOL(outsl); + +void insb(unsigned long addr, void *dst, unsigned long count) +{ + while (count) { + count -= 1; + *(unsigned char *)dst = inb(addr); + dst += 1; + /* addr += 1; */ + } +} +EXPORT_SYMBOL(insb); + +void insw(unsigned long addr, void *dst, unsigned long count) +{ + while (count) { + count -= 2; + *(unsigned short *)dst = inw(addr); + dst += 2; + /* addr += 2; */ + } +} +EXPORT_SYMBOL(insw); + +void insl(unsigned long addr, void *dst, unsigned long count) +{ + while (count) { + count -= 4; + /* + * XXX I am sure we are in for an unaligned trap here. + */ + *(unsigned long *)dst = inl(addr); + dst += 4; + /* addr += 4; */ + } +} +EXPORT_SYMBOL(insl); diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index c85f744270a5..094308e41be5 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_X86_VISWS) += setup-irq.o obj-$(CONFIG_MN10300) += setup-bus.o obj-$(CONFIG_MICROBLAZE) += setup-bus.o obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o +obj-$(CONFIG_SPARC_LEON) += setup-bus.o setup-irq.o # # ACPI Related PCI FW Functions From 5d07b7869a48aec43ee0de6413a6657457287b63 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Mon, 23 May 2011 21:04:48 +0000 Subject: [PATCH 044/595] sparc32,leon: add GRPCI2 PCI Host driver The DMA region must be accessible in order for PCI peripheral drivers to work, the sparc32 has DMA in the normal memory zone which requires the GRPCI2 to PCI target BARs so that all kernel low mem (192MB) can be mapped 1:1 to PCI address space. The GRPCI2 has resizeable target BARs, by default the first is made 256MB and all other BARs are disabled. I/O space are always located on 0x1000-0x10000, but accessed through the GRPCI2 PCI I/O Window memory mapped to virtual address space. Configuration space is accessed through the 64KB GRPCI2 PCI CFG Window using LDA bypassing the MMU. The GRPCI2 has a single PCI Window for prefetchable and non- prefetchable address space, it is up to the AHB master requesting PCI data to determine access type. Memory space is mapped 1:1. The GRPCI2 core can be configured in 4 different IRQ modes, where PCI Interrupt, Error Interrupt and DMA Interrupt are shared on a single IRQ line or at most 5 IRQs are used. The GRPCI2 can mask/unmask PCI interrupts, Err and DMA in the control and check status bits which tells us which IRQ really happended. The GENIRQ layer is used to unmask/mask each individual IRQ source by creating virtual IRQs and implementing a IRQ chip. The optional DMA functionality of the GRPCI2 is not supported by this patch. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 7 + arch/sparc/include/asm/leon.h | 3 + arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/leon_kernel.c | 15 + arch/sparc/kernel/leon_pci_grpci2.c | 897 ++++++++++++++++++++++++++++ 5 files changed, 923 insertions(+) create mode 100644 arch/sparc/kernel/leon_pci_grpci2.c diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index ec748c4c16ce..730dda1ad143 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -538,6 +538,13 @@ config LEON_PCI depends on PCI && SPARC_LEON default y +config GRPCI2 + bool "GRPCI2 Host Bridge Support" + depends on LEON_PCI + default y + help + Say Y here to include the GRPCI2 Host Bridge Driver. + source "drivers/pci/Kconfig" source "drivers/pcmcia/Kconfig" diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h index 6bdaf1e43d2a..a4e457f003ed 100644 --- a/arch/sparc/include/asm/leon.h +++ b/arch/sparc/include/asm/leon.h @@ -318,6 +318,9 @@ struct device_node; extern unsigned int leon_build_device_irq(unsigned int real_irq, irq_flow_handler_t flow_handler, const char *name, int do_ack); +extern void leon_update_virq_handling(unsigned int virq, + irq_flow_handler_t flow_handler, + const char *name, int do_ack); extern void leon_clear_clock_irq(void); extern void leon_load_profile_irq(int cpu, unsigned int limit); extern void leon_init_timers(irq_handler_t counter_fn); diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index b02d2e3f36bc..b90b4a1d070a 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -75,6 +75,7 @@ obj-y += dma.o obj-$(CONFIG_PCIC_PCI) += pcic.o obj-$(CONFIG_LEON_PCI) += leon_pci.o +obj-$(CONFIG_GRPCI2) += leon_pci_grpci2.o obj-$(CONFIG_SMP) += trampoline_$(BITS).o smp_$(BITS).o obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 2f538ac2e139..c23d61e9e52c 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -236,6 +236,21 @@ static unsigned int _leon_build_device_irq(struct platform_device *op, return leon_build_device_irq(real_irq, handle_simple_irq, "edge", 0); } +void leon_update_virq_handling(unsigned int virq, + irq_flow_handler_t flow_handler, + const char *name, int do_ack) +{ + unsigned long mask = (unsigned long)irq_get_chip_data(virq); + + mask &= ~LEON_DO_ACK_HW; + if (do_ack) + mask |= LEON_DO_ACK_HW; + + irq_set_chip_and_handler_name(virq, &leon_irq, + flow_handler, name); + irq_set_chip_data(virq, (void *)mask); +} + void __init leon_init_timers(irq_handler_t counter_fn) { int irq, eirq; diff --git a/arch/sparc/kernel/leon_pci_grpci2.c b/arch/sparc/kernel/leon_pci_grpci2.c new file mode 100644 index 000000000000..44dc093ee33a --- /dev/null +++ b/arch/sparc/kernel/leon_pci_grpci2.c @@ -0,0 +1,897 @@ +/* + * leon_pci_grpci2.c: GRPCI2 Host PCI driver + * + * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "irq.h" + +struct grpci2_barcfg { + unsigned long pciadr; /* PCI Space Address */ + unsigned long ahbadr; /* PCI Base address mapped to this AHB addr */ +}; + +/* Device Node Configuration options: + * - barcfgs : Custom Configuration of Host's 6 target BARs + * - irq_mask : Limit which PCI interrupts are enabled + * - do_reset : Force PCI Reset on startup + * + * barcfgs + * ======= + * + * Optional custom Target BAR configuration (see struct grpci2_barcfg). All + * addresses are physical. Array always contains 6 elements (len=2*4*6 bytes) + * + * -1 means not configured (let host driver do default setup). + * + * [i*2+0] = PCI Address of BAR[i] on target interface + * [i*2+1] = Accessing PCI address of BAR[i] result in this AMBA address + * + * + * irq_mask + * ======== + * + * Limit which PCI interrupts are enabled. 0=Disable, 1=Enable. By default + * all are enabled. Use this when PCI interrupt pins are floating on PCB. + * int, len=4. + * bit0 = PCI INTA# + * bit1 = PCI INTB# + * bit2 = PCI INTC# + * bit3 = PCI INTD# + * + * + * reset + * ===== + * + * Force PCI reset on startup. int, len=4 + */ + +/* Enable Debugging Configuration Space Access */ +#undef GRPCI2_DEBUG_CFGACCESS + +/* + * GRPCI2 APB Register MAP + */ +struct grpci2_regs { + unsigned int ctrl; /* 0x00 Control */ + unsigned int sts_cap; /* 0x04 Status / Capabilities */ + int res1; /* 0x08 */ + unsigned int io_map; /* 0x0C I/O Map address */ + unsigned int dma_ctrl; /* 0x10 DMA */ + unsigned int dma_bdbase; /* 0x14 DMA */ + int res2[2]; /* 0x18 */ + unsigned int bars[6]; /* 0x20 read-only PCI BARs */ + int res3[2]; /* 0x38 */ + unsigned int ahbmst_map[16]; /* 0x40 AHB->PCI Map per AHB Master */ + + /* PCI Trace Buffer Registers (OPTIONAL) */ + unsigned int t_ctrl; /* 0x80 */ + unsigned int t_cnt; /* 0x84 */ + unsigned int t_adpat; /* 0x88 */ + unsigned int t_admask; /* 0x8C */ + unsigned int t_sigpat; /* 0x90 */ + unsigned int t_sigmask; /* 0x94 */ + unsigned int t_adstate; /* 0x98 */ + unsigned int t_sigstate; /* 0x9C */ +}; + +#define REGLOAD(a) (be32_to_cpu(__raw_readl(&(a)))) +#define REGSTORE(a, v) (__raw_writel(cpu_to_be32(v), &(a))) + +#define CTRL_BUS_BIT 16 + +#define CTRL_RESET (1<<31) +#define CTRL_SI (1<<27) +#define CTRL_PE (1<<26) +#define CTRL_EI (1<<25) +#define CTRL_ER (1<<24) +#define CTRL_BUS (0xff<bus->sysdata; + int irq_group; + + /* Use default IRQ decoding on PCI BUS0 according slot numbering */ + irq_group = slot & 0x3; + pin = ((pin - 1) + irq_group) & 0x3; + + return priv->irq_map[pin]; +} + +static int grpci2_cfg_r32(struct grpci2_priv *priv, unsigned int bus, + unsigned int devfn, int where, u32 *val) +{ + unsigned int *pci_conf; + unsigned long flags; + u32 tmp; + + if (where & 0x3) + return -EINVAL; + + if (bus == 0 && PCI_SLOT(devfn) != 0) + devfn += (0x8 * 6); + + /* Select bus */ + spin_lock_irqsave(&grpci2_dev_lock, flags); + REGSTORE(priv->regs->ctrl, (REGLOAD(priv->regs->ctrl) & ~(0xff << 16)) | + (bus << 16)); + spin_unlock_irqrestore(&grpci2_dev_lock, flags); + + /* clear old status */ + REGSTORE(priv->regs->sts_cap, (STS_CFGERR | STS_CFGERRVALID)); + + pci_conf = (unsigned int *) (priv->pci_conf | + (devfn << 8) | (where & 0xfc)); + tmp = LEON3_BYPASS_LOAD_PA(pci_conf); + + /* Wait until GRPCI2 signals that CFG access is done, it should be + * done instantaneously unless a DMA operation is ongoing... + */ + while ((REGLOAD(priv->regs->sts_cap) & STS_CFGERRVALID) == 0) + ; + + if (REGLOAD(priv->regs->sts_cap) & STS_CFGERR) { + *val = 0xffffffff; + } else { + /* Bus always little endian (unaffected by byte-swapping) */ + *val = flip_dword(tmp); + } + + return 0; +} + +static int grpci2_cfg_r16(struct grpci2_priv *priv, unsigned int bus, + unsigned int devfn, int where, u32 *val) +{ + u32 v; + int ret; + + if (where & 0x1) + return -EINVAL; + ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v); + *val = 0xffff & (v >> (8 * (where & 0x3))); + return ret; +} + +static int grpci2_cfg_r8(struct grpci2_priv *priv, unsigned int bus, + unsigned int devfn, int where, u32 *val) +{ + u32 v; + int ret; + + ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v); + *val = 0xff & (v >> (8 * (where & 3))); + + return ret; +} + +static int grpci2_cfg_w32(struct grpci2_priv *priv, unsigned int bus, + unsigned int devfn, int where, u32 val) +{ + unsigned int *pci_conf; + unsigned long flags; + + if (where & 0x3) + return -EINVAL; + + if (bus == 0 && PCI_SLOT(devfn) != 0) + devfn += (0x8 * 6); + + /* Select bus */ + spin_lock_irqsave(&grpci2_dev_lock, flags); + REGSTORE(priv->regs->ctrl, (REGLOAD(priv->regs->ctrl) & ~(0xff << 16)) | + (bus << 16)); + spin_unlock_irqrestore(&grpci2_dev_lock, flags); + + /* clear old status */ + REGSTORE(priv->regs->sts_cap, (STS_CFGERR | STS_CFGERRVALID)); + + pci_conf = (unsigned int *) (priv->pci_conf | + (devfn << 8) | (where & 0xfc)); + LEON3_BYPASS_STORE_PA(pci_conf, flip_dword(val)); + + /* Wait until GRPCI2 signals that CFG access is done, it should be + * done instantaneously unless a DMA operation is ongoing... + */ + while ((REGLOAD(priv->regs->sts_cap) & STS_CFGERRVALID) == 0) + ; + + return 0; +} + +static int grpci2_cfg_w16(struct grpci2_priv *priv, unsigned int bus, + unsigned int devfn, int where, u32 val) +{ + int ret; + u32 v; + + if (where & 0x1) + return -EINVAL; + ret = grpci2_cfg_r32(priv, bus, devfn, where&~3, &v); + if (ret) + return ret; + v = (v & ~(0xffff << (8 * (where & 0x3)))) | + ((0xffff & val) << (8 * (where & 0x3))); + return grpci2_cfg_w32(priv, bus, devfn, where & ~0x3, v); +} + +static int grpci2_cfg_w8(struct grpci2_priv *priv, unsigned int bus, + unsigned int devfn, int where, u32 val) +{ + int ret; + u32 v; + + ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v); + if (ret != 0) + return ret; + v = (v & ~(0xff << (8 * (where & 0x3)))) | + ((0xff & val) << (8 * (where & 0x3))); + return grpci2_cfg_w32(priv, bus, devfn, where & ~0x3, v); +} + +/* Read from Configuration Space. When entering here the PCI layer has taken + * the pci_lock spinlock and IRQ is off. + */ +static int grpci2_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + struct grpci2_priv *priv = grpci2priv; + unsigned int busno = bus->number; + int ret; + + if (PCI_SLOT(devfn) > 15 || (PCI_SLOT(devfn) == 0 && busno == 0)) { + *val = ~0; + return 0; + } + + switch (size) { + case 1: + ret = grpci2_cfg_r8(priv, busno, devfn, where, val); + break; + case 2: + ret = grpci2_cfg_r16(priv, busno, devfn, where, val); + break; + case 4: + ret = grpci2_cfg_r32(priv, busno, devfn, where, val); + break; + default: + ret = -EINVAL; + break; + } + +#ifdef GRPCI2_DEBUG_CFGACCESS + printk(KERN_INFO "grpci2_read_config: [%02x:%02x:%x] ofs=%d val=%x " + "size=%d\n", busno, PCI_SLOT(devfn), PCI_FUNC(devfn), where, + *val, size); +#endif + + return ret; +} + +/* Write to Configuration Space. When entering here the PCI layer has taken + * the pci_lock spinlock and IRQ is off. + */ +static int grpci2_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + struct grpci2_priv *priv = grpci2priv; + unsigned int busno = bus->number; + + if (PCI_SLOT(devfn) > 15 || (PCI_SLOT(devfn) == 0 && busno == 0)) + return 0; + +#ifdef GRPCI2_DEBUG_CFGACCESS + printk(KERN_INFO "grpci2_write_config: [%02x:%02x:%x] ofs=%d size=%d " + "val=%x\n", busno, PCI_SLOT(devfn), PCI_FUNC(devfn), + where, size, val); +#endif + + switch (size) { + default: + return -EINVAL; + case 1: + return grpci2_cfg_w8(priv, busno, devfn, where, val); + case 2: + return grpci2_cfg_w16(priv, busno, devfn, where, val); + case 4: + return grpci2_cfg_w32(priv, busno, devfn, where, val); + } +} + +static struct pci_ops grpci2_ops = { + .read = grpci2_read_config, + .write = grpci2_write_config, +}; + +/* GENIRQ IRQ chip implementation for GRPCI2 irqmode=0..2. In configuration + * 3 where all PCI Interrupts has a separate IRQ on the system IRQ controller + * this is not needed and the standard IRQ controller can be used. + */ + +static void grpci2_mask_irq(struct irq_data *data) +{ + unsigned long flags; + unsigned int irqidx; + struct grpci2_priv *priv = grpci2priv; + + irqidx = (unsigned int)data->chip_data - 1; + if (irqidx > 3) /* only mask PCI interrupts here */ + return; + + spin_lock_irqsave(&grpci2_dev_lock, flags); + REGSTORE(priv->regs->ctrl, REGLOAD(priv->regs->ctrl) & ~(1 << irqidx)); + spin_unlock_irqrestore(&grpci2_dev_lock, flags); +} + +static void grpci2_unmask_irq(struct irq_data *data) +{ + unsigned long flags; + unsigned int irqidx; + struct grpci2_priv *priv = grpci2priv; + + irqidx = (unsigned int)data->chip_data - 1; + if (irqidx > 3) /* only unmask PCI interrupts here */ + return; + + spin_lock_irqsave(&grpci2_dev_lock, flags); + REGSTORE(priv->regs->ctrl, REGLOAD(priv->regs->ctrl) | (1 << irqidx)); + spin_unlock_irqrestore(&grpci2_dev_lock, flags); +} + +static unsigned int grpci2_startup_irq(struct irq_data *data) +{ + grpci2_unmask_irq(data); + return 0; +} + +static void grpci2_shutdown_irq(struct irq_data *data) +{ + grpci2_mask_irq(data); +} + +static struct irq_chip grpci2_irq = { + .name = "grpci2", + .irq_startup = grpci2_startup_irq, + .irq_shutdown = grpci2_shutdown_irq, + .irq_mask = grpci2_mask_irq, + .irq_unmask = grpci2_unmask_irq, +}; + +/* Handle one or multiple IRQs from the PCI core */ +static void grpci2_pci_flow_irq(unsigned int irq, struct irq_desc *desc) +{ + struct grpci2_priv *priv = grpci2priv; + int i, ack = 0; + unsigned int ctrl, sts_cap, pci_ints; + + ctrl = REGLOAD(priv->regs->ctrl); + sts_cap = REGLOAD(priv->regs->sts_cap); + + /* Error Interrupt? */ + if (sts_cap & STS_ERR_IRQ) { + generic_handle_irq(priv->virq_err); + ack = 1; + } + + /* PCI Interrupt? */ + pci_ints = ((~sts_cap) >> STS_INTSTS_BIT) & ctrl & CTRL_HOSTINT; + if (pci_ints) { + /* Call respective PCI Interrupt handler */ + for (i = 0; i < 4; i++) { + if (pci_ints & (1 << i)) + generic_handle_irq(priv->irq_map[i]); + } + ack = 1; + } + + /* + * Decode DMA Interrupt only when shared with Err and PCI INTX#, when + * the DMA is a unique IRQ the DMA interrupts doesn't end up here, they + * goes directly to DMA ISR. + */ + if ((priv->irq_mode == 0) && (sts_cap & (STS_IDMA | STS_IDMAERR))) { + generic_handle_irq(priv->virq_dma); + ack = 1; + } + + /* + * Call "first level" IRQ chip end-of-irq handler. It will ACK LEON IRQ + * Controller, this must be done after IRQ sources have been handled to + * avoid double IRQ generation + */ + if (ack) + desc->irq_data.chip->irq_eoi(&desc->irq_data); +} + +/* Create a virtual IRQ */ +static unsigned int grpci2_build_device_irq(unsigned int irq) +{ + unsigned int virq = 0, pil; + + pil = 1 << 8; + virq = irq_alloc(irq, pil); + if (virq == 0) + goto out; + + irq_set_chip_and_handler_name(virq, &grpci2_irq, handle_simple_irq, + "pcilvl"); + irq_set_chip_data(virq, (void *)irq); + +out: + return virq; +} + +void grpci2_hw_init(struct grpci2_priv *priv) +{ + u32 ahbadr, pciadr, bar_sz, capptr, io_map, data; + struct grpci2_regs *regs = priv->regs; + int i; + struct grpci2_barcfg *barcfg = priv->tgtbars; + + /* Reset any earlier setup */ + if (priv->do_reset) { + printk(KERN_INFO "GRPCI2: Resetting PCI bus\n"); + REGSTORE(regs->ctrl, CTRL_RESET); + ssleep(1); /* Wait for boards to settle */ + } + REGSTORE(regs->ctrl, 0); + REGSTORE(regs->sts_cap, ~0); /* Clear Status */ + REGSTORE(regs->dma_ctrl, 0); + REGSTORE(regs->dma_bdbase, 0); + + /* Translate I/O accesses to 0, I/O Space always @ PCI low 64Kbytes */ + REGSTORE(regs->io_map, REGLOAD(regs->io_map) & 0x0000ffff); + + /* set 1:1 mapping between AHB -> PCI memory space, for all Masters + * Each AHB master has it's own mapping registers. Max 16 AHB masters. + */ + for (i = 0; i < 16; i++) + REGSTORE(regs->ahbmst_map[i], priv->pci_area); + + /* Get the GRPCI2 Host PCI ID */ + grpci2_cfg_r32(priv, 0, 0, PCI_VENDOR_ID, &priv->pciid); + + /* Get address to first (always defined) capability structure */ + grpci2_cfg_r8(priv, 0, 0, PCI_CAPABILITY_LIST, &capptr); + + /* Enable/Disable Byte twisting */ + grpci2_cfg_r32(priv, 0, 0, capptr+CAP9_IOMAP_OFS, &io_map); + io_map = (io_map & ~0x1) | (priv->bt_enabled ? 1 : 0); + grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_IOMAP_OFS, io_map); + + /* Setup the Host's PCI Target BARs for other peripherals to access, + * and do DMA to the host's memory. The target BARs can be sized and + * enabled individually. + * + * User may set custom target BARs, but default is: + * The first BARs is used to map kernel low (DMA is part of normal + * region on sparc which is SRMMU_MAXMEM big) main memory 1:1 to the + * PCI bus, the other BARs are disabled. We assume that the first BAR + * is always available. + */ + for (i = 0; i < 6; i++) { + if (barcfg[i].pciadr != ~0 && barcfg[i].ahbadr != ~0) { + /* Target BARs must have the proper alignment */ + ahbadr = barcfg[i].ahbadr; + pciadr = barcfg[i].pciadr; + bar_sz = ((pciadr - 1) & ~pciadr) + 1; + } else { + if (i == 0) { + /* Map main memory */ + bar_sz = 0xf0000008; /* 256MB prefetchable */ + ahbadr = 0xf0000000 & (u32)__pa(PAGE_ALIGN( + (unsigned long) &_end)); + pciadr = ahbadr; + } else { + bar_sz = 0; + ahbadr = 0; + pciadr = 0; + } + } + grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BARSIZE_OFS+i*4, bar_sz); + grpci2_cfg_w32(priv, 0, 0, PCI_BASE_ADDRESS_0+i*4, pciadr); + grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BAR_OFS+i*4, ahbadr); + printk(KERN_INFO " TGT BAR[%d]: 0x%08x (PCI)-> 0x%08x\n", + i, pciadr, ahbadr); + } + + /* set as bus master and enable pci memory responses */ + grpci2_cfg_r32(priv, 0, 0, PCI_COMMAND, &data); + data |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + grpci2_cfg_w32(priv, 0, 0, PCI_COMMAND, data); + + /* Enable Error respone (CPU-TRAP) on illegal memory access. */ + REGSTORE(regs->ctrl, CTRL_ER | CTRL_PE); +} + +static irqreturn_t grpci2_jump_interrupt(int irq, void *arg) +{ + printk(KERN_ERR "GRPCI2: Jump IRQ happened\n"); + return IRQ_NONE; +} + +/* Handle GRPCI2 Error Interrupt */ +static irqreturn_t grpci2_err_interrupt(int irq, void *arg) +{ + struct grpci2_priv *priv = arg; + struct grpci2_regs *regs = priv->regs; + unsigned int status; + + status = REGLOAD(regs->sts_cap); + if ((status & STS_ERR_IRQ) == 0) + return IRQ_NONE; + + if (status & STS_IPARERR) + printk(KERN_ERR "GRPCI2: Parity Error\n"); + + if (status & STS_ITGTABRT) + printk(KERN_ERR "GRPCI2: Target Abort\n"); + + if (status & STS_IMSTABRT) + printk(KERN_ERR "GRPCI2: Master Abort\n"); + + if (status & STS_ISYSERR) + printk(KERN_ERR "GRPCI2: System Error\n"); + + /* Clear handled INT TYPE IRQs */ + REGSTORE(regs->sts_cap, status & STS_ERR_IRQ); + + return IRQ_HANDLED; +} + +static int __devinit grpci2_of_probe(struct platform_device *ofdev) +{ + struct grpci2_regs *regs; + struct grpci2_priv *priv; + int err, i, len; + const int *tmp; + unsigned int capability; + + if (grpci2priv) { + printk(KERN_ERR "GRPCI2: only one GRPCI2 core supported\n"); + return -ENODEV; + } + + if (ofdev->num_resources < 3) { + printk(KERN_ERR "GRPCI2: not enough APB/AHB resources\n"); + return -EIO; + } + + /* Find Device Address */ + regs = of_ioremap(&ofdev->resource[0], 0, + resource_size(&ofdev->resource[0]), + "grlib-grpci2 regs"); + if (regs == NULL) { + printk(KERN_ERR "GRPCI2: ioremap failed\n"); + return -EIO; + } + + /* + * Check that we're in Host Slot and that we can act as a Host Bridge + * and not only as target. + */ + capability = REGLOAD(regs->sts_cap); + if ((capability & STS_HOST) || !(capability & STS_MST)) { + printk(KERN_INFO "GRPCI2: not in host system slot\n"); + err = -EIO; + goto err1; + } + + priv = grpci2priv = kzalloc(sizeof(struct grpci2_priv), GFP_KERNEL); + if (grpci2priv == NULL) { + err = -ENOMEM; + goto err1; + } + memset(grpci2priv, 0, sizeof(*grpci2priv)); + priv->regs = regs; + priv->irq = ofdev->archdata.irqs[0]; /* BASE IRQ */ + priv->irq_mode = (capability & STS_IRQMODE) >> STS_IRQMODE_BIT; + + printk(KERN_INFO "GRPCI2: host found at %p, irq%d\n", regs, priv->irq); + + /* Byte twisting should be made configurable from kernel command line */ + priv->bt_enabled = 1; + + /* Let user do custom Target BAR assignment */ + tmp = of_get_property(ofdev->dev.of_node, "barcfg", &len); + if (tmp && (len == 2*4*6)) + memcpy(priv->tgtbars, tmp, 2*4*6); + else + memset(priv->tgtbars, -1, 2*4*6); + + /* Limit IRQ unmasking in irq_mode 2 and 3 */ + tmp = of_get_property(ofdev->dev.of_node, "irq_mask", &len); + if (tmp && (len == 4)) + priv->do_reset = *tmp; + else + priv->irq_mask = 0xf; + + /* Optional PCI reset. Force PCI reset on startup */ + tmp = of_get_property(ofdev->dev.of_node, "reset", &len); + if (tmp && (len == 4)) + priv->do_reset = *tmp; + else + priv->do_reset = 0; + + /* Find PCI Memory, I/O and Configuration Space Windows */ + priv->pci_area = ofdev->resource[1].start; + priv->pci_area_end = ofdev->resource[1].end+1; + priv->pci_io = ofdev->resource[2].start; + priv->pci_conf = ofdev->resource[2].start + 0x10000; + priv->pci_conf_end = priv->pci_conf + 0x10000; + priv->pci_io_va = (unsigned long)ioremap(priv->pci_io, 0x10000); + if (!priv->pci_io_va) { + err = -EIO; + goto err2; + } + + printk(KERN_INFO + "GRPCI2: MEMORY SPACE [0x%08lx - 0x%08lx]\n" + " I/O SPACE [0x%08lx - 0x%08lx]\n" + " CONFIG SPACE [0x%08lx - 0x%08lx]\n", + priv->pci_area, priv->pci_area_end-1, + priv->pci_io, priv->pci_conf-1, + priv->pci_conf, priv->pci_conf_end-1); + + /* + * I/O Space resources in I/O Window mapped into Virtual Adr Space + * We never use low 4KB because some devices seem have problems using + * address 0. + */ + memset(&priv->info.io_space, 0, sizeof(struct resource)); + priv->info.io_space.name = "GRPCI2 PCI I/O Space"; + priv->info.io_space.start = priv->pci_io_va + 0x1000; + priv->info.io_space.end = priv->pci_io_va + 0x10000 - 1; + priv->info.io_space.flags = IORESOURCE_IO; + + /* + * GRPCI2 has no prefetchable memory, map everything as + * non-prefetchable memory + */ + memset(&priv->info.mem_space, 0, sizeof(struct resource)); + priv->info.mem_space.name = "GRPCI2 PCI MEM Space"; + priv->info.mem_space.start = priv->pci_area; + priv->info.mem_space.end = priv->pci_area_end - 1; + priv->info.mem_space.flags = IORESOURCE_MEM; + + if (request_resource(&iomem_resource, &priv->info.mem_space) < 0) + goto err3; + if (request_resource(&ioport_resource, &priv->info.io_space) < 0) + goto err4; + + grpci2_hw_init(priv); + + /* + * Get PCI Interrupt to System IRQ mapping and setup IRQ handling + * Error IRQ always on PCI INTA. + */ + if (priv->irq_mode < 2) { + /* All PCI interrupts are shared using the same system IRQ */ + leon_update_virq_handling(priv->irq, grpci2_pci_flow_irq, + "pcilvl", 0); + + priv->irq_map[0] = grpci2_build_device_irq(1); + priv->irq_map[1] = grpci2_build_device_irq(2); + priv->irq_map[2] = grpci2_build_device_irq(3); + priv->irq_map[3] = grpci2_build_device_irq(4); + + priv->virq_err = grpci2_build_device_irq(5); + if (priv->irq_mode & 1) + priv->virq_dma = ofdev->archdata.irqs[1]; + else + priv->virq_dma = grpci2_build_device_irq(6); + + /* Enable IRQs on LEON IRQ controller */ + err = request_irq(priv->irq, grpci2_jump_interrupt, 0, + "GRPCI2_JUMP", priv); + if (err) + printk(KERN_ERR "GRPCI2: ERR IRQ request failed\n"); + } else { + /* All PCI interrupts have an unique IRQ interrupt */ + for (i = 0; i < 4; i++) { + /* Make LEON IRQ layer handle level IRQ by acking */ + leon_update_virq_handling(ofdev->archdata.irqs[i], + handle_fasteoi_irq, "pcilvl", + 1); + priv->irq_map[i] = ofdev->archdata.irqs[i]; + } + priv->virq_err = priv->irq_map[0]; + if (priv->irq_mode & 1) + priv->virq_dma = ofdev->archdata.irqs[4]; + else + priv->virq_dma = priv->irq_map[0]; + + /* Unmask all PCI interrupts, request_irq will not do that */ + REGSTORE(regs->ctrl, REGLOAD(regs->ctrl)|(priv->irq_mask&0xf)); + } + + /* Setup IRQ handler for non-configuration space access errors */ + err = request_irq(priv->virq_err, grpci2_err_interrupt, IRQF_SHARED, + "GRPCI2_ERR", priv); + if (err) { + printk(KERN_DEBUG "GRPCI2: ERR VIRQ request failed: %d\n", err); + goto err5; + } + + /* + * Enable Error Interrupts. PCI interrupts are unmasked once request_irq + * is called by the PCI Device drivers + */ + REGSTORE(regs->ctrl, REGLOAD(regs->ctrl) | CTRL_EI | CTRL_SI); + + /* Init common layer and scan buses */ + priv->info.ops = &grpci2_ops; + priv->info.map_irq = grpci2_map_irq; + leon_pci_init(ofdev, &priv->info); + + return 0; + +err5: + release_resource(&priv->info.io_space); +err4: + release_resource(&priv->info.mem_space); +err3: + err = -ENOMEM; + iounmap((void *)priv->pci_io_va); +err2: + kfree(priv); +err1: + of_iounmap(&ofdev->resource[0], regs, + resource_size(&ofdev->resource[0])); + return err; +} + +static struct of_device_id grpci2_of_match[] = { + { + .name = "GAISLER_GRPCI2", + }, + { + .name = "01_07c", + }, + {}, +}; + +static struct platform_driver grpci2_of_driver = { + .driver = { + .name = "grpci2", + .owner = THIS_MODULE, + .of_match_table = grpci2_of_match, + }, + .probe = grpci2_of_probe, +}; + +static int __init grpci2_init(void) +{ + return platform_driver_register(&grpci2_of_driver); +} + +subsys_initcall(grpci2_init); From 4819fef5e7cb9a39e1fd59ecd85861b3ffebdcaa Mon Sep 17 00:00:00 2001 From: Matt Evans Date: Wed, 1 Jun 2011 13:01:07 +1000 Subject: [PATCH 045/595] xhci: Bigendian fix for xhci_check_bandwidth() Commit 834cb0fc4712a3b21c6b8c5cb55bd13607191311 "xhci: Fix memory leak bug when dropping endpoints" added a small endian bug. This patch fixes xhci_check_bandwidth() to read add/drop_flags LE. Signed-off-by: Matt Evans Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d9660eb97eb9..ecd202101617 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1849,8 +1849,8 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) /* Free any rings that were dropped, but not changed. */ for (i = 1; i < 31; ++i) { - if ((ctrl_ctx->drop_flags & (1 << (i + 1))) && - !(ctrl_ctx->add_flags & (1 << (i + 1)))) + if ((le32_to_cpu(ctrl_ctx->drop_flags) & (1 << (i + 1))) && + !(le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1)))) xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i); } xhci_zero_in_ctx(xhci, virt_dev); From 2c7d1644406748d7c5da7b9db3c5080296af55bf Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 27 May 2011 21:39:56 +0000 Subject: [PATCH 046/595] sparc: Do not select GENERIC_HARDIRQS_NO_DEPRECATED Config option GENERIC_HARDIRQS_NO_DEPRECATED was removed in commit 78c89825649a9a5ed526c507603196f467d781a5 ("genirq: Remove the now obsolete config options and select statements"), but the select was accidentally reintroduced in commit 6baa9b20a68a88c2fd751cbe8d7652009379351b ("sparc32: genirq support") Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 730dda1ad143..cb1c2f112fa9 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -26,7 +26,6 @@ config SPARC select HAVE_DMA_API_DEBUG select HAVE_ARCH_JUMP_LABEL select HAVE_GENERIC_HARDIRQS - select GENERIC_HARDIRQS_NO_DEPRECATED select GENERIC_IRQ_SHOW select USE_GENERIC_SMP_HELPERS if SMP From e2b0217715c6d10379d94bdfe5560af96eecbb7c Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 1 Jun 2011 23:27:49 +0200 Subject: [PATCH 047/595] xhci: Add defines for hardcoded slot states This needs to be added to the stable trees back to 2.6.34 to support an upcoming bug fix. Signed-off-by: Maarten Lankhorst Signed-off-by: Sarah Sharp Cc: stable@kernel.org --- drivers/usb/host/xhci-dbg.c | 8 ++++---- drivers/usb/host/xhci.h | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 2e0486178dbe..1f50b4468e87 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -438,13 +438,13 @@ char *xhci_get_slot_state(struct xhci_hcd *xhci, struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx); switch (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state))) { - case 0: + case SLOT_STATE_ENABLED: return "enabled/disabled"; - case 1: + case SLOT_STATE_DEFAULT: return "default"; - case 2: + case SLOT_STATE_ADDRESSED: return "addressed"; - case 3: + case SLOT_STATE_CONFIGURED: return "configured"; default: return "reserved"; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index ac0196e7fcf1..bbc1d9afb49c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -560,6 +560,11 @@ struct xhci_slot_ctx { #define SLOT_STATE (0x1f << 27) #define GET_SLOT_STATE(p) (((p) & (0x1f << 27)) >> 27) +#define SLOT_STATE_DISABLED 0 +#define SLOT_STATE_ENABLED SLOT_STATE_DISABLED +#define SLOT_STATE_DEFAULT 1 +#define SLOT_STATE_ADDRESSED 2 +#define SLOT_STATE_CONFIGURED 3 /** * struct xhci_ep_ctx From 001fd3826f4c736ce292315782d015f768399080 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 1 Jun 2011 23:27:50 +0200 Subject: [PATCH 048/595] xhci: Do not issue device reset when device is not setup xHCI controllers respond to a Reset Device command when the Slot is in the Enabled/Disabled state by returning an error. This is fine on other host controllers, but the Etron xHCI host controller returns a vendor-specific error code that the xHCI driver doesn't understand. The xHCI driver then gives up on device enumeration. Instead of issuing a command that will fail, just return. This fixes the issue with the xhci driver not working on ASRock P67 Pro/Extreme boards. This should be backported to stable kernels as far back as 2.6.34. Signed-off-by: Maarten Lankhorst Signed-off-by: Sarah Sharp Cc: stable@kernel.org --- drivers/usb/host/xhci.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ecd202101617..66f3e41bba52 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2467,6 +2467,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_command *reset_device_cmd; int timeleft; int last_freed_endpoint; + struct xhci_slot_ctx *slot_ctx; ret = xhci_check_args(hcd, udev, NULL, 0, false, __func__); if (ret <= 0) @@ -2499,6 +2500,12 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) return -EINVAL; } + /* If device is not setup, there is no point in resetting it */ + slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); + if (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)) == + SLOT_STATE_DISABLED) + return 0; + xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id); /* Allocate the command structure that holds the struct completion. * Assume we're in process context, since the normal device reset From f5182b4155b9d686c5540a6822486400e34ddd98 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 2 Jun 2011 11:33:02 -0700 Subject: [PATCH 049/595] xhci: Disable MSI for some Fresco Logic hosts. Some Fresco Logic hosts, including those found in the AUAU N533V laptop, advertise MSI, but fail to actually generate MSI interrupts. Add a new xHCI quirk to skip MSI enabling for the Fresco Logic host controllers. Fresco Logic confirms that all chips with PCI vendor ID 0x1b73 and device ID 0x1000, regardless of PCI revision ID, do not support MSI. This should be backported to stable kernels as far back as 2.6.36, which was the first kernel to support MSI on xHCI hosts. Signed-off-by: Sarah Sharp Reported-by: Sergey Galanov Cc: stable@kernel.org --- drivers/usb/host/xhci-pci.c | 14 ++++++++++++-- drivers/usb/host/xhci.c | 7 +++++++ drivers/usb/host/xhci.h | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index c408e9f6a707..17541d09eabb 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -106,12 +106,22 @@ static int xhci_pci_setup(struct usb_hcd *hcd) /* Look for vendor-specific quirks */ if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && - pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK && - pdev->revision == 0x0) { + pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) { + if (pdev->revision == 0x0) { xhci->quirks |= XHCI_RESET_EP_QUIRK; xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure" " endpoint cmd after reset endpoint\n"); + } + /* Fresco Logic confirms: all revisions of this chip do not + * support MSI, even though some of them claim to in their PCI + * capabilities. + */ + xhci->quirks |= XHCI_BROKEN_MSI; + xhci_dbg(xhci, "QUIRK: Fresco Logic revision %u " + "has broken MSI implementation\n", + pdev->revision); } + if (pdev->vendor == PCI_VENDOR_ID_NEC) xhci->quirks |= XHCI_NEC_HOST; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 66f3e41bba52..06e7023258d0 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -430,12 +430,19 @@ int xhci_run(struct usb_hcd *hcd) free_irq(hcd->irq, hcd); hcd->irq = -1; + /* Some Fresco Logic host controllers advertise MSI, but fail to + * generate interrupts. Don't even try to enable MSI. + */ + if (xhci->quirks & XHCI_BROKEN_MSI) + goto legacy_irq; + ret = xhci_setup_msix(xhci); if (ret) /* fall back to msi*/ ret = xhci_setup_msi(xhci); if (ret) { +legacy_irq: /* fall back to legacy interrupt*/ ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, hcd->irq_descr, hcd); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index bbc1d9afb49c..7d1ea3bf5e1f 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1307,6 +1307,7 @@ struct xhci_hcd { * commands. */ #define XHCI_EP_LIMIT_QUIRK (1 << 5) +#define XHCI_BROKEN_MSI (1 << 6) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ From 704102a6799ecf7c1b268a43452761dae335f29c Mon Sep 17 00:00:00 2001 From: Shaohui Xie Date: Fri, 3 Jun 2011 10:45:11 +0800 Subject: [PATCH 050/595] powerpc/85xx: fix race bug of calling request_irq after enable elbc interrupts Signed-off-by: Shaohui Xie Signed-off-by: Kumar Gala --- arch/powerpc/sysdev/fsl_lbc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c index 0608b1657da4..d917573cf1a8 100644 --- a/arch/powerpc/sysdev/fsl_lbc.c +++ b/arch/powerpc/sysdev/fsl_lbc.c @@ -196,9 +196,6 @@ static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl, out_be32(&lbc->lteccr, LTECCR_CLEAR); out_be32(&lbc->ltedr, LTEDR_ENABLE); - /* Enable interrupts for any detected events */ - out_be32(&lbc->lteir, LTEIR_ENABLE); - /* Set the monitor timeout value to the maximum for erratum A001 */ if (of_device_is_compatible(node, "fsl,elbc")) clrsetbits_be32(&lbc->lbcr, LBCR_BMT, LBCR_BMTPS); @@ -322,6 +319,9 @@ static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev) goto err; } + /* Enable interrupts for any detected events */ + out_be32(&fsl_lbc_ctrl_dev->regs->lteir, LTEIR_ENABLE); + return 0; err: From 8c47f8d07e16034dfbf736bb4478809aba8a53f1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 2 Jun 2011 22:49:11 -0700 Subject: [PATCH 051/595] sparc: PCIC_PCI needs SPARC32 dependency Reported-by: Stephen Rothwell Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index cb1c2f112fa9..253986bd6bb6 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -529,7 +529,7 @@ config PCI_SYSCALL config PCIC_PCI bool - depends on PCI && !SPARC_LEON + depends on PCI && SPARC32 && !SPARC_LEON default y config LEON_PCI From 840d8e5e964dc51673d0f26e119b27d2898e8417 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Wed, 1 Jun 2011 23:59:10 +0200 Subject: [PATCH 052/595] ASoC: atmel_ssc: Don't try to free ssc if request failed We should only call ssc_free() when ssc_request() succeeds or bad things will happen. Signed-off-by: Joachim Eastwood Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/atmel/atmel_ssc_dai.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 7fbfa051f6e1..eda955b15834 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -848,9 +848,10 @@ int atmel_ssc_set_audio(int ssc_id) if (IS_ERR(ssc)) pr_warn("Unable to parent ASoC SSC DAI on SSC: %ld\n", PTR_ERR(ssc)); - else + else { ssc_pdev->dev.parent = &(ssc->pdev->dev); - ssc_free(ssc); + ssc_free(ssc); + } ret = platform_device_add(ssc_pdev); if (ret < 0) From ef26f20cd117eb3c185038ed7cbf7b235575751d Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 31 May 2011 08:56:10 +0200 Subject: [PATCH 053/595] genirq: Print threaded handler in spurious debug output In forced threaded mode (or with an explicit threaded handler) we only see the primary handler, but not the threaded handler. Signed-off-by: Sebastian Andrzej Siewior Link: http://lkml.kernel.org/r/1306824972-27067-1-git-send-email-sebastian@breakpoint.cc Signed-off-by: Thomas Gleixner --- kernel/irq/spurious.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index dfbd550401b2..c9a78ba30b6f 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -201,10 +201,11 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc, raw_spin_lock_irqsave(&desc->lock, flags); action = desc->action; while (action) { - printk(KERN_ERR "[<%p>]", action->handler); - print_symbol(" (%s)", - (unsigned long)action->handler); - printk("\n"); + printk(KERN_ERR "[<%p>] %pf", action->handler, action->handler); + if (action->thread_fn) + printk(KERN_CONT " threaded [<%p>] %pf", + action->thread_fn, action->thread_fn); + printk(KERN_CONT "\n"); action = action->next; } raw_spin_unlock_irqrestore(&desc->lock, flags); From 3a43e05f4d0600e906fa09f4a65d749288c44592 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 31 May 2011 08:56:11 +0200 Subject: [PATCH 054/595] irq: Handle spurios irq detection for threaded irqs The detection of spurios interrupts is currently limited to first level handler. In force-threaded mode we never notice if the threaded irq does not feel responsible. This patch catches the return value of the threaded handler and forwards it to the spurious detector. If the primary handler returns only IRQ_WAKE_THREAD then the spourious detector ignores it because it gets called again from the threaded handler. [ tglx: Report the erroneous return value early and bail out ] Signed-off-by: Sebastian Andrzej Siewior Link: http://lkml.kernel.org/r/1306824972-27067-2-git-send-email-sebastian@breakpoint.cc Signed-off-by: Thomas Gleixner --- include/linux/irqreturn.h | 6 +++--- kernel/irq/handle.c | 6 ------ kernel/irq/manage.c | 24 ++++++++++++++++++------ kernel/irq/spurious.c | 22 ++++++++++++++++++---- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/include/linux/irqreturn.h b/include/linux/irqreturn.h index 819acaaac3f5..714ba08dc092 100644 --- a/include/linux/irqreturn.h +++ b/include/linux/irqreturn.h @@ -8,9 +8,9 @@ * @IRQ_WAKE_THREAD handler requests to wake the handler thread */ enum irqreturn { - IRQ_NONE, - IRQ_HANDLED, - IRQ_WAKE_THREAD, + IRQ_NONE = (0 << 0), + IRQ_HANDLED = (1 << 0), + IRQ_WAKE_THREAD = (1 << 1), }; typedef enum irqreturn irqreturn_t; diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 90cb55f6d7eb..470d08c82bbe 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -132,12 +132,6 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) switch (res) { case IRQ_WAKE_THREAD: - /* - * Set result to handled so the spurious check - * does not trigger. - */ - res = IRQ_HANDLED; - /* * Catch drivers which return WAKE_THREAD but * did not set up a thread function diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index f7ce0021e1c4..d64bafb1afd0 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -723,13 +723,16 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { } * context. So we need to disable bh here to avoid deadlocks and other * side effects. */ -static void +static irqreturn_t irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action) { + irqreturn_t ret; + local_bh_disable(); - action->thread_fn(action->irq, action->dev_id); + ret = action->thread_fn(action->irq, action->dev_id); irq_finalize_oneshot(desc, action, false); local_bh_enable(); + return ret; } /* @@ -737,10 +740,14 @@ irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action) * preemtible - many of them need to sleep and wait for slow busses to * complete. */ -static void irq_thread_fn(struct irq_desc *desc, struct irqaction *action) +static irqreturn_t irq_thread_fn(struct irq_desc *desc, + struct irqaction *action) { - action->thread_fn(action->irq, action->dev_id); + irqreturn_t ret; + + ret = action->thread_fn(action->irq, action->dev_id); irq_finalize_oneshot(desc, action, false); + return ret; } /* @@ -753,7 +760,8 @@ static int irq_thread(void *data) }; struct irqaction *action = data; struct irq_desc *desc = irq_to_desc(action->irq); - void (*handler_fn)(struct irq_desc *desc, struct irqaction *action); + irqreturn_t (*handler_fn)(struct irq_desc *desc, + struct irqaction *action); int wake; if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD, @@ -783,8 +791,12 @@ static int irq_thread(void *data) desc->istate |= IRQS_PENDING; raw_spin_unlock_irq(&desc->lock); } else { + irqreturn_t action_ret; + raw_spin_unlock_irq(&desc->lock); - handler_fn(desc, action); + action_ret = handler_fn(desc, action); + if (!noirqdebug) + note_interrupt(action->irq, desc, action_ret); } wake = atomic_dec_and_test(&desc->threads_active); diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index c9a78ba30b6f..aa57d5da18c1 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -167,6 +167,13 @@ static void poll_spurious_irqs(unsigned long dummy) jiffies + POLL_SPURIOUS_IRQ_INTERVAL); } +static inline int bad_action_ret(irqreturn_t action_ret) +{ + if (likely(action_ret <= (IRQ_HANDLED | IRQ_WAKE_THREAD))) + return 0; + return 1; +} + /* * If 99,900 of the previous 100,000 interrupts have not been handled * then assume that the IRQ is stuck in some manner. Drop a diagnostic @@ -182,7 +189,7 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *action; unsigned long flags; - if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) { + if (bad_action_ret(action_ret)) { printk(KERN_ERR "irq event %d: bogus return value %x\n", irq, action_ret); } else { @@ -263,7 +270,16 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, if (desc->istate & IRQS_POLL_INPROGRESS) return; - if (unlikely(action_ret != IRQ_HANDLED)) { + /* we get here again via the threaded handler */ + if (action_ret == IRQ_WAKE_THREAD) + return; + + if (bad_action_ret(action_ret)) { + report_bad_irq(irq, desc, action_ret); + return; + } + + if (unlikely(action_ret == IRQ_NONE)) { /* * If we are seeing only the odd spurious IRQ caused by * bus asynchronicity then don't eventually trigger an error, @@ -275,8 +291,6 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, else desc->irqs_unhandled++; desc->last_unhandled = jiffies; - if (unlikely(action_ret != IRQ_NONE)) - report_bad_irq(irq, desc, action_ret); } if (unlikely(try_misrouted_irq(irq, desc, action_ret))) { From e7fbad300a7a6432238f086e3c9a61538a905858 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 31 May 2011 18:14:39 +0200 Subject: [PATCH 055/595] genirq: Fix descriptor init on non-sparse IRQs The genirq changes are initializing descriptors for sparse IRQs quite differently from how non-sparse (stacked?) IRQs are initialized, with the effect that on my platform all IRQs are default-disabled on sparse IRQs and default-enabled if non-sparse IRQs are used, crashing some GPIO driver. Fix this by refactoring the non-sparse IRQs to use the same descriptor init function as the sparse IRQs. Signed-off: Linus Walleij Link: http://lkml.kernel.org/r/1306858479-16622-1-git-send-email-linus.walleij@stericsson.com Cc: stable@kernel.org # 2.6.39 Signed-off-by: Thomas Gleixner --- kernel/irq/irqdesc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 886e80347b32..c7ddc87d6c87 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -257,13 +257,11 @@ int __init early_irq_init(void) count = ARRAY_SIZE(irq_desc); for (i = 0; i < count; i++) { - desc[i].irq_data.irq = i; - desc[i].irq_data.chip = &no_irq_chip; desc[i].kstat_irqs = alloc_percpu(unsigned int); - irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS); - alloc_masks(desc + i, GFP_KERNEL, node); - desc_smp_init(desc + i, node); + alloc_masks(&desc[i], GFP_KERNEL, node); + raw_spin_lock_init(&desc[i].lock); lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); + desc_set_defaults(i, &desc[i], node); } return arch_early_irq_init(); } From c5182b8867e189e14a8df5dbfcba1c73f286e061 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2011 18:55:13 +0100 Subject: [PATCH 056/595] genirq: Ensure we locate the passed IRQ in irq_alloc_descs() When irq_alloc_descs() is called with no base IRQ specified then it will search for a range of IRQs starting from a specified base address. In the case where an IRQ is specified it still does this search in order to ensure that none of the requested range is already allocated and it still uses the from parameter to specify the base for the search. This means that in the case where a base is specified but from is zero (which is reasonable as any IRQ number is in the range specified by a zero from) the function will get confused and try to allocate the first suitably sized block of free IRQs it finds. Instead use a specified IRQ as the base address for the search, and insist that any from that is specified can support that IRQ. Signed-off-by: Mark Brown Link: http://lkml.kernel.org/r/1307037313-15733-1-git-send-email-broonie@opensource.wolfsonmicro.com Signed-off-by: Thomas Gleixner --- kernel/irq/irqdesc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index c7ddc87d6c87..4c60a50e66b2 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -344,6 +344,12 @@ irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node) if (!cnt) return -EINVAL; + if (irq >= 0) { + if (from > irq) + return -EINVAL; + from = irq; + } + mutex_lock(&sparse_irq_lock); start = bitmap_find_next_zero_area(allocated_irqs, IRQ_BITMAP_BITS, From d21cc9f67d689effbfd24bac878bc2c057de8c46 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 2 Jun 2011 10:39:43 -0300 Subject: [PATCH 057/595] perf evlist: Remove dependency on debug routines So far we avoided having to link debug.o in the python binding, keep it that way by not using ui__warning() in evlist.c. Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-4wtew8hd3g7ejnlehtspys2t@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 50aa34879c33..04c8a60075b3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -12,7 +12,6 @@ #include "evlist.h" #include "evsel.h" #include "util.h" -#include "debug.h" #include @@ -257,19 +256,15 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist) return evlist->mmap != NULL ? 0 : -ENOMEM; } -static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel, +static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, int prot, int mask, int fd) { evlist->mmap[idx].prev = 0; evlist->mmap[idx].mask = mask; evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, MAP_SHARED, fd, 0); - if (evlist->mmap[idx].base == MAP_FAILED) { - if (evlist->cpus->map[idx] == -1 && evsel->attr.inherit) - ui__warning("Inherit is not allowed on per-task " - "events using mmap.\n"); + if (evlist->mmap[idx].base == MAP_FAILED) return -1; - } perf_evlist__add_pollfd(evlist, fd); return 0; @@ -289,7 +284,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int m if (output == -1) { output = fd; - if (__perf_evlist__mmap(evlist, evsel, cpu, + if (__perf_evlist__mmap(evlist, cpu, prot, mask, output) < 0) goto out_unmap; } else { @@ -329,7 +324,7 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, in if (output == -1) { output = fd; - if (__perf_evlist__mmap(evlist, evsel, thread, + if (__perf_evlist__mmap(evlist, thread, prot, mask, output) < 0) goto out_unmap; } else { From 9c850d6c4b95bb07fb066eb7f43dd4e3b4842b85 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 2 Jun 2011 10:55:10 -0300 Subject: [PATCH 058/595] perf python: Use exception to propagate errors We were using pr_debug to tell the user about not being able to parse a sample where we should really use the python way of reporting errors: exceptions. Fixes this problem: [root@emilia ~]# python >>> import perf Traceback (most recent call last): File "", line 1, in ImportError: /home/acme/git/build/perf/python/perf.so: undefined symbol: eprintf >>> [root@emilia ~] As we want to keep the objects linked in the python binding (and in the future in a shared library) minimal. Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-m9dba9kaluas0kq8r58z191c@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 69436b3200a4..2dd1698e0932 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -694,14 +694,12 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, err = perf_event__parse_sample(event, first->attr.sample_type, perf_sample_size(first->attr.sample_type), sample_id_all, &pevent->sample); - if (err) { - pr_err("Can't parse sample, err = %d\n", err); - goto end; - } - + if (err) + return PyErr_Format(PyExc_OSError, + "perf: can't parse sample, err=%d", err); return pyevent; } -end: + Py_INCREF(Py_None); return Py_None; } From 56722381b8506733852c44dacf6d7bc5f90aedaf Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 2 Jun 2011 11:04:54 -0300 Subject: [PATCH 059/595] perf evlist: Don't die if sample_{id_all|type} is invalid Fixes two more cases where the python binding would not load: . Not finding die(), which it shouldn't anyway, not good to just stop the world because some particular perf.data file is invalid, just propagate the error to the caller. . Not finding perf_sample_size: fix it by moving it from event.c to evsel, where it belongs, as most cases are moving to operate on an evsel object.o One of the fixed problems: [root@emilia ~]# python >>> import perf Traceback (most recent call last): File "", line 1, in ImportError: /home/acme/git/build/perf/python/perf.so: undefined symbol: perf_sample_size >>> [root@emilia ~]# Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-1hkj7b2cvgbfnoizsekjb6c9@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-test.c | 2 +- tools/perf/util/event.c | 16 ------------ tools/perf/util/event.h | 2 -- tools/perf/util/evlist.c | 55 ++++++++++++++++++++++++--------------- tools/perf/util/evlist.h | 6 +++-- tools/perf/util/evsel.c | 16 ++++++++++++ tools/perf/util/evsel.h | 7 +++++ tools/perf/util/python.c | 2 +- tools/perf/util/session.c | 12 ++++++++- 9 files changed, 74 insertions(+), 44 deletions(-) diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index b67186228c89..2da9162262b0 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -474,7 +474,7 @@ static int test__basic_mmap(void) unsigned int nr_events[nsyscalls], expected_nr_events[nsyscalls], i, j; struct perf_evsel *evsels[nsyscalls], *evsel; - int sample_size = perf_sample_size(attr.sample_type); + int sample_size = __perf_evsel__sample_size(attr.sample_type); for (i = 0; i < nsyscalls; ++i) { char name[64]; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 0fe9adf76379..3c1b8a632101 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -35,22 +35,6 @@ const char *perf_event__name(unsigned int id) return perf_event__names[id]; } -int perf_sample_size(u64 sample_type) -{ - u64 mask = sample_type & PERF_SAMPLE_MASK; - int size = 0; - int i; - - for (i = 0; i < 64; i++) { - if (mask & (1ULL << i)) - size++; - } - - size *= sizeof(u64); - - return size; -} - static struct perf_sample synth_sample = { .pid = -1, .tid = -1, diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index c08332871408..1d7f66488a88 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -82,8 +82,6 @@ struct perf_sample { struct ip_callchain *callchain; }; -int perf_sample_size(u64 sample_type); - #define BUILD_ID_SIZE 20 struct build_id_event { diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 04c8a60075b3..b021ea9265c3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -455,33 +455,46 @@ int perf_evlist__set_filters(struct perf_evlist *evlist) return 0; } -u64 perf_evlist__sample_type(struct perf_evlist *evlist) +bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist) { - struct perf_evsel *pos; - u64 type = 0; - - list_for_each_entry(pos, &evlist->entries, node) { - if (!type) - type = pos->attr.sample_type; - else if (type != pos->attr.sample_type) - die("non matching sample_type"); + struct perf_evsel *pos, *first; + + pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); + + list_for_each_entry_continue(pos, &evlist->entries, node) { + if (first->attr.sample_type != pos->attr.sample_type) + return false; } - return type; + return true; } -bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) +u64 perf_evlist__sample_type(const struct perf_evlist *evlist) +{ + struct perf_evsel *first; + + first = list_entry(evlist->entries.next, struct perf_evsel, node); + return first->attr.sample_type; +} + +bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist) { - bool value = false, first = true; - struct perf_evsel *pos; - - list_for_each_entry(pos, &evlist->entries, node) { - if (first) { - value = pos->attr.sample_id_all; - first = false; - } else if (value != pos->attr.sample_id_all) - die("non matching sample_id_all"); + struct perf_evsel *pos, *first; + + pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); + + list_for_each_entry_continue(pos, &evlist->entries, node) { + if (first->attr.sample_id_all != pos->attr.sample_id_all) + return false; } - return value; + return true; +} + +bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) +{ + struct perf_evsel *first; + + first = list_entry(evlist->entries.next, struct perf_evsel, node); + return first->attr.sample_id_all; } diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 0a1ef1f051f0..b2b862374f37 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -66,7 +66,9 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, void perf_evlist__delete_maps(struct perf_evlist *evlist); int perf_evlist__set_filters(struct perf_evlist *evlist); -u64 perf_evlist__sample_type(struct perf_evlist *evlist); -bool perf_evlist__sample_id_all(const struct perf_evlist *evlist); +u64 perf_evlist__sample_type(const struct perf_evlist *evlist); +bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); +bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); +bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); #endif /* __PERF_EVLIST_H */ diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index cca29ededb5b..0239eb87b232 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -15,6 +15,22 @@ #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) +int __perf_evsel__sample_size(u64 sample_type) +{ + u64 mask = sample_type & PERF_SAMPLE_MASK; + int size = 0; + int i; + + for (i = 0; i < 64; i++) { + if (mask & (1ULL << i)) + size++; + } + + size *= sizeof(u64); + + return size; +} + void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, int idx) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index f79bb2c09a6c..7e9366e4490b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -149,4 +149,11 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel, return __perf_evsel__read(evsel, ncpus, nthreads, true); } +int __perf_evsel__sample_size(u64 sample_type); + +static inline int perf_evsel__sample_size(struct perf_evsel *evsel) +{ + return __perf_evsel__sample_size(evsel->attr.sample_type); +} + #endif /* __PERF_EVSEL_H */ diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 2dd1698e0932..24063b4d41e0 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -692,7 +692,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, first = list_entry(evlist->entries.next, struct perf_evsel, node); err = perf_event__parse_sample(event, first->attr.sample_type, - perf_sample_size(first->attr.sample_type), + perf_evsel__sample_size(first), sample_id_all, &pevent->sample); if (err) return PyErr_Format(PyExc_OSError, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 64500fc78799..f5a8fbdd3f76 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -58,6 +58,16 @@ static int perf_session__open(struct perf_session *self, bool force) goto out_close; } + if (!perf_evlist__valid_sample_type(self->evlist)) { + pr_err("non matching sample_type"); + goto out_close; + } + + if (!perf_evlist__valid_sample_id_all(self->evlist)) { + pr_err("non matching sample_id_all"); + goto out_close; + } + self->size = input_stat.st_size; return 0; @@ -97,7 +107,7 @@ static void perf_session__id_header_size(struct perf_session *session) void perf_session__update_sample_type(struct perf_session *self) { self->sample_type = perf_evlist__sample_type(self->evlist); - self->sample_size = perf_sample_size(self->sample_type); + self->sample_size = __perf_evsel__sample_size(self->sample_type); self->sample_id_all = perf_evlist__sample_id_all(self->evlist); perf_session__id_header_size(self); } From b273fa9716aa1564bee88ceee62f9042981cdc81 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 31 Mar 2011 18:27:42 +0200 Subject: [PATCH 060/595] perf python: Fix argument name list of read_on_cpu() Mandatory arguments need to be present in the argument name list, as well as optional arguments, otherwise python barfs: # ./python/twatch.py Traceback (most recent call last): File "./python/twatch.py", line 41, in main() File "./python/twatch.py", line 32, in main event = evlist.read_on_cpu(cpu) RuntimeError: more argument specifiers than keyword list entries Hence, add cpu to the name list. Cc: David Ahern Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Tom Zanussi Link: http://lkml.kernel.org/r/1301588863-20210-1-git-send-email-fweisbec@gmail.com Signed-off-by: Frederic Weisbecker Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 24063b4d41e0..a9ac0504aabd 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -674,7 +674,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, struct perf_evlist *evlist = &pevlist->evlist; union perf_event *event; int sample_id_all = 1, cpu; - static char *kwlist[] = {"sample_id_all", NULL, NULL}; + static char *kwlist[] = {"cpu", "sample_id_all", NULL, NULL}; int err; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, From c592a7073796de1cd221f957ab693c19d383423f Mon Sep 17 00:00:00 2001 From: Suresh Jayaraman Date: Fri, 3 Jun 2011 12:06:19 +0530 Subject: [PATCH 061/595] cifs: fix the kernel release version in the default security warning message When ntlm security mechanim is used, the message that warns about the upgrade to ntlmv2 got the kernel release version wrong (Blame it on Linus :). Fix it. Signed-off-by: Suresh Jayaraman Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 6d88b82537c3..84c730701c09 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1976,7 +1976,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) warned_on_ntlm = true; cERROR(1, "default security mechanism requested. The default " "security mechanism will be upgraded from ntlm to " - "ntlmv2 in kernel release 2.6.41"); + "ntlmv2 in kernel release 3.1"); } ses->overrideSecFlg = volume_info->secFlg; From d4d84fef6d0366b585b7de13527a0faeca84d9ce Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 2 Jun 2011 10:19:41 -0400 Subject: [PATCH 062/595] slub: always align cpu_slab to honor cmpxchg_double requirement On an architecture without CMPXCHG_LOCAL but with DEBUG_VM enabled, the VM_BUG_ON() in __pcpu_double_call_return_bool() will cause an early panic during boot unless we always align cpu_slab properly. In principle we could remove the alignment-testing VM_BUG_ON() for architectures that don't have CMPXCHG_LOCAL, but leaving it in means that new code will tend not to break x86 even if it is introduced on another platform, and it's low cost to require alignment. Acked-by: David Rientjes Acked-by: Christoph Lameter Signed-off-by: Chris Metcalf Signed-off-by: Pekka Enberg --- include/linux/percpu.h | 3 +++ mm/slub.c | 12 ++++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 8b97308e65df..9ca008f0c542 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -259,6 +259,9 @@ extern void __bad_size_call_parameter(void); * Special handling for cmpxchg_double. cmpxchg_double is passed two * percpu variables. The first has to be aligned to a double word * boundary and the second has to follow directly thereafter. + * We enforce this on all architectures even if they don't support + * a double cmpxchg instruction, since it's a cheap requirement, and it + * avoids breaking the requirement for architectures with the instruction. */ #define __pcpu_double_call_return_bool(stem, pcp1, pcp2, ...) \ ({ \ diff --git a/mm/slub.c b/mm/slub.c index 7be0223531b0..35f351f26193 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2320,16 +2320,12 @@ static inline int alloc_kmem_cache_cpus(struct kmem_cache *s) BUILD_BUG_ON(PERCPU_DYNAMIC_EARLY_SIZE < SLUB_PAGE_SHIFT * sizeof(struct kmem_cache_cpu)); -#ifdef CONFIG_CMPXCHG_LOCAL /* - * Must align to double word boundary for the double cmpxchg instructions - * to work. + * Must align to double word boundary for the double cmpxchg + * instructions to work; see __pcpu_double_call_return_bool(). */ - s->cpu_slab = __alloc_percpu(sizeof(struct kmem_cache_cpu), 2 * sizeof(void *)); -#else - /* Regular alignment is sufficient */ - s->cpu_slab = alloc_percpu(struct kmem_cache_cpu); -#endif + s->cpu_slab = __alloc_percpu(sizeof(struct kmem_cache_cpu), + 2 * sizeof(void *)); if (!s->cpu_slab) return 0; From a947eb95ea03199da7408a64baa97fbb613e9b84 Mon Sep 17 00:00:00 2001 From: Suleiman Souhlal Date: Thu, 2 Jun 2011 00:16:42 -0700 Subject: [PATCH 063/595] SLAB: Record actual last user of freed objects. Currently, when using CONFIG_DEBUG_SLAB, we put in kfree() or kmem_cache_free() as the last user of free objects, which is not very useful, so change it to the caller of those functions instead. Acked-by: David Rientjes Acked-by: Christoph Lameter Signed-off-by: Suleiman Souhlal Signed-off-by: Pekka Enberg --- mm/slab.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index bcfa4987c8ae..d96e223de775 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3604,13 +3604,14 @@ static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac) * Release an obj back to its cache. If the obj has a constructed state, it must * be in this state _before_ it is released. Called with disabled ints. */ -static inline void __cache_free(struct kmem_cache *cachep, void *objp) +static inline void __cache_free(struct kmem_cache *cachep, void *objp, + void *caller) { struct array_cache *ac = cpu_cache_get(cachep); check_irq_off(); kmemleak_free_recursive(objp, cachep->flags); - objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0)); + objp = cache_free_debugcheck(cachep, objp, caller); kmemcheck_slab_free(cachep, objp, obj_size(cachep)); @@ -3801,7 +3802,7 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp) debug_check_no_locks_freed(objp, obj_size(cachep)); if (!(cachep->flags & SLAB_DEBUG_OBJECTS)) debug_check_no_obj_freed(objp, obj_size(cachep)); - __cache_free(cachep, objp); + __cache_free(cachep, objp, __builtin_return_address(0)); local_irq_restore(flags); trace_kmem_cache_free(_RET_IP_, objp); @@ -3831,7 +3832,7 @@ void kfree(const void *objp) c = virt_to_cache(objp); debug_check_no_locks_freed(objp, obj_size(c)); debug_check_no_obj_freed(objp, obj_size(c)); - __cache_free(c, (void *)objp); + __cache_free(c, (void *)objp, __builtin_return_address(0)); local_irq_restore(flags); } EXPORT_SYMBOL(kfree); From 5f0b23eeba2d9105944148e5a85b0bfb34a8ecf5 Mon Sep 17 00:00:00 2001 From: Suresh Jayaraman Date: Fri, 3 Jun 2011 14:19:01 +0530 Subject: [PATCH 064/595] cifs: make CIFS depend on CRYPTO_ECB When CONFIG_CRYPTO_ECB is not set, trying to mount a CIFS share with NTLM security resulted in mount failure with the following error: "CIFS VFS: could not allocate des crypto API" Seems like a leftover from commit 43988d7. Signed-off-by: Suresh Jayaraman CC: Shirish Pargaonkar Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 1cd4c3a1862d..66c68ab9e7df 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -7,6 +7,7 @@ config CIFS select CRYPTO_MD5 select CRYPTO_HMAC select CRYPTO_ARC4 + select CRYPTO_ECB select CRYPTO_DES help This is the client VFS module for the Common Internet File System From bdf492f502ad4f646e9905db1b89e11822826edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 1 Jun 2011 11:01:11 +0200 Subject: [PATCH 065/595] ssb: fix PCI(e) driver regression causing oops on PCI cards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were incorrectly executing PCIe specific workarounds on PCI cards. This resulted in: Machine check in kernel mode. Caused by (from SRR1=149030): Transfer error ack signal Oops: Machine check, sig: 7 [#1] Reported-by: Andreas Schwab Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_pcicore.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 82feb348c8bb..2a20dabec76d 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -539,10 +539,12 @@ void ssb_pcicore_init(struct ssb_pcicore *pc) if (!pc->hostmode) ssb_pcicore_init_clientmode(pc); - /* Additional always once-executed workarounds */ - ssb_pcicore_serdes_workaround(pc); - /* TODO: ASPM */ - /* TODO: Clock Request Update */ + /* Additional PCIe always once-executed workarounds */ + if (dev->id.coreid == SSB_DEV_PCIE) { + ssb_pcicore_serdes_workaround(pc); + /* TODO: ASPM */ + /* TODO: Clock Request Update */ + } } static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) From a99168eece601d2a79ecfcb968ce226f2f30cf98 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 2 Jun 2011 03:09:48 +0300 Subject: [PATCH 066/595] ath5k: Disable fast channel switching by default Disable fast channel change by default on AR2413/AR5413 due to some bug reports (it still works for me but it's better to be safe). Add a module parameter "fastchanswitch" in case anyone wants to enable it and play with it. Signed-off-by: Nick Kossifidis Tested-by: Sedat Dilek Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 11 ++++++++++- drivers/net/wireless/ath/ath5k/reset.c | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 22047628ccfa..b6c5d3715b96 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -72,6 +72,11 @@ static int modparam_all_channels; module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO); MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); +static int modparam_fastchanswitch; +module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO); +MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios."); + + /* Module info */ MODULE_AUTHOR("Jiri Slaby"); MODULE_AUTHOR("Nick Kossifidis"); @@ -2686,6 +2691,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); int ret, ani_mode; + bool fast; ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); @@ -2705,7 +2711,10 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, ath5k_drain_tx_buffs(sc); if (chan) sc->curchan = chan; - ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL, + + fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0; + + ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast, skip_pcu); if (ret) { ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 3510de2cf622..126a4eab35f3 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -1124,8 +1124,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* Non fatal, can happen eg. * on mode change */ ret = 0; - } else + } else { + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, + "fast chan change successful\n"); return 0; + } } /* From 6f213ff1919fab6f8244ceae55631b5d6ef750a7 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 2 Jun 2011 18:17:15 +0200 Subject: [PATCH 067/595] iwlagn: fix channel switch locking We use priv->mutex to avoid race conditions between iwl_chswitch_done() and iwlagn_mac_channel_switch(), when marking channel switch in progress. But iwl_chswitch_done() can be called in atomic context from iwl_rx_csa() or with mutex already taken from iwlagn_commit_rxon(). These bugs were introduced by: commit 79d07325502e73508f917475bc1617b60979dd94 Author: Wey-Yi Guy Date: Thu May 6 08:54:11 2010 -0700 iwlwifi: support channel switch offload in driver To fix remove mutex from iwl_chswitch_done() and use atomic bitops for marking channel switch pending. Also remove iwl2030_hw_channel_switch() since 2000 series adapters are 2.4GHz only devices. Cc: stable@kernel.org # 2.6.36+ Signed-off-by: Stanislaw Gruszka Acked-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-2000.c | 74 --------------------- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 - drivers/net/wireless/iwlwifi/iwl-6000.c | 2 - drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 6 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 19 +++--- drivers/net/wireless/iwlwifi/iwl-core.c | 6 +- drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 13 +--- drivers/net/wireless/iwlwifi/iwl-rx.c | 24 +++---- 9 files changed, 28 insertions(+), 119 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 86feec86d130..2282279cffc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -177,79 +177,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) return 0; } -static int iwl2030_hw_channel_switch(struct iwl_priv *priv, - struct ieee80211_channel_switch *ch_switch) -{ - /* - * MULTI-FIXME - * See iwl_mac_channel_switch. - */ - struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - struct iwl6000_channel_switch_cmd cmd; - const struct iwl_channel_info *ch_info; - u32 switch_time_in_usec, ucode_switch_time; - u16 ch; - u32 tsf_low; - u8 switch_count; - u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); - struct ieee80211_vif *vif = ctx->vif; - struct iwl_host_cmd hcmd = { - .id = REPLY_CHANNEL_SWITCH, - .len = { sizeof(cmd), }, - .flags = CMD_SYNC, - .data = { &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; - switch_count = ch_switch->count; - tsf_low = ch_switch->timestamp & 0x0ffffffff; - /* - * calculate the ucode channel switch time - * adding TSF as one of the factor for when to switch - */ - if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { - if (switch_count > ((priv->ucode_beacon_time - tsf_low) / - beacon_interval)) { - switch_count -= (priv->ucode_beacon_time - - tsf_low) / beacon_interval; - } else - switch_count = 0; - } - if (switch_count <= 1) - 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, - 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); - ch_info = iwl_get_channel_info(priv, priv->band, ch); - if (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; - } - priv->switch_rxon.channel = cmd.channel; - priv->switch_rxon.switch_in_progress = true; - - return iwl_send_cmd_sync(priv, &hcmd); -} - static struct iwl_lib_ops iwl2000_lib = { .set_hw_params = iwl2000_hw_set_hw_params, .rx_handler_setup = iwlagn_rx_handler_setup, @@ -258,7 +185,6 @@ static struct iwl_lib_ops iwl2000_lib = { .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, .send_tx_power = iwlagn_send_tx_power, .update_chain_flags = iwl_update_chain_flags, - .set_channel_switch = iwl2030_hw_channel_switch, .apm_ops = { .init = iwl_apm_init, .config = iwl2000_nic_config, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a70b8cfafda1..5b721c56aee9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -331,8 +331,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, ctx->active.channel, ch); return -EFAULT; } - priv->switch_rxon.channel = cmd.channel; - priv->switch_rxon.switch_in_progress = true; return iwl_send_cmd_sync(priv, &hcmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index fda6fe08cf91..fbe565c816e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -270,8 +270,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, ctx->active.channel, ch); return -EFAULT; } - priv->switch_rxon.channel = cmd.channel; - priv->switch_rxon.switch_in_progress = true; return iwl_send_cmd_sync(priv, &hcmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index a95ad84c5377..2532c7db3aff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -342,10 +342,10 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) * receive commit_rxon request * abort any previous channel switch if still in process */ - if (priv->switch_rxon.switch_in_progress && - (priv->switch_rxon.channel != ctx->staging.channel)) { + if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) && + (priv->switch_channel != ctx->staging.channel)) { IWL_DEBUG_11H(priv, "abort channel switch on %d\n", - le16_to_cpu(priv->switch_rxon.channel)); + le16_to_cpu(priv->switch_channel)); iwl_chswitch_done(priv, false); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a662adcb2adb..8e1942ebd9a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2843,16 +2843,13 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, goto out; if (test_bit(STATUS_EXIT_PENDING, &priv->status) || - test_bit(STATUS_SCANNING, &priv->status)) + test_bit(STATUS_SCANNING, &priv->status) || + test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) goto out; if (!iwl_is_associated_ctx(ctx)) goto out; - /* channel switch in progress */ - if (priv->switch_rxon.switch_in_progress == true) - goto out; - if (priv->cfg->ops->lib->set_channel_switch) { ch = channel->hw_value; @@ -2901,15 +2898,19 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, * at this point, staging_rxon has the * configuration for channel switch */ + set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); + priv->switch_channel = cpu_to_le16(ch); if (priv->cfg->ops->lib->set_channel_switch(priv, - ch_switch)) - priv->switch_rxon.switch_in_progress = false; + ch_switch)) { + clear_bit(STATUS_CHANNEL_SWITCH_PENDING, + &priv->status); + priv->switch_channel = 0; + ieee80211_chswitch_done(ctx->vif, false); + } } } out: mutex_unlock(&priv->mutex); - if (!priv->switch_rxon.switch_in_progress) - ieee80211_chswitch_done(ctx->vif, false); IWL_DEBUG_MAC80211(priv, "leave\n"); } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4653deada05b..213c80c6a668 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -843,12 +843,8 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (priv->switch_rxon.switch_in_progress) { + if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) ieee80211_chswitch_done(ctx->vif, is_success); - mutex_lock(&priv->mutex); - priv->switch_rxon.switch_in_progress = false; - mutex_unlock(&priv->mutex); - } } #ifdef CONFIG_IWLWIFI_DEBUG diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 3bb76f6ea410..a54d416ec345 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -560,6 +560,7 @@ void iwlcore_free_geos(struct iwl_priv *priv); #define STATUS_POWER_PMI 16 #define STATUS_FW_ERROR 17 #define STATUS_DEVICE_ENABLED 18 +#define STATUS_CHANNEL_SWITCH_PENDING 19 static inline int iwl_is_ready(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 22a6e3ec7094..c8de236c141b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -981,17 +981,6 @@ struct traffic_stats { #endif }; -/* - * iwl_switch_rxon: "channel switch" structure - * - * @ switch_in_progress: channel switch in progress - * @ channel: new channel - */ -struct iwl_switch_rxon { - bool switch_in_progress; - __le16 channel; -}; - /* * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds * to perform continuous uCode event logging operation if enabled @@ -1287,7 +1276,7 @@ struct iwl_priv { struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX]; - struct iwl_switch_rxon switch_rxon; + __le16 switch_channel; struct { u32 error_event_table; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 0053e9ea9021..b774517aa9fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -250,19 +250,19 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_rxon_cmd *rxon = (void *)&ctx->active; - if (priv->switch_rxon.switch_in_progress) { - if (!le32_to_cpu(csa->status) && - (csa->channel == priv->switch_rxon.channel)) { - rxon->channel = csa->channel; - ctx->staging.channel = csa->channel; - IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", - le16_to_cpu(csa->channel)); - iwl_chswitch_done(priv, true); - } else { - IWL_ERR(priv, "CSA notif (fail) : channel %d\n", + if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) + return; + + if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { + rxon->channel = csa->channel; + ctx->staging.channel = csa->channel; + IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", le16_to_cpu(csa->channel)); - iwl_chswitch_done(priv, false); - } + iwl_chswitch_done(priv, true); + } else { + IWL_ERR(priv, "CSA notif (fail) : channel %d\n", + le16_to_cpu(csa->channel)); + iwl_chswitch_done(priv, false); } } From 59e7e7078d6c2c6294caf454c6e3695f9d3e46a2 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Thu, 2 Jun 2011 17:28:37 -0300 Subject: [PATCH 068/595] mac80211: call dev_alloc_name before copying name to sdata This partially reverts 1c5cae815d19ffe02bdfda1260949ef2b1806171, because the netdev name is copied into sdata->name, which is used for debugging messages, for example. Otherwise, we get messages like this: wlan%d: authenticated Signed-off-by: Thadeu Lima de Souza Cascardo Cc: Jiri Pirko Cc: David S. Miller Cc: Johannes Berg Cc: "John W. Linville" Signed-off-by: John W. Linville --- net/mac80211/iface.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 49d4f869e0bc..dee30aea9ab3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1145,6 +1145,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, + IEEE80211_ENCRYPT_HEADROOM; ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; + ret = dev_alloc_name(ndev, ndev->name); + if (ret < 0) + goto fail; + ieee80211_assign_perm_addr(local, ndev, type); memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); From d2ac49fe3c7c4730323c1042fb53a2e008643b6a Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Fri, 3 Jun 2011 00:13:26 +0100 Subject: [PATCH 069/595] libertas_sdio: handle spurious interrupts Commit 06e8935febe687e2a561707d4c7ca4245d261dbe adds an IRQ handling optimization for single-function SDIO cards like this one, but at the same time exposes a small hardware bug. During hardware init, an interrupt is generated with (apparently) no source. Previously, mmc threw this interrupt away, but now (due to the optimization), the mmc layer passes this onto libertas, before it is ready (and before it has enabled interrupts), causing a crash. Work around this hardware bug by registering the IRQ handler later and making it capable of handling interrupts with no cause. The change that makes the IRQ handler registration happen later actually eliminates the spurious interrupt as well. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_sdio.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index a7b5cb0c2753..224e9853c480 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -907,7 +907,7 @@ static void if_sdio_interrupt(struct sdio_func *func) card = sdio_get_drvdata(func); cause = sdio_readb(card->func, IF_SDIO_H_INT_STATUS, &ret); - if (ret) + if (ret || !cause) goto out; lbs_deb_sdio("interrupt: 0x%X\n", (unsigned)cause); @@ -1008,10 +1008,6 @@ static int if_sdio_probe(struct sdio_func *func, if (ret) goto release; - ret = sdio_claim_irq(func, if_sdio_interrupt); - if (ret) - goto disable; - /* For 1-bit transfers to the 8686 model, we need to enable the * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 * bit to allow access to non-vendor registers. */ @@ -1082,6 +1078,21 @@ static int if_sdio_probe(struct sdio_func *func, else card->rx_unit = 0; + /* + * Set up the interrupt handler late. + * + * If we set it up earlier, the (buggy) hardware generates a spurious + * interrupt, even before the interrupt has been enabled, with + * CCCR_INTx = 0. + * + * We register the interrupt handler late so that we can handle any + * spurious interrupts, and also to avoid generation of that known + * spurious interrupt in the first place. + */ + ret = sdio_claim_irq(func, if_sdio_interrupt); + if (ret) + goto disable; + /* * Enable interrupts now that everything is set up */ From f124c6ae59e193705c9ddac57684d50006d710e6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 3 Jun 2011 07:45:28 +0300 Subject: [PATCH 070/595] xen: off by one errors in multicalls.c b->args[] has MC_ARGS elements, so the comparison here should be ">=" instead of ">". Otherwise we read past the end of the array one space. CC: stable@kernel.org Signed-off-by: Dan Carpenter Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Jeremy Fitzhardinge --- arch/x86/xen/multicalls.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c index 8bff7e7c290b..1b2b73ff0a6e 100644 --- a/arch/x86/xen/multicalls.c +++ b/arch/x86/xen/multicalls.c @@ -189,10 +189,10 @@ struct multicall_space __xen_mc_entry(size_t args) unsigned argidx = roundup(b->argidx, sizeof(u64)); BUG_ON(preemptible()); - BUG_ON(b->argidx > MC_ARGS); + BUG_ON(b->argidx >= MC_ARGS); if (b->mcidx == MC_BATCH || - (argidx + args) > MC_ARGS) { + (argidx + args) >= MC_ARGS) { mc_stats_flush(b->mcidx == MC_BATCH ? FL_SLOTS : FL_ARGS); xen_mc_flush(); argidx = roundup(b->argidx, sizeof(u64)); @@ -206,7 +206,7 @@ struct multicall_space __xen_mc_entry(size_t args) ret.args = &b->args[argidx]; b->argidx = argidx + args; - BUG_ON(b->argidx > MC_ARGS); + BUG_ON(b->argidx >= MC_ARGS); return ret; } @@ -216,7 +216,7 @@ struct multicall_space xen_mc_extend_args(unsigned long op, size_t size) struct multicall_space ret = { NULL, NULL }; BUG_ON(preemptible()); - BUG_ON(b->argidx > MC_ARGS); + BUG_ON(b->argidx >= MC_ARGS); if (b->mcidx == 0) return ret; @@ -224,14 +224,14 @@ struct multicall_space xen_mc_extend_args(unsigned long op, size_t size) if (b->entries[b->mcidx - 1].op != op) return ret; - if ((b->argidx + size) > MC_ARGS) + if ((b->argidx + size) >= MC_ARGS) return ret; ret.mc = &b->entries[b->mcidx - 1]; ret.args = &b->args[b->argidx]; b->argidx += size; - BUG_ON(b->argidx > MC_ARGS); + BUG_ON(b->argidx >= MC_ARGS); return ret; } From 8b20c8cb89b733f5a73fad1f7ad7cff8325e0034 Mon Sep 17 00:00:00 2001 From: "Govindraj.R" Date: Wed, 1 Jun 2011 11:31:24 +0530 Subject: [PATCH 071/595] spi/omap2: fix uninitialized variable fixes below compilation warning. The variable doesn't actual ever get used uninitialized, but that's no reason to be sloppy. drivers/spi/omap2_mcspi.c: In function 'omap2_mcspi_txrx_dma': drivers/spi/omap2_mcspi.c:301: warning: 'elements' may be used uninitialized in this function Signed-off-by: Govindraj.R [grant.likely: amended description] Signed-off-by: Grant Likely --- drivers/spi/omap2_mcspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index 6f86ba0175ac..969cdd2fe124 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c @@ -298,7 +298,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) unsigned int count, c; unsigned long base, tx_reg, rx_reg; int word_len, data_type, element_count; - int elements; + int elements = 0; u32 l; u8 * rx; const u8 * tx; From f8d8e12dd1e0e2559e2419b7acdaf9eee9865736 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Fri, 3 Jun 2011 12:34:14 +0530 Subject: [PATCH 072/595] ARM: S5P: Fix compilation error for exynos4_defconfig Added Kconfig entry for setup-usb-phy.c on which EHCI support is dependent on. Following the naming convention of other setup files, we have following renaming. usb-phy.c ==> setup-usb-phy.c Signed-off-by: Tushar Behera Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos4/Kconfig | 6 ++++++ arch/arm/mach-exynos4/Makefile | 2 +- arch/arm/mach-exynos4/{usb-phy.c => setup-usb-phy.c} | 0 3 files changed, 7 insertions(+), 1 deletion(-) rename arch/arm/mach-exynos4/{usb-phy.c => setup-usb-phy.c} (100%) diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig index b92c1e557145..1435fc31c4b2 100644 --- a/arch/arm/mach-exynos4/Kconfig +++ b/arch/arm/mach-exynos4/Kconfig @@ -91,6 +91,11 @@ config EXYNOS4_SETUP_FIMC help Common setup code for the camera interfaces. +config EXYNOS4_SETUP_USB_PHY + bool + help + Common setup code for USB PHY controller + # machine support menu "EXYNOS4 Machines" @@ -176,6 +181,7 @@ config MACH_NURI select EXYNOS4_SETUP_I2C3 select EXYNOS4_SETUP_I2C5 select EXYNOS4_SETUP_SDHCI + select EXYNOS4_SETUP_USB_PHY select SAMSUNG_DEV_PWM help Machine support for Samsung Mobile NURI Board. diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile index a9bb94fabaa7..60fe5ecf3599 100644 --- a/arch/arm/mach-exynos4/Makefile +++ b/arch/arm/mach-exynos4/Makefile @@ -56,4 +56,4 @@ obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD) += setup-keypad.o obj-$(CONFIG_EXYNOS4_SETUP_SDHCI) += setup-sdhci.o obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o -obj-$(CONFIG_USB_SUPPORT) += usb-phy.o +obj-$(CONFIG_EXYNOS4_SETUP_USB_PHY) += setup-usb-phy.o diff --git a/arch/arm/mach-exynos4/usb-phy.c b/arch/arm/mach-exynos4/setup-usb-phy.c similarity index 100% rename from arch/arm/mach-exynos4/usb-phy.c rename to arch/arm/mach-exynos4/setup-usb-phy.c From 80839a19804702df2f24ebf24899579fd2ab6d9d Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 2 Jun 2011 18:30:52 +0900 Subject: [PATCH 073/595] ARM: EXYNOS4: Remove compiler warning on exynos4_pwm4_resume Remove compiler warning when no CONFIG_PM arch/arm/mach-exynos4/time.c:209: warning: 'exynos4_pwm4_resume' defined but not used Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos4/time.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-exynos4/time.c b/arch/arm/mach-exynos4/time.c index 86b9fa0d3639..ebb8f38d5405 100644 --- a/arch/arm/mach-exynos4/time.c +++ b/arch/arm/mach-exynos4/time.c @@ -206,6 +206,7 @@ static cycle_t exynos4_pwm4_read(struct clocksource *cs) return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40)); } +#ifdef CONFIG_PM static void exynos4_pwm4_resume(struct clocksource *cs) { unsigned long pclk; @@ -218,6 +219,7 @@ static void exynos4_pwm4_resume(struct clocksource *cs) exynos4_pwm_init(4, ~0); exynos4_pwm_start(4, 1); } +#endif struct clocksource pwm_clocksource = { .name = "pwm_timer4", From 74cdfa538d433dde9720ae02ac48a7be8c0ec3fb Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 2 Jun 2011 18:27:27 +0900 Subject: [PATCH 074/595] ARM: SAMSUNG: Remove unused onenand plat functions There's no place to use these functions. and actually no need to set the platform data. Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/plat-s5p/dev-onenand.c | 12 ------------ arch/arm/plat-samsung/dev-onenand.c | 12 ------------ 2 files changed, 24 deletions(-) diff --git a/arch/arm/plat-s5p/dev-onenand.c b/arch/arm/plat-s5p/dev-onenand.c index 6db926202caa..20336c8f2479 100644 --- a/arch/arm/plat-s5p/dev-onenand.c +++ b/arch/arm/plat-s5p/dev-onenand.c @@ -15,8 +15,6 @@ #include #include -#include -#include #include #include @@ -45,13 +43,3 @@ struct platform_device s5p_device_onenand = { .num_resources = ARRAY_SIZE(s5p_onenand_resources), .resource = s5p_onenand_resources, }; - -void s5p_onenand_set_platdata(struct onenand_platform_data *pdata) -{ - struct onenand_platform_data *pd; - - pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL); - if (!pd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - s5p_device_onenand.dev.platform_data = pd; -} diff --git a/arch/arm/plat-samsung/dev-onenand.c b/arch/arm/plat-samsung/dev-onenand.c index 45ec73287d8c..f54ae71f0cd2 100644 --- a/arch/arm/plat-samsung/dev-onenand.c +++ b/arch/arm/plat-samsung/dev-onenand.c @@ -13,8 +13,6 @@ #include #include -#include -#include #include #include @@ -43,13 +41,3 @@ struct platform_device s3c_device_onenand = { .num_resources = ARRAY_SIZE(s3c_onenand_resources), .resource = s3c_onenand_resources, }; - -void s3c_onenand_set_platdata(struct onenand_platform_data *pdata) -{ - struct onenand_platform_data *pd; - - pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL); - if (!pd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - s3c_device_onenand.dev.platform_data = pd; -} From e4698188444a639ac9a3cfb3e06006dd1d4e7fcc Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 2 Jun 2011 12:56:39 +0200 Subject: [PATCH 075/595] ARM: S3C24xx: Fix missing struct for s3c2410_dma_chan s3c2410_dma_chan is not a type itself, so struct is required. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- 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 c10d10c56e2e..2abf9660bc6c 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -1199,7 +1199,7 @@ EXPORT_SYMBOL(s3c2410_dma_getposition); #ifdef CONFIG_PM -static void s3c2410_dma_suspend_chan(s3c2410_dma_chan *cp) +static void s3c2410_dma_suspend_chan(struct s3c2410_dma_chan *cp) { printk(KERN_DEBUG "suspending dma channel %d\n", cp->number); From de11c5852811665e581ef0b915bb478f38b92fb1 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 2 Jun 2011 12:57:41 +0200 Subject: [PATCH 076/595] ARM: S3C24XX: Move s3c24xx_irq_syscore_ops to plat-s3c24xx/irq.c s3c24xx_irq_syscore_ops was only defined for s3c2410 cpus leading to compile errors on for example 2412 and 2416. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c2410/irq.c | 5 ----- arch/arm/plat-s3c24xx/irq.c | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c index 2854129f8cc7..442869578fd0 100644 --- a/arch/arm/mach-s3c2410/irq.c +++ b/arch/arm/mach-s3c2410/irq.c @@ -27,8 +27,3 @@ #include #include - -struct syscore_ops s3c24xx_irq_syscore_ops = { - .suspend = s3c24xx_irq_suspend, - .resume = s3c24xx_irq_resume, -}; diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index 9aee7e1668b1..fc8c5f89954d 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -668,3 +669,8 @@ void __init s3c24xx_init_irq(void) irqdbf("s3c2410: registered interrupt handlers\n"); } + +struct syscore_ops s3c24xx_irq_syscore_ops = { + .suspend = s3c24xx_irq_suspend, + .resume = s3c24xx_irq_resume, +}; From 2aec0d697725bc4d402d7a9b51587af53a4cca76 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 2 Jun 2011 12:58:30 +0200 Subject: [PATCH 077/595] ARM: S3C2410: remove the now empty mach-s3c2410/irq.c Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c2410/Makefile | 1 - arch/arm/mach-s3c2410/irq.c | 29 ----------------------------- 2 files changed, 30 deletions(-) delete mode 100644 arch/arm/mach-s3c2410/irq.c diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index 0d468e96e83e..81695353d8f4 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile @@ -10,7 +10,6 @@ obj-n := obj- := obj-$(CONFIG_CPU_S3C2410) += s3c2410.o -obj-$(CONFIG_CPU_S3C2410) += irq.o obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c deleted file mode 100644 index 442869578fd0..000000000000 --- a/arch/arm/mach-s3c2410/irq.c +++ /dev/null @@ -1,29 +0,0 @@ -/* linux/arch/arm/mach-s3c2410/irq.c - * - * Copyright (c) 2006 Simtec Electronics - * Ben Dooks - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ - -#include -#include -#include -#include -#include - -#include -#include From aa4a221875873d2a1f9656cb7fd7e545e952b4fa Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Fri, 3 Jun 2011 17:54:40 -0400 Subject: [PATCH 078/595] perf: Comment /proc/sys/kernel/perf_event_paranoid to be part of user ABI Turns out that distro packages use this file as an indicator of the perf event subsystem - this is easier to check for from scripts than the existence of the system call. This is easy enough to keep around for the kernel, so add a comment to make sure it stays so. Signed-off-by: Vince Weaver Cc: David Ahern Cc: Peter Zijlstra Cc: paulus@samba.org Cc: acme@redhat.com Cc: Linus Torvalds Cc: Andrew Morton Link: http://lkml.kernel.org/r/alpine.DEB.2.00.1106031751170.29381@cl320.eecs.utk.edu Signed-off-by: Ingo Molnar --- kernel/sysctl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 4fc92445a29c..f175d98bd355 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -938,6 +938,12 @@ static struct ctl_table kern_table[] = { }, #endif #ifdef CONFIG_PERF_EVENTS + /* + * User-space scripts rely on the existence of this file + * as a feature check for perf_events being enabled. + * + * So it's an ABI, do not remove! + */ { .procname = "perf_event_paranoid", .data = &sysctl_perf_event_paranoid, From d7ebe75b065a7c2d58ffc12f9d2e00d5ea4e71eb Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Fri, 3 Jun 2011 17:59:51 -0400 Subject: [PATCH 079/595] perf: Fix comments in include/linux/perf_event.h Fix include/linux/perf_event.h comments to be consistent with the actual #define names. This is trivial, but it can be a bit confusing when first reading through the file. Signed-off-by: Vince Weaver Cc: Peter Zijlstra Cc: paulus@samba.org Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker Cc: Steven Rostedt Link: http://lkml.kernel.org/r/alpine.DEB.2.00.1106031757090.29381@cl320.eecs.utk.edu Signed-off-by: Ingo Molnar --- include/linux/perf_event.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 3412684ce5d5..e0786e35f247 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -137,14 +137,14 @@ enum perf_event_sample_format { * * struct read_format { * { u64 value; - * { u64 time_enabled; } && PERF_FORMAT_ENABLED - * { u64 time_running; } && PERF_FORMAT_RUNNING + * { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED + * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING * { u64 id; } && PERF_FORMAT_ID * } && !PERF_FORMAT_GROUP * * { u64 nr; - * { u64 time_enabled; } && PERF_FORMAT_ENABLED - * { u64 time_running; } && PERF_FORMAT_RUNNING + * { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED + * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING * { u64 value; * { u64 id; } && PERF_FORMAT_ID * } cntr[nr]; From c316e6a3084cef1a5857cd66bb5429c969f06c93 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 5 Jun 2011 00:37:35 +0000 Subject: [PATCH 080/595] get_net_ns_by_fd() oopses if proc_ns_fget() returns an error BTW, looking through the code related to struct net lifetime rules has caught something else: struct net *get_net_ns_by_fd(int fd) { ... file = proc_ns_fget(fd); if (!file) goto out; ei = PROC_I(file->f_dentry->d_inode); while in proc_ns_fget() we have two return ERR_PTR(...) and not a single path that would return NULL. The other caller of proc_ns_fget() treats ERR_PTR() correctly... Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/core/net_namespace.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 6c6b86d0da15..e41e5110c65c 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -310,19 +310,17 @@ struct net *get_net_ns_by_fd(int fd) struct file *file; struct net *net; - net = ERR_PTR(-EINVAL); file = proc_ns_fget(fd); - if (!file) - goto out; + if (IS_ERR(file)) + return ERR_CAST(file); ei = PROC_I(file->f_dentry->d_inode); - if (ei->ns_ops != &netns_operations) - goto out; + if (ei->ns_ops == &netns_operations) + net = get_net(ei->ns); + else + net = ERR_PTR(-EINVAL); - net = get_net(ei->ns); -out: - if (file) - fput(file); + fput(file); return net; } From b8f07a063163f8216cd891c5b007e839a56b6d93 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 5 Jun 2011 00:54:03 +0000 Subject: [PATCH 081/595] fix return values of l2tp_dfs_seq_open() More fallout from struct net lifetime rules review: PTR_ERR() is *already* negative and failing ->open() should return negatives on failure. Signed-off-by: Al Viro Signed-off-by: James Chapman Signed-off-by: David S. Miller --- net/l2tp/l2tp_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c index b8dbae82fab8..76130134bfa6 100644 --- a/net/l2tp/l2tp_debugfs.c +++ b/net/l2tp/l2tp_debugfs.c @@ -258,7 +258,7 @@ static int l2tp_dfs_seq_open(struct inode *inode, struct file *file) */ pd->net = get_net_ns_by_pid(current->pid); if (IS_ERR(pd->net)) { - rc = -PTR_ERR(pd->net); + rc = PTR_ERR(pd->net); goto err_free_pd; } From 54ff502c283b6cf77c95c05c99dbca40d910b17d Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Thu, 2 Jun 2011 12:42:21 +0000 Subject: [PATCH 082/595] qlcnic: Fix bug in FW queue dump Due to a change in FW template, a bug was introduced in dump queue entries. This is fixed by reinitializing queue address before looping for each que dump operation. Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_hw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index e9656616f2a2..a5d9fbf9d816 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -1406,6 +1406,7 @@ qlcnic_dump_que(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, for (loop = 0; loop < que->no_ops; loop++) { QLCNIC_WR_DUMP_REG(que->sel_addr, base, que_id); + addr = que->read_addr; for (i = 0; i < cnt; i++) { QLCNIC_RD_DUMP_REG(addr, base, &data); *buffer++ = cpu_to_le32(data); From 5b446c6a7179513edcb34706088c4ce901b9a039 Mon Sep 17 00:00:00 2001 From: Sucheta Chakraborty Date: Fri, 3 Jun 2011 05:52:18 +0000 Subject: [PATCH 083/595] qlcnic: Avoid double free of skb in tx path buffer->skb should be marked NULL to avoid double free of the skb. Signed-off-by: Sucheta Chakraborty Signed-off-by: Anirban Chakraborty Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 3ab7d2c7baf2..0f6af5c61a7c 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -2159,6 +2159,7 @@ qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb, nf = &pbuf->frag_array[0]; pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); + pbuf->skb = NULL; } static inline void From 374eeb5a9d77ea719c5c46f4d70226623f4528ce Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 3 Jun 2011 10:35:52 +0000 Subject: [PATCH 084/595] bonding: reset queue mapping prior to transmission to physical device (v5) The bonding driver is multiqueue enabled, in which each queue represents a slave to enable optional steering of output frames to given slaves against the default output policy. However, it needs to reset the skb->queue_mapping prior to queuing to the physical device or the physical slave (if it is multiqueue) could wind up transmitting on an unintended tx queue Change Notes: v2) Based on first pass review, updated the patch to restore the origional queue mapping that was found in bond_select_queue, rather than simply resetting to zero. This preserves the value of queue_mapping when it was set on receive in the forwarding case which is desireable. v3) Fixed spelling an casting error in skb->cb v4) fixed to store raw queue_mapping to avoid double decrement v5) Eric D requested that ->cb access be wrapped in a macro. Signed-off-by: Neil Horman CC: Jay Vosburgh CC: Andy Gospodarek CC: "David S. Miller" Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 17b4dd94da90..652b30e525d0 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -388,6 +388,8 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) return next; } +#define bond_queue_mapping(skb) (*(u16 *)((skb)->cb)) + /** * bond_dev_queue_xmit - Prepare skb for xmit. * @@ -400,6 +402,9 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, { skb->dev = slave_dev; skb->priority = 1; + + skb->queue_mapping = bond_queue_mapping(skb); + if (unlikely(netpoll_tx_running(slave_dev))) bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb); else @@ -4206,6 +4211,7 @@ static inline int bond_slave_override(struct bonding *bond, return res; } + static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) { /* @@ -4216,6 +4222,11 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) */ u16 txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0; + /* + * Save the original txq to restore before passing to the driver + */ + bond_queue_mapping(skb) = skb->queue_mapping; + if (unlikely(txq >= dev->real_num_tx_queues)) { do { txq -= dev->real_num_tx_queues; From fb04883371f2cb7867d24783e7d590036dc9b548 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 19 May 2011 15:44:27 +0200 Subject: [PATCH 085/595] netfilter: add more values to enum ip_conntrack_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following error is raised (and other similar ones) : net/ipv4/netfilter/nf_nat_standalone.c: In function ‘nf_nat_fn’: net/ipv4/netfilter/nf_nat_standalone.c:119:2: warning: case value ‘4’ not in enumerated type ‘enum ip_conntrack_info’ gcc barfs on adding two enum values and getting a not enumerated result : case IP_CT_RELATED+IP_CT_IS_REPLY: Add missing enum values Signed-off-by: Eric Dumazet CC: David Miller Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/nf_conntrack_common.h | 3 +++ net/ipv4/netfilter/ipt_CLUSTERIP.c | 6 +++--- net/ipv4/netfilter/ipt_MASQUERADE.c | 2 +- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 2 +- net/ipv4/netfilter/nf_nat_core.c | 2 +- net/ipv4/netfilter/nf_nat_rule.c | 2 +- net/ipv4/netfilter/nf_nat_standalone.c | 4 ++-- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 2 +- net/netfilter/nf_conntrack_core.c | 4 ++-- net/netfilter/nf_conntrack_ftp.c | 2 +- net/netfilter/nf_conntrack_h323_main.c | 10 ++++------ net/netfilter/nf_conntrack_irc.c | 3 +-- net/netfilter/nf_conntrack_pptp.c | 3 +-- net/netfilter/nf_conntrack_sane.c | 2 +- net/netfilter/nf_conntrack_sip.c | 2 +- net/netfilter/xt_socket.c | 4 ++-- 16 files changed, 26 insertions(+), 27 deletions(-) diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h index 50cdc2559a5a..0d3dd66322ec 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux/netfilter/nf_conntrack_common.h @@ -18,6 +18,9 @@ enum ip_conntrack_info { /* >= this indicates reply direction */ IP_CT_IS_REPLY, + IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY, + IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY, + IP_CT_NEW_REPLY = IP_CT_NEW + IP_CT_IS_REPLY, /* Number of distinct IP_CT types (no NEW in reply dirn). */ IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1 }; diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index d609ac3cb9a4..5c9e97c79017 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -307,7 +307,7 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par) * error messages (RELATED) and information requests (see below) */ if (ip_hdr(skb)->protocol == IPPROTO_ICMP && (ctinfo == IP_CT_RELATED || - ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)) + ctinfo == IP_CT_RELATED_REPLY)) return XT_CONTINUE; /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO, @@ -321,12 +321,12 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par) ct->mark = hash; break; case IP_CT_RELATED: - case IP_CT_RELATED+IP_CT_IS_REPLY: + case IP_CT_RELATED_REPLY: /* FIXME: we don't handle expectations at the * moment. they can arrive on a different node than * the master connection (e.g. FTP passive mode) */ case IP_CT_ESTABLISHED: - case IP_CT_ESTABLISHED+IP_CT_IS_REPLY: + case IP_CT_ESTABLISHED_REPLY: break; default: break; diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index d2ed9dc74ebc..9931152a78b5 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -60,7 +60,7 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par) nat = nfct_nat(ct); NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || - ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); + ctinfo == IP_CT_RELATED_REPLY)); /* Source address is 0.0.0.0 - locally generated packet that is * probably not supposed to be masqueraded. diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 5a03c02af999..db10075dd88e 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -101,7 +101,7 @@ static unsigned int ipv4_confirm(unsigned int hooknum, /* This is where we call the helper: as the packet goes out. */ ct = nf_ct_get(skb, &ctinfo); - if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) + if (!ct || ctinfo == IP_CT_RELATED_REPLY) goto out; help = nfct_help(ct); diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 9c71b2755ce3..3346de5d94d0 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -433,7 +433,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, /* Must be RELATED */ NF_CT_ASSERT(skb->nfctinfo == IP_CT_RELATED || - skb->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY); + skb->nfctinfo == IP_CT_RELATED_REPLY); /* Redirects on non-null nats must be dropped, else they'll start talking to each other without our translation, and be diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 21c30426480b..733c9abc1cbd 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c @@ -53,7 +53,7 @@ ipt_snat_target(struct sk_buff *skb, const struct xt_action_param *par) /* Connection must be valid and new. */ NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || - ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); + ctinfo == IP_CT_RELATED_REPLY)); NF_CT_ASSERT(par->out != NULL); return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC); diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 7317bdf1d457..483b76d042da 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -116,7 +116,7 @@ nf_nat_fn(unsigned int hooknum, switch (ctinfo) { case IP_CT_RELATED: - case IP_CT_RELATED+IP_CT_IS_REPLY: + case IP_CT_RELATED_REPLY: if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { if (!nf_nat_icmp_reply_translation(ct, ctinfo, hooknum, skb)) @@ -144,7 +144,7 @@ nf_nat_fn(unsigned int hooknum, default: /* ESTABLISHED */ NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED || - ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); + ctinfo == IP_CT_ESTABLISHED_REPLY); } return nf_nat_packet(ct, ctinfo, hooknum, skb); diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index c8af58b22562..4111050a9fc5 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -160,7 +160,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum, /* This is where we call the helper: as the packet goes out. */ ct = nf_ct_get(skb, &ctinfo); - if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) + if (!ct || ctinfo == IP_CT_RELATED_REPLY) goto out; help = nfct_help(ct); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 2e1c11f78419..0bd568929403 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -850,7 +850,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, /* It exists; we have (non-exclusive) reference. */ if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) { - *ctinfo = IP_CT_ESTABLISHED + IP_CT_IS_REPLY; + *ctinfo = IP_CT_ESTABLISHED_REPLY; /* Please set reply bit if this packet OK */ *set_reply = 1; } else { @@ -1143,7 +1143,7 @@ static void nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb) /* This ICMP is in reverse direction to the packet which caused it */ ct = nf_ct_get(skb, &ctinfo); if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) - ctinfo = IP_CT_RELATED + IP_CT_IS_REPLY; + ctinfo = IP_CT_RELATED_REPLY; else ctinfo = IP_CT_RELATED; diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index e17cb7c7dd8f..6f5801eac999 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -368,7 +368,7 @@ static int help(struct sk_buff *skb, /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { + ctinfo != IP_CT_ESTABLISHED_REPLY) { pr_debug("ftp: Conntrackinfo = %u\n", ctinfo); return NF_ACCEPT; } diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 18b2ce5c8ced..f03c2d4539f6 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -571,10 +571,9 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff, int ret; /* Until there's been traffic both ways, don't look in packets. */ - if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY) return NF_ACCEPT; - } + pr_debug("nf_ct_h245: skblen = %u\n", skb->len); spin_lock_bh(&nf_h323_lock); @@ -1125,10 +1124,9 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff, int ret; /* Until there's been traffic both ways, don't look in packets. */ - if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY) return NF_ACCEPT; - } + pr_debug("nf_ct_q931: skblen = %u\n", skb->len); spin_lock_bh(&nf_h323_lock); diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index b394aa318776..4f9390b98697 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c @@ -125,8 +125,7 @@ static int help(struct sk_buff *skb, unsigned int protoff, return NF_ACCEPT; /* Until there's been traffic both ways, don't look in packets. */ - if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY) return NF_ACCEPT; /* Not a full tcp header? */ diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 088944824e13..2fd4565144de 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c @@ -519,8 +519,7 @@ conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff, u_int16_t msg; /* don't do any tracking before tcp handshake complete */ - if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY) return NF_ACCEPT; nexthdr_off = protoff; diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index d9e27734b2a2..8501823b3f9b 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c @@ -78,7 +78,7 @@ static int help(struct sk_buff *skb, ct_sane_info = &nfct_help(ct)->help.ct_sane_info; /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) + ctinfo != IP_CT_ESTABLISHED_REPLY) return NF_ACCEPT; /* Not a full tcp header? */ diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index cb5a28581782..93faf6a3a637 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -1423,7 +1423,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, typeof(nf_nat_sip_seq_adjust_hook) nf_nat_sip_seq_adjust; if (ctinfo != IP_CT_ESTABLISHED && - ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) + ctinfo != IP_CT_ESTABLISHED_REPLY) return NF_ACCEPT; /* No Data ? */ diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 9cc46356b577..fe39f7e913df 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c @@ -143,9 +143,9 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, ct = nf_ct_get(skb, &ctinfo); if (ct && !nf_ct_is_untracked(ct) && ((iph->protocol != IPPROTO_ICMP && - ctinfo == IP_CT_IS_REPLY + IP_CT_ESTABLISHED) || + ctinfo == IP_CT_ESTABLISHED_REPLY) || (iph->protocol == IPPROTO_ICMP && - ctinfo == IP_CT_IS_REPLY + IP_CT_RELATED)) && + ctinfo == IP_CT_RELATED_REPLY)) && (ct->status & IPS_SRC_NAT_DONE)) { daddr = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip; From afb523c54718da57ff661950bd3287ec9eeb66bd Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Thu, 2 Jun 2011 09:09:54 +0900 Subject: [PATCH 086/595] ipvs: restore support for iptables SNAT Fix the IPVS priority in LOCAL_IN hook, so that SNAT target in POSTROUTING is supported for IPVS traffic as in 2.6.36 where it worked depending on module load order. Before 2.6.37 we used priority 100 in LOCAL_IN to process remote requests. We used the same priority as iptables SNAT and if IPVS handlers are installed before SNAT handlers we supported SNAT in POSTROUTING for the IPVS traffic. If SNAT is installed before IPVS, the netfilter handlers are before IPVS and netfilter checks the NAT table twice for the IPVS requests: once in LOCAL_IN where IPS_SRC_NAT_DONE is set and second time in POSTROUTING where the SNAT rules are ignored because IPS_SRC_NAT_DONE was already set in LOCAL_IN. But in 2.6.37 we changed the IPVS priority for LOCAL_IN with the goal to be unique (101) forgetting the fact that for IPVS traffic we should not walk both LOCAL_IN and POSTROUTING nat tables. So, change the priority for processing remote IPVS requests from 101 to 99, i.e. before NAT_SRC (100) because we prefer to support SNAT in POSTROUTING instead of LOCAL_IN. It also moves the priority for IPVS replies from 99 to 98. Use constants instead of magic numbers at these places. Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipvs/ip_vs_core.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index bfa808f4da13..55af2242bccd 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1772,7 +1772,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_LOCAL_IN, - .priority = 99, + .priority = NF_IP_PRI_NAT_SRC - 2, }, /* After packet filtering, forward packet through VS/DR, VS/TUN, * or VS/NAT(change destination), so that filtering rules can be @@ -1782,7 +1782,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_LOCAL_IN, - .priority = 101, + .priority = NF_IP_PRI_NAT_SRC - 1, }, /* Before ip_vs_in, change source only for VS/NAT */ { @@ -1790,7 +1790,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_LOCAL_OUT, - .priority = -99, + .priority = NF_IP_PRI_NAT_DST + 1, }, /* After mangle, schedule and forward local requests */ { @@ -1798,7 +1798,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_LOCAL_OUT, - .priority = -98, + .priority = NF_IP_PRI_NAT_DST + 2, }, /* After packet filtering (but before ip_vs_out_icmp), catch icmp * destined for 0.0.0.0/0, which is for incoming IPVS connections */ @@ -1824,7 +1824,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_INET_LOCAL_IN, - .priority = 99, + .priority = NF_IP6_PRI_NAT_SRC - 2, }, /* After packet filtering, forward packet through VS/DR, VS/TUN, * or VS/NAT(change destination), so that filtering rules can be @@ -1834,7 +1834,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_INET_LOCAL_IN, - .priority = 101, + .priority = NF_IP6_PRI_NAT_SRC - 1, }, /* Before ip_vs_in, change source only for VS/NAT */ { @@ -1842,7 +1842,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_LOCAL_OUT, - .priority = -99, + .priority = NF_IP6_PRI_NAT_DST + 1, }, /* After mangle, schedule and forward local requests */ { @@ -1850,7 +1850,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_INET_LOCAL_OUT, - .priority = -98, + .priority = NF_IP6_PRI_NAT_DST + 2, }, /* After packet filtering (but before ip_vs_out_icmp), catch icmp * destined for 0.0.0.0/0, which is for incoming IPVS connections */ From fcbf12817100d23890832801507107718a1fa448 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Wed, 1 Jun 2011 23:35:48 +0200 Subject: [PATCH 087/595] netfilter: ipset: Fix return code for destroy when sets are in use Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipset/ip_set_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 8041befc6555..42aa64b6b0b1 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -767,7 +767,7 @@ ip_set_destroy(struct sock *ctnl, struct sk_buff *skb, if (!attr[IPSET_ATTR_SETNAME]) { for (i = 0; i < ip_set_max; i++) { if (ip_set_list[i] != NULL && ip_set_list[i]->ref) { - ret = IPSET_ERR_BUSY; + ret = -IPSET_ERR_BUSY; goto out; } } From b48e3c5c323fea08c12a340cbb8dcc8ca2431d5b Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Wed, 1 Jun 2011 23:35:49 +0200 Subject: [PATCH 088/595] netfilter: ipset: Use the stored first cidr value instead of '1' The stored cidr values are tried one after anoter. The boolean condition evaluated to '1' instead of the first stored cidr or the default host cidr. Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipset/ip_set_hash_ipportnet.c | 10 ++++++---- net/netfilter/ipset/ip_set_hash_net.c | 8 ++++++-- net/netfilter/ipset/ip_set_hash_netport.c | 6 ++++-- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index 4743e5402522..565a7c5b8818 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c @@ -146,8 +146,9 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, { const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_ipportnet4_elem data = - { .cidr = h->nets[0].cidr || HOST_MASK }; + struct hash_ipportnet4_elem data = { + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK + }; if (data.cidr == 0) return -EINVAL; @@ -394,8 +395,9 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb, { const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_ipportnet6_elem data = - { .cidr = h->nets[0].cidr || HOST_MASK }; + struct hash_ipportnet6_elem data = { + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK + }; if (data.cidr == 0) return -EINVAL; diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c index c4db202b7da4..2aeeabcd5a21 100644 --- a/net/netfilter/ipset/ip_set_hash_net.c +++ b/net/netfilter/ipset/ip_set_hash_net.c @@ -131,7 +131,9 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb, { const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_net4_elem data = { .cidr = h->nets[0].cidr || HOST_MASK }; + struct hash_net4_elem data = { + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK + }; if (data.cidr == 0) return -EINVAL; @@ -296,7 +298,9 @@ hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb, { const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_net6_elem data = { .cidr = h->nets[0].cidr || HOST_MASK }; + struct hash_net6_elem data = { + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK + }; if (data.cidr == 0) return -EINVAL; diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c index d2a40362dd3a..e50d9bb8820b 100644 --- a/net/netfilter/ipset/ip_set_hash_netport.c +++ b/net/netfilter/ipset/ip_set_hash_netport.c @@ -144,7 +144,8 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb, const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netport4_elem data = { - .cidr = h->nets[0].cidr || HOST_MASK }; + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK + }; if (data.cidr == 0) return -EINVAL; @@ -357,7 +358,8 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb, const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netport6_elem data = { - .cidr = h->nets[0].cidr || HOST_MASK }; + .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK + }; if (data.cidr == 0) return -EINVAL; From d9be76f38526dccf84062e3ac3ed3a6a97698565 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Sun, 29 May 2011 23:42:29 +0300 Subject: [PATCH 089/595] netfilter: nf_nat: fix crash in nf_nat_csum Fix crash in nf_nat_csum when mangling packets in OUTPUT hook where skb->dev is not defined, it is set later before POSTROUTING. Problem happens for CHECKSUM_NONE. We can check device from rt but using CHECKSUM_PARTIAL should be safe (skb_checksum_help). Signed-off-by: Julian Anastasov Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/nf_nat_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 99cfa28b6d38..ebc5f8894f99 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -160,7 +160,7 @@ static void nf_nat_csum(struct sk_buff *skb, const struct iphdr *iph, void *data if (skb->ip_summed != CHECKSUM_PARTIAL) { if (!(rt->rt_flags & RTCF_LOCAL) && - skb->dev->features & NETIF_F_V4_CSUM) { + (!skb->dev || skb->dev->features & NETIF_F_V4_CSUM)) { skb->ip_summed = CHECKSUM_PARTIAL; skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) + From 88ed01d17b44bc2bed4ad4835d3b1099bff3dd71 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 2 Jun 2011 15:08:45 +0200 Subject: [PATCH 090/595] netfilter: nf_conntrack: fix ct refcount leak in l4proto->error() This patch fixes a refcount leak of ct objects that may occur if l4proto->error() assigns one conntrack object to one skbuff. In that case, we have to skip further processing in nf_conntrack_in(). With this patch, we can also fix wrong return values (-NF_ACCEPT) for special cases in ICMP[v6] that should not bump the invalid/error statistic counters. Reported-by: Zoltan Menyhart Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 2 +- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 2 +- net/netfilter/nf_conntrack_core.c | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 7404bde95994..ab5b27a2916f 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -160,7 +160,7 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, /* Update skb to refer to this connection */ skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general; skb->nfctinfo = *ctinfo; - return -NF_ACCEPT; + return NF_ACCEPT; } /* Small and modified version of icmp_rcv */ diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 1df3c8b6bf47..7c05e7eacbc6 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -177,7 +177,7 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl, /* Update skb to refer to this connection */ skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general; skb->nfctinfo = *ctinfo; - return -NF_ACCEPT; + return NF_ACCEPT; } static int diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 0bd568929403..f7af8b866017 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -922,6 +922,9 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, ret = -ret; goto out; } + /* ICMP[v6] protocol trackers may assign one conntrack. */ + if (skb->nfct) + goto out; } ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, From d232b8dded624af3e346b13807a591c63b601c44 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 27 May 2011 20:36:51 -0400 Subject: [PATCH 091/595] netfilter: use unsigned variables for packet lengths in ip[6]_queue. Netlink message lengths can't be negative, so use unsigned variables. Signed-off-by: Dave Jones Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/ip_queue.c | 3 ++- net/ipv6/netfilter/ip6_queue.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index d2c1311cb28d..f7f9bd7ba12d 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -402,7 +402,8 @@ ipq_dev_drop(int ifindex) static inline void __ipq_rcv_skb(struct sk_buff *skb) { - int status, type, pid, flags, nlmsglen, skblen; + int status, type, pid, flags; + unsigned int nlmsglen, skblen; struct nlmsghdr *nlh; skblen = skb->len; diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 413ab0754e1f..065fe405fb58 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -403,7 +403,8 @@ ipq_dev_drop(int ifindex) static inline void __ipq_rcv_skb(struct sk_buff *skb) { - int status, type, pid, flags, nlmsglen, skblen; + int status, type, pid, flags; + unsigned int nlmsglen, skblen; struct nlmsghdr *nlh; skblen = skb->len; From 5fb9fb132c5a83010cd8d4bf6d0ee34fb3b9d488 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 3 Jun 2011 21:31:27 +0000 Subject: [PATCH 092/595] net: fix smc91x.c device tree support Fix missing semicolon at end of smc91x.c match tabledevice driver. Also remove unnecessary #ifdef around of_match_table pointer. Signed-off-by: Grant Likely Signed-off-by: David S. Miller --- drivers/net/smc91x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index dc4805f473e3..f6285748bd3c 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -2400,8 +2400,10 @@ static const struct of_device_id smc91x_match[] = { { .compatible = "smsc,lan91c94", }, { .compatible = "smsc,lan91c111", }, {}, -} +}; MODULE_DEVICE_TABLE(of, smc91x_match); +#else +#define smc91x_match NULL #endif static struct dev_pm_ops smc_drv_pm_ops = { @@ -2416,9 +2418,7 @@ static struct platform_driver smc_driver = { .name = CARDNAME, .owner = THIS_MODULE, .pm = &smc_drv_pm_ops, -#ifdef CONFIG_OF .of_match_table = smc91x_match, -#endif }, }; From 298c48a811673ba5e292359545f3af6d1a6c9764 Mon Sep 17 00:00:00 2001 From: Srinivas KANDAGATLA Date: Thu, 2 Jun 2011 10:30:44 +0000 Subject: [PATCH 093/595] sh: fix wrong icache/dcache address-array start addr in cache-debugfs. This patch fixes a icache/dcache address-array start address while dumping its entires in debugfs. Perviously the code was attempting to remember the address in static variable, which is no more required for debugfs, as the function can be executed in one pass. Without this patch the start address ends up in wrong place and the /sys/kernel/debug/sh/icache or dcache debugfs contents may not be correct. Signed-off-by: Srinivas Kandagatla Cc: Stuart Menefy Signed-off-by: Paul Mundt --- arch/sh/mm/cache-debugfs.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c index 52411462c409..115725198038 100644 --- a/arch/sh/mm/cache-debugfs.c +++ b/arch/sh/mm/cache-debugfs.c @@ -26,9 +26,9 @@ static int cache_seq_show(struct seq_file *file, void *iter) { unsigned int cache_type = (unsigned int)file->private; struct cache_info *cache; - unsigned int waysize, way, cache_size; - unsigned long ccr, base; - static unsigned long addrstart = 0; + unsigned int waysize, way; + unsigned long ccr; + unsigned long addrstart = 0; /* * Go uncached immediately so we don't skew the results any @@ -45,28 +45,13 @@ static int cache_seq_show(struct seq_file *file, void *iter) } if (cache_type == CACHE_TYPE_DCACHE) { - base = CACHE_OC_ADDRESS_ARRAY; + addrstart = CACHE_OC_ADDRESS_ARRAY; cache = ¤t_cpu_data.dcache; } else { - base = CACHE_IC_ADDRESS_ARRAY; + addrstart = CACHE_IC_ADDRESS_ARRAY; cache = ¤t_cpu_data.icache; } - /* - * Due to the amount of data written out (depending on the cache size), - * we may be iterated over multiple times. In this case, keep track of - * the entry position in addrstart, and rewind it when we've hit the - * end of the cache. - * - * Likewise, the same code is used for multiple caches, so care must - * be taken for bouncing addrstart back and forth so the appropriate - * cache is hit. - */ - cache_size = cache->ways * cache->sets * cache->linesz; - if (((addrstart & 0xff000000) != base) || - (addrstart & 0x00ffffff) > cache_size) - addrstart = base; - waysize = cache->sets; /* From cd3c18ba2fac14b34d03cae111f215009735ea06 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 31 May 2011 14:37:23 -0700 Subject: [PATCH 094/595] USB: xhci - fix interval calculation for FS isoc endpoints Full-speed isoc endpoints specify interval in exponent based form in frames, not microframes, so we need to adjust accordingly. NEC xHCI host controllers will return an error code of 0x11 if a full speed isochronous endpoint is added with the Interval field set to something less than 3 (2^3 = 8 microframes, or one frame). It is impossible for a full speed device to have an interval smaller than one frame. This was always an issue in the xHCI driver, but commit dfa49c4ad120a784ef1ff0717168aa79f55a483a "USB: xhci - fix math in xhci_get_endpoint_interval()" removed the clamping of the minimum value in the Interval field, which revealed this bug. This needs to be backported to stable kernels back to 2.6.31. Reported-by: Matt Evans Signed-off-by: Dmitry Torokhov Signed-off-by: Sarah Sharp Cc: stable@kernel.org --- drivers/usb/host/xhci-mem.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 26caba4c1950..0f8e1d29a858 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -985,9 +985,19 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev, interval = clamp_val(ep->desc.bInterval, 1, 16) - 1; if (interval != ep->desc.bInterval - 1) dev_warn(&udev->dev, - "ep %#x - rounding interval to %d microframes\n", + "ep %#x - rounding interval to %d %sframes\n", ep->desc.bEndpointAddress, - 1 << interval); + 1 << interval, + udev->speed == USB_SPEED_FULL ? "" : "micro"); + + if (udev->speed == USB_SPEED_FULL) { + /* + * Full speed isoc endpoints specify interval in frames, + * not microframes. We are using microframes everywhere, + * so adjust accordingly. + */ + interval += 3; /* 1 frame = 2^3 uframes */ + } return interval; } From ad377c630864e2609c54385907493dbf68a34295 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 25 May 2011 11:34:57 +0200 Subject: [PATCH 095/595] arm: mxs: include asm/processor.h for cpu_relax() I get this build error as of today: arch/arm/mach-mxs/ocotp.c: In function 'mxs_get_ocotp': arch/arm/mach-mxs/ocotp.c:54: error: implicit declaration of function 'cpu_relax' make[2]: *** [arch/arm/mach-mxs/ocotp.o] Error 1 Looks like it has been indirectly included before which broke now. Include it directly. Signed-off-by: Wolfram Sang Cc: Shawn Guo Signed-off-by: Sascha Hauer --- arch/arm/mach-mxs/ocotp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c index 65157a35dbba..54add60f94c9 100644 --- a/arch/arm/mach-mxs/ocotp.c +++ b/arch/arm/mach-mxs/ocotp.c @@ -16,6 +16,8 @@ #include #include +#include /* for cpu_relax() */ + #include #define OCOTP_WORD_OFFSET 0x20 From 5f85e931278ff80aa3ea7861a73a6c6ce940f2e9 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 28 May 2011 16:05:08 -0300 Subject: [PATCH 096/595] ARM: mx51/sdma: Check the chip revision in run-time Check the MX51 chip revision in run-time so that the correct SDMA firmware can be loaded. While at it also remove the silicon revision from the sdma_script_start_addrs structure name for MX51. All the MX51 revisions share the same SDMA start addresses. Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/devices/platform-imx-dma.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-mxc/devices/platform-imx-dma.c b/arch/arm/plat-mxc/devices/platform-imx-dma.c index 3538b85ede91..b130f60ca6b7 100644 --- a/arch/arm/plat-mxc/devices/platform-imx-dma.c +++ b/arch/arm/plat-mxc/devices/platform-imx-dma.c @@ -139,7 +139,7 @@ static struct sdma_script_start_addrs addr_imx35_to2 = { #endif #ifdef CONFIG_SOC_IMX51 -static struct sdma_script_start_addrs addr_imx51_to1 = { +static struct sdma_script_start_addrs addr_imx51 = { .ap_2_ap_addr = 642, .uart_2_mcu_addr = 817, .mcu_2_app_addr = 747, @@ -196,7 +196,9 @@ static int __init imxXX_add_imx_dma(void) #if defined(CONFIG_SOC_IMX51) if (cpu_is_mx51()) { - imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51_to1; + int to_version = mx51_revision() >> 4; + imx51_imx_sdma_data.pdata.to_version = to_version; + imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51; ret = imx_add_imx_sdma(&imx51_imx_sdma_data); } else #endif From 363e9f05cbd105a900b7baf2cc55ec0cba546d08 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 6 Jun 2011 17:57:58 +0900 Subject: [PATCH 097/595] sh: Remove compressed kernel libgcc dependency. SH-2A is unable to combine the kernel and libgcc objects due to fundamental disagreements over FDPIC settings. As the kernel already contains all of the libgcc bits broken out, there's not much need to bother with the linking anymore, as everything can already be derived from the lib dir. This simply plugs in the necessary bits to ensure that everything is built uniformly, enabling us to wean the compressed build off of explicit libgcc linking. Reported-by: Phil Edworthy Signed-off-by: Paul Mundt --- arch/sh/boot/compressed/Makefile | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile index 780e083e4d17..23bc849d9c64 100644 --- a/arch/sh/boot/compressed/Makefile +++ b/arch/sh/boot/compressed/Makefile @@ -27,8 +27,6 @@ IMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \ $(CONFIG_BOOT_LINK_OFFSET)]') endif -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) - ifeq ($(CONFIG_MCOUNT),y) ORIG_CFLAGS := $(KBUILD_CFLAGS) KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) @@ -37,7 +35,25 @@ endif LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext $(IMAGE_OFFSET) -e startup \ -T $(obj)/../../kernel/vmlinux.lds -$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE +# +# Pull in the necessary libgcc bits from the in-kernel implementation. +# +lib1funcs-$(CONFIG_SUPERH32) := ashiftrt.S ashldi3.c ashrsi3.S ashlsi3.S \ + lshrsi3.S +lib1funcs-obj := \ + $(addsuffix .o, $(basename $(addprefix $(obj)/, $(lib1funcs-y)))) + +lib1funcs-dir := $(srctree)/arch/$(SRCARCH)/lib +ifeq ($(BITS),64) + lib1funcs-dir := $(addsuffix $(BITS), $(lib1funcs-dir)) +endif + +KBUILD_CFLAGS += -I$(lib1funcs-dir) + +$(addprefix $(obj)/,$(lib1funcs-y)): $(obj)/%: $(lib1funcs-dir)/% FORCE + $(call cmd,shipped) + +$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(lib1funcs-obj) FORCE $(call if_changed,ld) @: From 2fdf99934c2c39848ad3633ce504a0262f21faf9 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 30 May 2011 19:44:22 +0100 Subject: [PATCH 098/595] ARM: 6946/1: vexpress: move v2m clock init to init_early Commit 7ff550de99141cbd3be0129d563cc4554fdde9f6 breaks vexpress booting. The v2m clock table needs to be setup in init_early before the timer initialization occurs. Signed-off-by: Rob Herring Signed-off-by: Russell King --- arch/arm/mach-vexpress/v2m.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 285edcd2da2a..9e6b93b1a043 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -46,12 +46,6 @@ static struct map_desc v2m_io_desc[] __initdata = { }, }; -static void __init v2m_init_early(void) -{ - ct_desc->init_early(); - versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000); -} - static void __init v2m_timer_init(void) { u32 scctrl; @@ -365,6 +359,13 @@ static struct clk_lookup v2m_lookups[] = { }, }; +static void __init v2m_init_early(void) +{ + ct_desc->init_early(); + clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups)); + versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000); +} + static void v2m_power_off(void) { if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0)) @@ -418,8 +419,6 @@ static void __init v2m_init(void) { int i; - clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups)); - platform_device_register(&v2m_pcie_i2c_device); platform_device_register(&v2m_ddc_i2c_device); platform_device_register(&v2m_flash_device); From 9425032b77c3a4f066a032bac7f7d08668b6cc3c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 31 May 2011 22:10:03 +0100 Subject: [PATCH 099/595] ARM: 6947/2: mach-u300: fix compilation error in timer The introduction of the mmio timer accidentally referenced the old clocksource struct which does not exist anymore. Fix this by using a simple string instead. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-u300/timer.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index 891cf44591e0..18d7fa0603c2 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c @@ -411,8 +411,7 @@ static void __init u300_timer_init(void) /* Use general purpose timer 2 as clock source */ if (clocksource_mmio_init(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC, "GPT2", rate, 300, 32, clocksource_mmio_readl_up)) - printk(KERN_ERR "timer: failed to initialize clock " - "source %s\n", clocksource_u300_1mhz.name); + pr_err("timer: failed to initialize U300 clock source\n"); clockevents_calc_mult_shift(&clockevent_u300_1mhz, rate, APPTIMER_MIN_RANGE); From 9a819d8ac8197b44bbc2adad592b677fe749804d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 31 May 2011 08:09:39 +0100 Subject: [PATCH 100/595] ARM: 6948/1: Fix .size directives for __arm{7,9}tdmi_proc_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gas used to accept (and ignore?) .size directives which referred to undefined symbols, as these do. In binutils 2.21 these are treated as fatal errors. The issue in proc-arm7tdmi.S was also fixed independently by Peter Chubb. Signed-off-by: Ben Hutchings Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/mm/proc-arm7tdmi.S | 2 +- arch/arm/mm/proc-arm9tdmi.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S index e4c165ca6696..537ffcb0646d 100644 --- a/arch/arm/mm/proc-arm7tdmi.S +++ b/arch/arm/mm/proc-arm7tdmi.S @@ -146,7 +146,7 @@ __arm7tdmi_proc_info: .long 0 .long 0 .long v4_cache_fns - .size __arm7tdmi_proc_info, . - __arm7dmi_proc_info + .size __arm7tdmi_proc_info, . - __arm7tdmi_proc_info .type __triscenda7_proc_info, #object __triscenda7_proc_info: diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S index 7b7ebd4d096d..546b54da1005 100644 --- a/arch/arm/mm/proc-arm9tdmi.S +++ b/arch/arm/mm/proc-arm9tdmi.S @@ -116,7 +116,7 @@ __arm9tdmi_proc_info: .long 0 .long 0 .long v4_cache_fns - .size __arm9tdmi_proc_info, . - __arm9dmi_proc_info + .size __arm9tdmi_proc_info, . - __arm9tdmi_proc_info .type __p2001_proc_info, #object __p2001_proc_info: From 45f6d7e0e634d49744c1a590461ed1bb3d2201ac Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 2 Jun 2011 15:01:36 +0100 Subject: [PATCH 101/595] ARM: 6951/1: include .bss in memory layout information The "Virtual memory kernel layout" message at startup already prints .text and .data. Print .bss too. Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/mm/init.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 2c2cce9cd8c8..b2cf9460ea60 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -635,7 +635,8 @@ void __init mem_init(void) " modules : 0x%08lx - 0x%08lx (%4ld MB)\n" " .init : 0x%p" " - 0x%p" " (%4d kB)\n" " .text : 0x%p" " - 0x%p" " (%4d kB)\n" - " .data : 0x%p" " - 0x%p" " (%4d kB)\n", + " .data : 0x%p" " - 0x%p" " (%4d kB)\n" + " .bss : 0x%p" " - 0x%p" " (%4d kB)\n", MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) + (PAGE_SIZE)), @@ -657,7 +658,8 @@ void __init mem_init(void) MLK_ROUNDUP(__init_begin, __init_end), MLK_ROUNDUP(_text, _etext), - MLK_ROUNDUP(_sdata, _edata)); + MLK_ROUNDUP(_sdata, _edata), + MLK_ROUNDUP(__bss_start, __bss_stop)); #undef MLK #undef MLM From 9fc2552a68eb28f95f367156cf46a3da7843ff37 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sun, 5 Jun 2011 02:24:58 +0100 Subject: [PATCH 102/595] ARM: 6952/1: fix lockdep warning of "unannotated irqs-off" This patch fixes the lockdep warning of "unannotated irqs-off"[1]. After entering __irq_usr, arm core will disable interrupt automatically, but __irq_usr does not annotate the irq disable, so lockdep may complain the warning if it has chance to check this in irq handler. This patch adds trace_hardirqs_off in __irq_usr before entering irq_handler to handle the irq, also calls ret_to_user_from_irq to avoid calling disable_irq again. This is also a fix for irq off tracer. [1], lockdep warning log of "unannotated irqs-off" [ 13.804687] ------------[ cut here ]------------ [ 13.809570] WARNING: at kernel/lockdep.c:3335 check_flags+0x78/0x1d0() [ 13.816467] Modules linked in: [ 13.819732] Backtrace: [ 13.822357] [] (dump_backtrace+0x0/0x100) from [] (dump_stack+0x20/0x24) [ 13.831268] r6:c07d8c2c r5:00000d07 r4:00000000 r3:00000000 [ 13.837280] [] (dump_stack+0x0/0x24) from [] (warn_slowpath_common+0x5c/0x74) [ 13.846649] [] (warn_slowpath_common+0x0/0x74) from [] (warn_slowpath_null+0x2c/0x34) [ 13.856781] r8:00000000 r7:00000000 r6:c18b8194 r5:60000093 r4:ef182000 [ 13.863708] r3:00000009 [ 13.866485] [] (warn_slowpath_null+0x0/0x34) from [] (check_flags+0x78/0x1d0) [ 13.875823] [] (check_flags+0x0/0x1d0) from [] (lock_acquire+0x4c/0x150) [ 13.884704] [] (lock_acquire+0x0/0x150) from [] (_raw_spin_lock+0x4c/0x84) [ 13.893798] [] (_raw_spin_lock+0x0/0x84) from [] (sched_ttwu_pending+0x58/0x8c) [ 13.903320] r6:ef92d040 r5:00000003 r4:c18b8180 [ 13.908233] [] (sched_ttwu_pending+0x0/0x8c) from [] (scheduler_ipi+0x18/0x1c) [ 13.917663] r6:ef183fb0 r5:00000003 r4:00000000 r3:00000001 [ 13.923645] [] (scheduler_ipi+0x0/0x1c) from [] (do_IPI+0x9c/0xfc) [ 13.932006] [] (do_IPI+0x0/0xfc) from [] (__irq_usr+0x48/0xe0) [ 13.939971] Exception stack(0xef183fb0 to 0xef183ff8) [ 13.945281] 3fa0: ffffffc3 0001500c 00000001 0001500c [ 13.953948] 3fc0: 00000050 400b45f0 400d9000 00000000 00000001 400d9600 6474e552 bea05b3c [ 13.962585] 3fe0: 400d96c0 bea059c0 400b6574 400b65d8 20000010 ffffffff [ 13.969573] r6:00000403 r5:fa240100 r4:ffffffff r3:20000010 [ 13.975585] ---[ end trace efc4896ab0fb62cb ]--- [ 13.980468] possible reason: unannotated irqs-off. [ 13.985534] irq event stamp: 1610 [ 13.989044] hardirqs last enabled at (1610): [] no_work_pending+0x8/0x2c [ 13.997131] hardirqs last disabled at (1609): [] ret_slow_syscall+0xc/0x1c [ 14.005371] softirqs last enabled at (0): [] copy_process+0x2cc/0xa24 [ 14.013183] softirqs last disabled at (0): [< (null)>] (null) Signed-off-by: Ming Lei Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 6 +++++- arch/arm/kernel/entry-common.S | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index e8d885676807..90c62cd51ca9 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -435,6 +435,10 @@ __irq_usr: usr_entry kuser_cmpxchg_check +#ifdef CONFIG_IRQSOFF_TRACER + bl trace_hardirqs_off +#endif + get_thread_info tsk #ifdef CONFIG_PREEMPT ldr r8, [tsk, #TI_PREEMPT] @ get preempt count @@ -453,7 +457,7 @@ __irq_usr: #endif mov why, #0 - b ret_to_user + b ret_to_user_from_irq UNWIND(.fnend ) ENDPROC(__irq_usr) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 1e7b04a40a31..b2a27b6b0046 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -64,6 +64,7 @@ work_resched: ENTRY(ret_to_user) ret_slow_syscall: disable_irq @ disable interrupts +ENTRY(ret_to_user_from_irq) ldr r1, [tsk, #TI_FLAGS] tst r1, #_TIF_WORK_MASK bne work_pending @@ -75,6 +76,7 @@ no_work_pending: arch_ret_to_user r1, lr restore_user_regs fast = 0, offset = 0 +ENDPROC(ret_to_user_from_irq) ENDPROC(ret_to_user) /* From 17ee083b7897ab27b4949c42de805889ebd2b4c5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 5 May 2011 17:23:10 +0100 Subject: [PATCH 103/595] ARM: 6894/1: mmci: trigger card detect IRQs on falling and rising edges Right now the card detect IRQ for MMCI is requested without any flags which will give some default machine-specified IRQ behaviour. However on the U300 rising+falling edges (such as can be expected from a simple GPIO to generate when inserting/removing a card) need to be requested explicitly. Cc: Rabin Vincent Cc: Ulf Hansson Cc: Sebastian Rasmussen Signed-off-by: Linus Walleij Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 5da5bea0f9f0..7721de942c69 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -1144,9 +1144,17 @@ static int __devinit mmci_probe(struct amba_device *dev, else if (ret != -ENOSYS) goto err_gpio_cd; + /* + * A gpio pin that will detect cards when inserted and removed + * will most likely want to trigger on the edges if it is + * 0 when ejected and 1 when inserted (or mutatis mutandis + * for the inverted case) so we request triggers on both + * edges. + */ ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd), - mmci_cd_irq, 0, - DRIVER_NAME " (cd)", host); + mmci_cd_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + DRIVER_NAME " (cd)", host); if (ret >= 0) host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd); } From 1622ee1822e8adb391b55a09e3cd5144bd9fad47 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Jun 2011 17:13:57 +0100 Subject: [PATCH 104/595] ASoC: Only update SYSCLK_ENA when pausing WM8915 SYSCLK Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8915.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8915.c b/sound/soc/codecs/wm8915.c index a0b1a7278284..28fbf072b9c0 100644 --- a/sound/soc/codecs/wm8915.c +++ b/sound/soc/codecs/wm8915.c @@ -1839,7 +1839,7 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai, int old; /* Disable SYSCLK while we reconfigure */ - old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1); + old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1) & WM8915_SYSCLK_ENA; snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, WM8915_SYSCLK_ENA, 0); From 6ac340623c5d2a945030814d900701439772ff57 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Jun 2011 18:20:50 +0100 Subject: [PATCH 105/595] ASoC: Add missing break in WM8915 FLL source selection Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8915.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wm8915.c b/sound/soc/codecs/wm8915.c index 28fbf072b9c0..e2ab4fac2819 100644 --- a/sound/soc/codecs/wm8915.c +++ b/sound/soc/codecs/wm8915.c @@ -2038,6 +2038,7 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source, break; case WM8915_FLL_MCLK2: reg = 1; + break; case WM8915_FLL_DACLRCLK1: reg = 2; break; From 0de66d5b35ee148455e268b2782873204ffdef4b Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 6 Jun 2011 16:04:02 +0200 Subject: [PATCH 106/595] x86/amd-iommu: Fix 3 possible endless loops The driver contains several loops counting on an u16 value where the exit-condition is checked against variables that can have values up to 0xffff. In this case the loops will never exit. This patch fixed 3 such loops. Cc: stable@kernel.org Signed-off-by: Joerg Roedel --- arch/x86/kernel/amd_iommu_init.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 9179c21120a8..bfc8453bd98d 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -731,8 +731,8 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, { u8 *p = (u8 *)h; u8 *end = p, flags = 0; - u16 dev_i, devid = 0, devid_start = 0, devid_to = 0; - u32 ext_flags = 0; + u16 devid = 0, devid_start = 0, devid_to = 0; + u32 dev_i, ext_flags = 0; bool alias = false; struct ivhd_entry *e; @@ -887,7 +887,7 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, /* Initializes the device->iommu mapping for the driver */ static int __init init_iommu_devices(struct amd_iommu *iommu) { - u16 i; + u32 i; for (i = iommu->first_device; i <= iommu->last_device; ++i) set_iommu_for_device(iommu, i); @@ -1177,7 +1177,7 @@ static int __init init_memory_definitions(struct acpi_table_header *table) */ static void init_device_table(void) { - u16 devid; + u32 devid; for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) { set_dev_entry_bit(devid, DEV_ENTRY_VALID); From 957df4535d06a8e009101239937ca5e50a6218c6 Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Mon, 6 Jun 2011 11:33:12 +0400 Subject: [PATCH 107/595] possible memory corruption in cifs_parse_mount_options() error path after mountdata check frees uninitialized mountdata_copy Signed-off-by: Vasily Averin Signed-off-by: Steve French --- fs/cifs/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 84c730701c09..fb31c2c1bb17 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -784,7 +784,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, struct smb_vol *vol) { char *value, *data, *end; - char *mountdata_copy, *options; + char *mountdata_copy = NULL, *options; unsigned int temp_len, i, j; char separator[2]; short int override_uid = -1; From 27c2127a15d340706c0aa84e311188a14468d841 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 30 May 2011 15:56:24 +0200 Subject: [PATCH 108/595] x86/amd-iommu: Use only per-device dma_ops Unfortunatly there are systems where the AMD IOMMU does not cover all devices. This breaks with the current driver as it initializes the global dma_ops variable. This patch limits the AMD IOMMU to the devices listed in the IVRS table fixing DMA for devices not covered by the IOMMU. Cc: stable@kernel.org Signed-off-by: Joerg Roedel --- arch/x86/kernel/amd_iommu.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index cd8cbeb5fa34..b2c309b07427 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -2383,6 +2384,23 @@ static struct dma_map_ops amd_iommu_dma_ops = { .dma_supported = amd_iommu_dma_supported, }; +static unsigned device_dma_ops_init(void) +{ + struct pci_dev *pdev = NULL; + unsigned unhandled = 0; + + for_each_pci_dev(pdev) { + if (!check_device(&pdev->dev)) { + unhandled += 1; + continue; + } + + pdev->dev.archdata.dma_ops = &amd_iommu_dma_ops; + } + + return unhandled; +} + /* * The function which clues the AMD IOMMU driver into dma_ops. */ @@ -2395,7 +2413,7 @@ void __init amd_iommu_init_api(void) int __init amd_iommu_init_dma_ops(void) { struct amd_iommu *iommu; - int ret; + int ret, unhandled; /* * first allocate a default protection domain for every IOMMU we @@ -2421,7 +2439,11 @@ int __init amd_iommu_init_dma_ops(void) swiotlb = 0; /* Make the driver finally visible to the drivers */ - dma_ops = &amd_iommu_dma_ops; + unhandled = device_dma_ops_init(); + if (unhandled && max_pfn > MAX_DMA32_PFN) { + /* There are unhandled devices - initialize swiotlb for them */ + swiotlb = 1; + } amd_iommu_stats_init(); From 243e2dd38e1b322b29a1714034cc60b84d3d5e07 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Mon, 6 Jun 2011 16:58:16 +0000 Subject: [PATCH 109/595] CIFS ACL support needs CONFIG_KEYS, so depend on it Build fails if CONFIG_KEYS is not selected. Signed-off-by: Darren Salt Reviewed-by: Shirish Pargaonkar Signed-off-by: Steve French --- fs/cifs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 66c68ab9e7df..53ed1ad2c112 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -149,7 +149,7 @@ config CIFS_FSCACHE config CIFS_ACL bool "Provide CIFS ACL support (EXPERIMENTAL)" - depends on EXPERIMENTAL && CIFS_XATTR + depends on EXPERIMENTAL && CIFS_XATTR && KEYS help Allows to fetch CIFS/NTFS ACL from the server. The DACL blob is handed over to the application/caller. From fd137e2bba53b7207cbae6a1312e89ef3ae55624 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 6 Jun 2011 11:26:15 +0100 Subject: [PATCH 110/595] ASoC: Check for NULL register bank in snd_soc_get_cache_val() Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-cache.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 06b7b81a1601..c005ceb70c9d 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -466,6 +466,9 @@ static bool snd_soc_set_cache_val(void *base, unsigned int idx, static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx, unsigned int word_size) { + if (!base) + return -1; + switch (word_size) { case 1: { const u8 *cache = base; From b084f598df36b62dfae83c10ed17f0b66b50f442 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 31 May 2011 12:24:58 -0400 Subject: [PATCH 111/595] nfsd: fix dependency of nfsd on auth_rpcgss Commit b0b0c0a26e84 "nfsd: add proc file listing kernel's gss_krb5 enctypes" added an nunnecessary dependency of nfsd on the auth_rpcgss module. It's a little ad hoc, but since the only piece of information nfsd needs from rpcsec_gss_krb5 is a single static string, one solution is just to share it with an include file. Cc: stable@kernel.org Reported-by: Michael Guntsche Cc: Kevin Coffman Signed-off-by: J. Bruce Fields --- fs/nfsd/nfsctl.c | 19 ++++++------------- include/linux/sunrpc/gss_krb5_enctypes.h | 4 ++++ net/sunrpc/auth_gss/gss_krb5_mech.c | 3 ++- 3 files changed, 12 insertions(+), 14 deletions(-) create mode 100644 include/linux/sunrpc/gss_krb5_enctypes.h diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 1f5eae40f34e..2b1449dd2f49 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "idmap.h" #include "nfsd.h" @@ -189,18 +190,10 @@ static struct file_operations export_features_operations = { .release = single_release, }; -#ifdef CONFIG_SUNRPC_GSS +#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) static int supported_enctypes_show(struct seq_file *m, void *v) { - struct gss_api_mech *k5mech; - - k5mech = gss_mech_get_by_name("krb5"); - if (k5mech == NULL) - goto out; - if (k5mech->gm_upcall_enctypes != NULL) - seq_printf(m, k5mech->gm_upcall_enctypes); - gss_mech_put(k5mech); -out: + seq_printf(m, KRB5_SUPPORTED_ENCTYPES); return 0; } @@ -215,7 +208,7 @@ static struct file_operations supported_enctypes_ops = { .llseek = seq_lseek, .release = single_release, }; -#endif /* CONFIG_SUNRPC_GSS */ +#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */ extern int nfsd_pool_stats_open(struct inode *inode, struct file *file); extern int nfsd_pool_stats_release(struct inode *inode, struct file *file); @@ -1427,9 +1420,9 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, -#ifdef CONFIG_SUNRPC_GSS +#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO}, -#endif /* CONFIG_SUNRPC_GSS */ +#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */ #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, diff --git a/include/linux/sunrpc/gss_krb5_enctypes.h b/include/linux/sunrpc/gss_krb5_enctypes.h new file mode 100644 index 000000000000..ec6234eee89c --- /dev/null +++ b/include/linux/sunrpc/gss_krb5_enctypes.h @@ -0,0 +1,4 @@ +/* + * Dumb way to share this static piece of information with nfsd + */ +#define KRB5_SUPPORTED_ENCTYPES "18,17,16,23,3,1,2" diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 0a9a2ec2e469..c3b75333b821 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -43,6 +43,7 @@ #include #include #include +#include #ifdef RPC_DEBUG # define RPCDBG_FACILITY RPCDBG_AUTH @@ -750,7 +751,7 @@ static struct gss_api_mech gss_kerberos_mech = { .gm_ops = &gss_kerberos_ops, .gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs), .gm_pfs = gss_kerberos_pfs, - .gm_upcall_enctypes = "18,17,16,23,3,1,2", + .gm_upcall_enctypes = KRB5_SUPPORTED_ENCTYPES, }; static int __init init_kerberos_module(void) From ab6a44ce1da48d35fe7ec95fa068aa617bd7e8dd Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 6 Jun 2011 14:35:27 -0400 Subject: [PATCH 112/595] Revert "mac80211: Skip tailroom reservation for full HW-crypto devices" This reverts commit aac6af5534fade2b18682a0b9efad1a6c04c34c6. Conflicts: net/mac80211/key.c That commit has a race that causes a warning, as documented in the thread here: http://marc.info/?l=linux-wireless&m=130717684914101&w=2 Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 3 --- net/mac80211/key.c | 21 ++------------------- net/mac80211/tx.c | 7 ++++++- 3 files changed, 8 insertions(+), 23 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 2025af52b195..090b0ec1e056 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -775,9 +775,6 @@ struct ieee80211_local { int tx_headroom; /* required headroom for hardware/radiotap */ - /* count for keys needing tailroom space allocation */ - int crypto_tx_tailroom_needed_cnt; - /* Tasklet and skb queue to process calls from IRQ mode. All frames * added to skb_queue will be processed, but frames in * skb_queue_unreliable may be dropped if the total length of these diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 31afd712930d..f825e2f0a57e 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -101,11 +101,6 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) if (!ret) { key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; - - if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || - (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))) - key->local->crypto_tx_tailroom_needed_cnt--; - return 0; } @@ -161,10 +156,6 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; - - if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || - (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))) - key->local->crypto_tx_tailroom_needed_cnt++; } void ieee80211_key_removed(struct ieee80211_key_conf *key_conf) @@ -403,10 +394,8 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) ieee80211_aes_key_free(key->u.ccmp.tfm); if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); - if (key->local) { + if (key->local) ieee80211_debugfs_key_remove(key); - key->local->crypto_tx_tailroom_needed_cnt--; - } kfree(key); } @@ -468,8 +457,6 @@ int ieee80211_key_link(struct ieee80211_key *key, ieee80211_debugfs_key_add(key); - key->local->crypto_tx_tailroom_needed_cnt++; - ret = ieee80211_key_enable_hw_accel(key); mutex_unlock(&sdata->local->key_mtx); @@ -511,12 +498,8 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) mutex_lock(&sdata->local->key_mtx); - sdata->local->crypto_tx_tailroom_needed_cnt = 0; - - list_for_each_entry(key, &sdata->key_list, list) { - sdata->local->crypto_tx_tailroom_needed_cnt++; + list_for_each_entry(key, &sdata->key_list, list) ieee80211_key_enable_hw_accel(key); - } mutex_unlock(&sdata->local->key_mtx); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 64e0f7587e6d..3104c844b544 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1480,7 +1480,12 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, { int tail_need = 0; - if (may_encrypt && local->crypto_tx_tailroom_needed_cnt) { + /* + * This could be optimised, devices that do full hardware + * crypto (including TKIP MMIC) need no tailroom... But we + * have no drivers for such devices currently. + */ + if (may_encrypt) { tail_need = IEEE80211_ENCRYPT_TAILROOM; tail_need -= skb_tailroom(skb); tail_need = max_t(int, tail_need, 0); From 42b70a5f6d18165a075d189d1bee82fad7cdbf29 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 26 May 2011 17:14:22 +0200 Subject: [PATCH 113/595] iwlagn: use cts-to-self protection on 5000 adapters series This patch fixes 802.11n stability and performance regression we have since 2.6.35. It boost performance on my 5GHz N-only network from about 5MB/s to 8MB/s. Similar percentage boost can be observed on 2.4 GHz. These are test results of 5x downloading of approximately 700MB iso image: vanilla: 5.27 5.22 4.94 4.47 5.31 ; avr 5.0420 std 0.35110 patched: 8.07 7.95 8.06 7.99 7.96 ; avr 8.0060 std 0.055946 This was achieved with NetworkManager configured to do not perform periodical scans, by configuring constant BSSID. With periodical scans, after some time, performance downgrade to unpatched driver level, like in example below: patched: 7.40 7.61 4.28 4.37 4.80 avr 5.6920 std 1.6683 However patch still make better here, since similar test on unpatched driver make link disconnects with below messages after some time: wlan1: authenticate with 00:23:69:35:d1:3f (try 1) wlan1: authenticate with 00:23:69:35:d1:3f (try 2) wlan1: authenticate with 00:23:69:35:d1:3f (try 3) wlan1: authentication with 00:23:69:35:d1:3f timed out On 2.6.35 kernel patch helps against connection hangs with messages: iwlagn 0000:20:00.0: queue 10 stuck 3 time. Fw reload. iwlagn 0000:20:00.0: On demand firmware reload iwlagn 0000:20:00.0: Stopping AGG while state not ON or starting Cc: stable@kernel.org # 2.6.35+ Signed-off-by: Stanislaw Gruszka Acked-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 1 - drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 12 ++---------- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 8 ++++++++ 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 5b721c56aee9..f99f9c193352 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -423,7 +423,6 @@ static struct iwl_base_params iwl5000_base_params = { }; static struct iwl_ht_params iwl5000_ht_params = { .ht_greenfield_support = true, - .use_rts_for_aggregation = true, /* use rts/cts protection */ }; #define IWL_DEVICE_5000 \ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index b12c72d63ccb..23fa93deae96 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -163,17 +163,9 @@ static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, __le16 fc, __le32 *tx_flags) { if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS || - info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT || + info->flags & IEEE80211_TX_CTL_AMPDU) *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; - return; - } - - if (priv->cfg->ht_params && - priv->cfg->ht_params->use_rts_for_aggregation && - info->flags & IEEE80211_TX_CTL_AMPDU) { - *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; - return; - } } /* Calc max signal level (dBm) among 3 possible receivers */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 2532c7db3aff..018874964602 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -325,6 +325,14 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) return 0; } + /* + * force CTS-to-self frames protection if RTS-CTS is not preferred + * one aggregation protection method + */ + if (!(priv->cfg->ht_params && + priv->cfg->ht_params->use_rts_for_aggregation)) + ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; + if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK)) ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; From 3bb42a64960253353278876ca8da6b0a7d3bea87 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 4 Jun 2011 16:48:54 +0200 Subject: [PATCH 114/595] rt2x00: fix rmmod crash Avoid queue and run autowakeup_work when device is not present anymore. That prevent rmmod and device remove crash introduced by: commit 1c0bcf89d85cc97a0d9ce4cd909351a81fa4fdde Author: Ivo van Doorn Date: Sat Apr 30 17:18:18 2011 +0200 rt2x00: Add autowake support for USB hardware Signed-off-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00config.c | 3 ++- drivers/net/wireless/rt2x00/rt2x00dev.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 555180d8f4aa..b704e5b183d0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -250,7 +250,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) rt2x00link_reset_tuner(rt2x00dev, false); - if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) && + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && + test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) && (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) && (conf->flags & IEEE80211_CONF_PS)) { beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index c018d67aab8e..939821b4af2f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -146,6 +146,9 @@ static void rt2x00lib_autowakeup(struct work_struct *work) struct rt2x00_dev *rt2x00dev = container_of(work, struct rt2x00_dev, autowakeup_work.work); + if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + return; + if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) ERROR(rt2x00dev, "Device failed to wakeup.\n"); clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); @@ -1160,6 +1163,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) * Stop all work. */ cancel_work_sync(&rt2x00dev->intf_work); + cancel_delayed_work_sync(&rt2x00dev->autowakeup_work); if (rt2x00_is_usb(rt2x00dev)) { del_timer_sync(&rt2x00dev->txstatus_timer); cancel_work_sync(&rt2x00dev->rxdone_work); From 51892dbbd511911c0f965a36b431fc3e8f1e4f8a Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 6 Jun 2011 15:11:30 +0200 Subject: [PATCH 115/595] iwl4965: set tx power after rxon_assoc Setting tx power can be deferred during scan or changing channel. If after that correct tx power settings will not be sent to device, we can observe transmission problems and timeouts. Force to send tx power settings also after partial rxon change, to assure device always be configured with up-to-date settings. Resolves: https://bugzilla.kernel.org/show_bug.cgi?id=36492 Cc: stable@kernel.org # 2.6.39+ Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-4965.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c index f9db25bb35c3..e1b89220c186 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965.c @@ -1237,7 +1237,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); iwl_legacy_print_rx_config_cmd(priv, ctx); - return 0; + goto set_tx_power; } /* If we are currently associated and the new config requires @@ -1317,6 +1317,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c iwl4965_init_sensitivity(priv); +set_tx_power: /* If we issue a new RXON command which required a tune then we must * send a new TXPOWER command or we won't be able to Tx any frames */ ret = iwl_legacy_set_tx_power(priv, priv->tx_power_next, true); From 5f98ecdbcef1920323d8777c0ba55dbd4335d3cf Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 5 Jun 2011 11:47:29 +0900 Subject: [PATCH 116/595] swiotlb: Export swioltb_nr_tbl and utilize it as appropiate. By default the io_tlb_nslabs is set to zero, and gets set to whatever value is passed in via swiotlb_init_with_tbl function. The default value passed in is 64MB. However, if the user provides the 'swiotlb=' the default value is ignored and the value provided by the user is used... Except when the SWIOTLB is used under Xen - there the default value of 64MB is used and the Xen-SWIOTLB has no mechanism to get the 'io_tlb_nslabs' filled out by setup_io_tlb_npages functions. This patch provides a function for the Xen-SWIOTLB to call to see if the io_tlb_nslabs is set and if so use that value. Signed-off-by: FUJITA Tomonori Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/swiotlb-xen.c | 12 +++++++++--- include/linux/swiotlb.h | 1 + lib/swiotlb.c | 5 +++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 54469c3eeacd..5ac3f4843f5c 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -147,9 +147,15 @@ void __init xen_swiotlb_init(int verbose) { unsigned long bytes; int rc; - - xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT); - xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE); + unsigned long nr_tbl; + + nr_tbl = swioltb_nr_tbl(); + if (nr_tbl) + xen_io_tlb_nslabs = nr_tbl; + else { + xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT); + xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE); + } bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT; diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index 8c0e349f4a6c..445702c60d04 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -24,6 +24,7 @@ extern int swiotlb_force; extern void swiotlb_init(int verbose); extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); +extern unsigned long swioltb_nr_tbl(void); /* * Enumeration for sync targets diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 93ca08b8a451..99093b396145 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c @@ -110,6 +110,11 @@ setup_io_tlb_npages(char *str) __setup("swiotlb=", setup_io_tlb_npages); /* make io_tlb_overflow tunable too? */ +unsigned long swioltb_nr_tbl(void) +{ + return io_tlb_nslabs; +} + /* Note that this doesn't work with highmem page */ static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev, volatile void *address) From 8ca695f273709a9d147826716a8dee3e0eb2407f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 6 Jun 2011 13:38:35 +0200 Subject: [PATCH 117/595] ASoC: AD1836: Fix setting the PCM format Signed-off-by: Lars-Peter Clausen Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/codecs/ad1836.c | 14 +++++++------- sound/soc/codecs/ad1836.h | 6 ++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index ab63d52e36e1..754c496412bd 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -145,22 +145,22 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, /* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - word_len = 3; + word_len = AD1836_WORD_LEN_16; break; case SNDRV_PCM_FORMAT_S20_3LE: - word_len = 1; + word_len = AD1836_WORD_LEN_20; break; case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S32_LE: - word_len = 0; + word_len = AD1836_WORD_LEN_24; break; } - snd_soc_update_bits(codec, AD1836_DAC_CTRL1, - AD1836_DAC_WORD_LEN_MASK, word_len); + snd_soc_update_bits(codec, AD1836_DAC_CTRL1, AD1836_DAC_WORD_LEN_MASK, + word_len << AD1836_DAC_WORD_LEN_OFFSET); - snd_soc_update_bits(codec, AD1836_ADC_CTRL2, - AD1836_ADC_WORD_LEN_MASK, word_len); + snd_soc_update_bits(codec, AD1836_ADC_CTRL2, AD1836_ADC_WORD_LEN_MASK, + word_len << AD1836_ADC_WORD_OFFSET); return 0; } diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index 845596717fdf..9d6a3f8f8aaf 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h @@ -25,6 +25,7 @@ #define AD1836_DAC_SERFMT_PCK256 (0x4 << 5) #define AD1836_DAC_SERFMT_PCK128 (0x5 << 5) #define AD1836_DAC_WORD_LEN_MASK 0x18 +#define AD1836_DAC_WORD_LEN_OFFSET 3 #define AD1836_DAC_CTRL2 1 #define AD1836_DACL1_MUTE 0 @@ -51,6 +52,7 @@ #define AD1836_ADCL2_MUTE 2 #define AD1836_ADCR2_MUTE 3 #define AD1836_ADC_WORD_LEN_MASK 0x30 +#define AD1836_ADC_WORD_OFFSET 5 #define AD1836_ADC_SERFMT_MASK (7 << 6) #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) @@ -60,4 +62,8 @@ #define AD1836_NUM_REGS 16 +#define AD1836_WORD_LEN_24 0x0 +#define AD1836_WORD_LEN_20 0x1 +#define AD1836_WORD_LEN_16 0x2 + #endif From 5a079c305ad4dda9708b7a29db4a8bd38e21c3a6 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Mon, 6 Jun 2011 06:00:07 +0000 Subject: [PATCH 118/595] net/ipv6: check for mistakenly passed in non-AF_INET6 sockaddrs Same check as for IPv4, also do for IPv6. (If you passed in a IPv4 sockaddr_in here, the sizeof check in the line before would have triggered already though.) Signed-off-by: Marcus Meissner Cc: Reinhard Max Signed-off-by: David S. Miller --- net/ipv6/af_inet6.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index b7919f901fbf..d450a2f9fc06 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -272,6 +272,10 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (addr_len < SIN6_LEN_RFC2133) return -EINVAL; + + if (addr->sin6_family != AF_INET6) + return -EINVAL; + addr_type = ipv6_addr_type(&addr->sin6_addr); if ((addr_type & IPV6_ADDR_MULTICAST) && sock->type == SOCK_STREAM) return -EINVAL; From be1f4084b4824301e640e81d63b6275cd99ee6a1 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 6 Jun 2011 11:22:17 -0700 Subject: [PATCH 119/595] nfsd: v4 support requires CRYPTO nfsd V4 support uses crypto interfaces, so select CRYPTO to fix build errors in 2.6.39: ERROR: "crypto_destroy_tfm" [fs/nfsd/nfsd.ko] undefined! ERROR: "crypto_alloc_base" [fs/nfsd/nfsd.ko] undefined! Reported-by: Wakko Warner Signed-off-by: Randy Dunlap Cc: stable@kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 18b3e8975fe0..fbb2a5ef5817 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig @@ -82,6 +82,7 @@ config NFSD_V4 select NFSD_V3 select FS_POSIX_ACL select SUNRPC_GSS + select CRYPTO help This option enables support in your system's NFS server for version 4 of the NFS protocol (RFC 3530). From 7d751f6f8c679f51b73d01a1b5269347a929004c Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Fri, 3 Jun 2011 12:21:23 -0400 Subject: [PATCH 120/595] nfsd: link returns nfserr_delay when breaking lease fix for commit 4795bb37effb7b8fe77e2d2034545d062d3788a8, nfsd: break lease on unlink, link, and rename if the LINK operation breaks a delegation, it returns NFS4ERR_NOENT (which is not a valid error in rfc 5661) instead of NFS4ERR_DELAY. the return value of nfsd_break_lease() in nfsd_link() must be converted from host_err to err Signed-off-by: Casey Bodley Cc: stable@kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/vfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index d5718273bb32..f3fb61b69a1e 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1660,8 +1660,10 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, if (!dold->d_inode) goto out_drop_write; host_err = nfsd_break_lease(dold->d_inode); - if (host_err) + if (host_err) { + err = nfserrno(host_err); goto out_drop_write; + } host_err = vfs_link(dold, dirp, dnew); if (!host_err) { err = nfserrno(commit_metadata(ffhp)); From cdacb598fe7ab85de80908c818dd7d66a2971117 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 6 Jun 2011 16:08:39 -0500 Subject: [PATCH 121/595] option: add Zoom 4597 modem USB IDs Uses Longcheer-based firmware and AT command set. Signed-off-by: Dan Williams Cc: stable@kernel.org 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 318dd00040a3..e39e7e8ba53a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -379,6 +379,9 @@ static void option_instat_callback(struct urb *urb); * It seems to contain a Qualcomm QSC6240/6290 chipset */ #define FOUR_G_SYSTEMS_PRODUCT_W14 0x9603 +/* Zoom */ +#define ZOOM_PRODUCT_4597 0x9607 + /* Haier products */ #define HAIER_VENDOR_ID 0x201e #define HAIER_PRODUCT_CE100 0x2009 @@ -942,6 +945,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), .driver_info = (kernel_ulong_t)&four_g_w14_blacklist }, + { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) }, { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, /* Pirelli */ { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)}, From 15badbcc8eede58b0d7e53a3acde1c90a7b6e40e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 6 Jun 2011 16:22:44 -0500 Subject: [PATCH 122/595] option: add Alcatel X200 to sendsetup blacklist This modem really wants sendsetup blacklisted for interfaces 0 and 1, otherwise the kernel hardlocks for about 10 seconds while waiting for the modem's firmware to respond, which it of course doesn't do. A slight complication here is that TCT (who owns the Alcatel brand) used the same USB IDs for the X200 as the X060s despite the devices having completely different firmware and AT command sets, so we end up adding the X060s to the blacklist at the same time. PSA to OEMs: don't use the same USB IDs for different devices. Really. It makes your kittens cry. Signed-off-by: Dan Williams Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e39e7e8ba53a..c7cca3f24c9d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -344,7 +344,7 @@ static void option_instat_callback(struct urb *urb); /* ALCATEL PRODUCTS */ #define ALCATEL_VENDOR_ID 0x1bbb -#define ALCATEL_PRODUCT_X060S 0x0000 +#define ALCATEL_PRODUCT_X060S_X200 0x0000 #define PIRELLI_VENDOR_ID 0x1266 #define PIRELLI_PRODUCT_C100_1 0x1002 @@ -435,6 +435,13 @@ static const struct option_blacklist_info four_g_w14_blacklist = { .reason = OPTION_BLACKLIST_SENDSETUP }; +static const u8 alcatel_x200_no_sendsetup[] = { 0, 1 }; +static const struct option_blacklist_info alcatel_x200_blacklist = { + .infolen = ARRAY_SIZE(alcatel_x200_no_sendsetup), + .ifaceinfo = alcatel_x200_no_sendsetup, + .reason = OPTION_BLACKLIST_SENDSETUP +}; + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -939,7 +946,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) }, { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, - { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), + .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist + }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), From 5c3e4076ee8253c1e3688d10653ddee47a03b0db Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 6 Jun 2011 16:55:41 -0500 Subject: [PATCH 123/595] option: add Prolink PH300 modem IDs Simple ID addition. Signed-off-by: Dan Williams Cc: stable@kernel.org 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 c7cca3f24c9d..2c10e298925a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -340,6 +340,7 @@ static void option_instat_callback(struct urb *urb); #define TOSHIBA_PRODUCT_G450 0x0d45 #define ALINK_VENDOR_ID 0x1e0e +#define ALINK_PRODUCT_PH300 0x9100 #define ALINK_PRODUCT_3GU 0x9200 /* ALCATEL PRODUCTS */ @@ -945,6 +946,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) }, { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) }, + { USB_DEVICE(ALINK_VENDOR_ID, ALINK_PRODUCT_PH300) }, { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist From 7e8e62e4a5d26e4cb45f25dddd093837d75616c2 Mon Sep 17 00:00:00 2001 From: Torsten Hilbrich Date: Mon, 6 Jun 2011 15:39:55 +0200 Subject: [PATCH 124/595] USB: option Add blacklist for ZTE K3765-Z (19d2:2002) The funtion option_send_status times out when sending USB messages to the interfaces 0, 1, and 2 of this UMTS stick. This results in a 5s timeout in the function causing other tty operations to feel very sluggish. This patch adds a blacklist entry for these 3 interfaces on the ZTE K3765-Z device. I was also able to reproduce the problem with v2.6.38 and v2.6.39. This is very similar to a problem fixed in commit 7a89e4cb9cdaba92f5fbc509945cf4e3c48db4e2 Author: Herton Ronaldo Krzesinski Date: Wed Mar 9 09:19:48 2011 +0000 USB: serial: option: Apply OPTION_BLACKLIST_SENDSETUP also for ZTE MF626 Signed-off-by: Torsten Hilbrich Cc: stable 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 2c10e298925a..f7583f847438 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -443,6 +443,13 @@ static const struct option_blacklist_info alcatel_x200_blacklist = { .reason = OPTION_BLACKLIST_SENDSETUP }; +static const u8 zte_k3765_z_no_sendsetup[] = { 0, 1, 2 }; +static const struct option_blacklist_info zte_k3765_z_blacklist = { + .infolen = ARRAY_SIZE(zte_k3765_z_no_sendsetup), + .ifaceinfo = zte_k3765_z_no_sendsetup, + .reason = OPTION_BLACKLIST_SENDSETUP +}; + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -927,7 +934,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 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) }, { 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) }, From 3898115896c7f18cb7009de691c43cb3d92bb82a Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Fri, 27 May 2011 08:37:40 +0400 Subject: [PATCH 125/595] usb-gadget: unlock data->lock mutex on error path in ep_write() ep_write() acquires data->lock mutex in get_ready_ep() and releases it on all paths except for one: when usb_endpoint_xfer_isoc() failed. The patch adds mutex_unlock(&data->lock) at that path. It is similar to commit 00cc7a5 ("usb-gadget: unlock data->lock mutex on error path in ep_read()"), it was not fixed at that time by accident. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/inode.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index a01383f71f38..a56876aaf76c 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -431,8 +431,10 @@ ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) /* halt any endpoint by doing a "wrong direction" i/o call */ if (!usb_endpoint_dir_in(&data->desc)) { - if (usb_endpoint_xfer_isoc(&data->desc)) + if (usb_endpoint_xfer_isoc(&data->desc)) { + mutex_unlock(&data->lock); return -EINVAL; + } DBG (data->dev, "%s halt\n", data->name); spin_lock_irq (&data->dev->lock); if (likely (data->ep != NULL)) From 4061fde2fa80f40cb27114f60500d38d0afcf350 Mon Sep 17 00:00:00 2001 From: Toby Gray Date: Mon, 6 Jun 2011 14:52:48 +0100 Subject: [PATCH 126/595] USB: cdc-acm: Adding second ACM channel support for Nokia E7 and C7 This adds the Nokia E7 and C7 to the list of devices in cdc-acm, allowing the secondary ACM channel on the device to be exposed. Without this patch the ACM driver won't claim this secondary channel as it's marked as having a vendor-specific protocol. Signed-off-by: Toby Gray Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 395a347f2ebb..dac7676ce21b 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1530,6 +1530,8 @@ static const struct usb_device_id acm_ids[] = { { NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */ { NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */ { NOKIA_PCSUITE_ACM_INFO(0x0302), }, /* Nokia N8 */ + { NOKIA_PCSUITE_ACM_INFO(0x0335), }, /* Nokia E7 */ + { NOKIA_PCSUITE_ACM_INFO(0x03cd), }, /* Nokia C7 */ { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */ /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ From 9303961f5b8c8da0b65b897fb6521d2a123ec8a8 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 25 May 2011 08:13:24 -0400 Subject: [PATCH 127/595] musb: fix prefetch build failure After the prefetch/list.h restructure, drivers need to explicitly include linux/prefetch.h in order to use the prefetch() function. Otherwise, the current driver fails to build: drivers/usb/musb/musb_core.c: In function 'musb_write_fifo': drivers/usb/musb/musb_core.c:219: error: implicit declaration of function 'prefetch' make[3]: *** [drivers/usb/musb/musb_core.o] Error 1 Signed-off-by: Mike Frysinger Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index ab8e1001e5e2..c71b0372786e 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -96,6 +96,7 @@ #include #include #include +#include #include #include From 3824c1ddaf744be44b170a335332b9d6afe79254 Mon Sep 17 00:00:00 2001 From: Libor Pechacek Date: Fri, 20 May 2011 14:53:25 +0200 Subject: [PATCH 128/595] USB: core: Tolerate protocol stall during hub and port status read Protocol stall should not be fatal while reading port or hub status as it is transient state. Currently hub EP0 STALL during port status read results in failed device enumeration. This has been observed with ST-Ericsson (formerly Philips) USB 2.0 Hub (04cc:1521) after connecting keyboard. Signed-off-by: Libor Pechacek Acked-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 79a58c3a2e2a..90ae1753dda1 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -339,7 +339,8 @@ static int get_hub_status(struct usb_device *hdev, { int i, status = -ETIMEDOUT; - for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) { + for (i = 0; i < USB_STS_RETRIES && + (status == -ETIMEDOUT || status == -EPIPE); i++) { status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, data, sizeof(*data), USB_STS_TIMEOUT); @@ -355,7 +356,8 @@ static int get_port_status(struct usb_device *hdev, int port1, { int i, status = -ETIMEDOUT; - for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) { + for (i = 0; i < USB_STS_RETRIES && + (status == -ETIMEDOUT || status == -EPIPE); i++) { status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port1, data, sizeof(*data), USB_STS_TIMEOUT); From d52b31deffe1956ac62d0b81b915c9b52cffb814 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 27 May 2011 13:56:12 -0700 Subject: [PATCH 129/595] GPIO: OMAP: fix section mismatch warnings WARNING: arch/arm/plat-omap/built-in.o(.devinit.text+0x46c): Section mismatch in reference from the function omap_gpio_probe() to the function .init.text:omap_gpio_chip_init() The function __devinit omap_gpio_probe() references a function __init omap_gpio_chip_init(). If omap_gpio_chip_init is only used by omap_gpio_probe then annotate omap_gpio_chip_init with a matching annotation. Signed-off-by: Russell King Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 6c51191da567..76709b03572e 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1524,7 +1524,7 @@ static void omap_gpio_mod_init(struct gpio_bank *bank, int id) } } -static void __init omap_gpio_chip_init(struct gpio_bank *bank) +static void __devinit omap_gpio_chip_init(struct gpio_bank *bank) { int j; static int gpio; From 0622b25bf071fd83c6eef6b61fb5f3f12a418528 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 6 Jun 2011 13:38:17 -0700 Subject: [PATCH 130/595] GPIO: OMAP: fix setting IRQWAKEN bits for OMAP4 Setting the IRQWAKEN bit was overwriting previous IRQWAKEN bits, causing only the last bit set to take effect, resulting in lost wakeups when the GPIO controller is in idle. Replace direct writes to IRQWAKEN with MOD_REG_BIT calls to perform a read-modify-write on the register. Signed-off-by: Colin Cross Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 76709b03572e..5ad827a1a3e8 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -432,7 +432,6 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, { void __iomem *base = bank->base; u32 gpio_bit = 1 << gpio; - u32 val; if (cpu_is_omap44xx()) { MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT0, gpio_bit, @@ -455,15 +454,8 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, } if (likely(!(bank->non_wakeup_gpios & gpio_bit))) { if (cpu_is_omap44xx()) { - if (trigger != 0) - __raw_writel(1 << gpio, bank->base+ - OMAP4_GPIO_IRQWAKEN0); - else { - val = __raw_readl(bank->base + - OMAP4_GPIO_IRQWAKEN0); - __raw_writel(val & (~(1 << gpio)), bank->base + - OMAP4_GPIO_IRQWAKEN0); - } + MOD_REG_BIT(OMAP4_GPIO_IRQWAKEN0, gpio_bit, + trigger != 0); } else { /* * GPIO wakeup request can only be generated on edge From 85ec7b970553369e0c956fab1d7a6022f2a99369 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 6 Jun 2011 13:38:18 -0700 Subject: [PATCH 131/595] GPIO: OMAP: add locking around calls to _set_gpio_triggering _set_gpio_triggering uses read-modify-write on bank registers, lock bank->lock around all calls to it to prevent register corruption if two cpus access gpios in the same bank at the same time. Signed-off-by: Colin Cross Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 5ad827a1a3e8..01f74a8459d9 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1126,8 +1126,11 @@ static void gpio_irq_shutdown(struct irq_data *d) { unsigned int gpio = d->irq - IH_GPIO_BASE; struct gpio_bank *bank = irq_data_get_irq_chip_data(d); + unsigned long flags; + spin_lock_irqsave(&bank->lock, flags); _reset_gpio(bank, gpio); + spin_unlock_irqrestore(&bank->lock, flags); } static void gpio_ack_irq(struct irq_data *d) @@ -1142,9 +1145,12 @@ static void gpio_mask_irq(struct irq_data *d) { unsigned int gpio = d->irq - IH_GPIO_BASE; struct gpio_bank *bank = irq_data_get_irq_chip_data(d); + unsigned long flags; + spin_lock_irqsave(&bank->lock, flags); _set_gpio_irqenable(bank, gpio, 0); _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE); + spin_unlock_irqrestore(&bank->lock, flags); } static void gpio_unmask_irq(struct irq_data *d) @@ -1153,7 +1159,9 @@ static void gpio_unmask_irq(struct irq_data *d) struct gpio_bank *bank = irq_data_get_irq_chip_data(d); unsigned int irq_mask = 1 << get_gpio_index(gpio); u32 trigger = irqd_get_trigger_type(d); + unsigned long flags; + spin_lock_irqsave(&bank->lock, flags); if (trigger) _set_gpio_triggering(bank, get_gpio_index(gpio), trigger); @@ -1165,6 +1173,7 @@ static void gpio_unmask_irq(struct irq_data *d) } _set_gpio_irqenable(bank, gpio, 1); + spin_unlock_irqrestore(&bank->lock, flags); } static struct irq_chip gpio_irq_chip = { From c8fb13d04ad0d08772f637bee873e620fcc064c2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 27 May 2011 13:56:12 -0700 Subject: [PATCH 132/595] OMAP: PM debug: fix section mismatch warnings WARNING: arch/arm/mach-omap2/built-in.o(.text+0x423c): Section mismatch in reference from the function pm_dbg_regset_init() to the function .init.text:pm_dbg_init() The function pm_dbg_regset_init() references the function __init pm_dbg_init(). This is often because pm_dbg_regset_init lacks a __init annotation or the annotation of pm_dbg_init is wrong. Signed-off-by: Russell King Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/pm-debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index a5a83b358ddd..e01da45c0537 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -189,7 +189,7 @@ static struct dentry *pm_dbg_dir; static int pm_dbg_init_done; -static int __init pm_dbg_init(void); +static int pm_dbg_init(void); enum { DEBUG_FILE_COUNTERS = 0, @@ -595,7 +595,7 @@ static int option_set(void *data, u64 val) DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n"); -static int __init pm_dbg_init(void) +static int pm_dbg_init(void) { int i; struct dentry *d; From 345f79b3de7f6d651e4dba794af7c7303bdfd649 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 31 May 2011 16:08:09 -0700 Subject: [PATCH 133/595] OMAP: PM: omap_device: fix device power domain callbacks After commit 4d27e9dcff00a6425d779b065ec8892e4f391661 (PM: Make power domain callbacks take precedence over subsystem ones), the power domain callbacks need to call the driver callbacks instead of relying on the default subsystem (in this case, platform_bus) to handle the driver callbacks. Validated on 3430/n900, 3530/Overo. Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/omap_device.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index a37b8eb65b76..49fc0df0c21f 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -84,6 +84,7 @@ #include #include #include +#include #include #include @@ -539,20 +540,34 @@ int omap_early_device_register(struct omap_device *od) static int _od_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); + int ret; + + ret = pm_generic_runtime_suspend(dev); + + if (!ret) + omap_device_idle(pdev); + + return ret; +} - return omap_device_idle(pdev); +static int _od_runtime_idle(struct device *dev) +{ + return pm_generic_runtime_idle(dev); } static int _od_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - return omap_device_enable(pdev); + omap_device_enable(pdev); + + return pm_generic_runtime_resume(dev); } static struct dev_power_domain omap_device_power_domain = { .ops = { .runtime_suspend = _od_runtime_suspend, + .runtime_idle = _od_runtime_idle, .runtime_resume = _od_runtime_resume, USE_PLATFORM_PM_SLEEP_OPS } From 1d4a4bde6b1cd4c8bbe1dd20dee18416a62b9c51 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 31 May 2011 09:11:11 -0700 Subject: [PATCH 134/595] usb: remove bad dput after dentry_unhash Commit 64252c75a (vfs: remove dget() from dentry_unhash()) removed the useless dget from dentry_unhash but didn't fix up this caller in the usb code. There used to be exactly one dput per dentry_unhash call; now there are none. Tested-by: Sebastian Andrzej Siewior Signed-off-by: Sage Weil Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/inode.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 1b125c224dcf..2278dad886e2 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -389,7 +389,6 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry) mutex_unlock(&inode->i_mutex); if (!error) d_delete(dentry); - dput(dentry); return error; } From 83a018045659ee2cc9b1390ddb8b2a247d269bc4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 1 Jun 2011 17:16:15 +0100 Subject: [PATCH 135/595] USB: s3c-hsotg: Tone down debugging Currently the s3c-hsotg driver is extremely chatty, producing voluminous with large register dumps even in default operation. Tone this down so we're not chatty unless DEBUG is defined. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/s3c-hsotg.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index acb9cc418df9..0dfee282878a 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2680,9 +2680,9 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, writel(0, hsotg->regs + S3C_DAINTMSK); - dev_info(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", - readl(hsotg->regs + S3C_DIEPCTL0), - readl(hsotg->regs + S3C_DOEPCTL0)); + dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", + readl(hsotg->regs + S3C_DIEPCTL0), + readl(hsotg->regs + S3C_DOEPCTL0)); /* enable in and out endpoint interrupts */ s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt); @@ -2701,7 +2701,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, udelay(10); /* see openiboot */ __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone); - dev_info(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL)); + dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL)); /* S3C_DxEPCTL_USBActEp says RO in manual, but seems to be set by writing to the EPCTL register.. */ @@ -2721,9 +2721,9 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, s3c_hsotg_enqueue_setup(hsotg); - dev_info(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", - readl(hsotg->regs + S3C_DIEPCTL0), - readl(hsotg->regs + S3C_DOEPCTL0)); + dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", + readl(hsotg->regs + S3C_DIEPCTL0), + readl(hsotg->regs + S3C_DOEPCTL0)); /* clear global NAKs */ writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK, @@ -2921,9 +2921,9 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg) /* setup fifos */ - dev_info(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", - readl(hsotg->regs + S3C_GRXFSIZ), - readl(hsotg->regs + S3C_GNPTXFSIZ)); + dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", + readl(hsotg->regs + S3C_GRXFSIZ), + readl(hsotg->regs + S3C_GNPTXFSIZ)); s3c_hsotg_init_fifo(hsotg); @@ -2945,6 +2945,7 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg) static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) { +#ifdef DEBUG struct device *dev = hsotg->dev; void __iomem *regs = hsotg->regs; u32 val; @@ -2987,6 +2988,7 @@ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n", readl(regs + S3C_DVBUSDIS), readl(regs + S3C_DVBUSPULSE)); +#endif } From b38b03b363a53067e8b8f3f43f00b6428bd5319c Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Thu, 2 Jun 2011 12:51:29 +0800 Subject: [PATCH 136/595] usb: gadget: include to fix compiling error drivers/usb/gadget/at91_udc.c: In function 'write_fifo': drivers/usb/gadget/at91_udc.c:421:2: error: implicit declaration of function 'prefetch' make[3]: *** [drivers/usb/gadget/at91_udc.o] Error 1 make[2]: *** [drivers/usb/gadget] Error 2 make[2]: *** Waiting for unfinished jobs.... Signed-off-by: Bryan Wu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/amd5536udc.c | 1 + drivers/usb/gadget/at91_udc.c | 1 + drivers/usb/gadget/net2280.c | 1 + drivers/usb/gadget/s3c-hsudc.c | 1 + drivers/usb/gadget/s3c2410_udc.c | 1 + 5 files changed, 5 insertions(+) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 6e42aab75806..95e8138cd48f 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -60,6 +60,7 @@ #include #include #include +#include #include #include diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 41dc093c0a1b..f4690ffcb489 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 24696f7fa6a9..476d88e1ae97 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -63,6 +63,7 @@ #include #include #include +#include #include #include diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index cfe3cf56d6bd..9a1b966e18db 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 6d8b04061d5d..100f2635cf0a 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include From cb42447374eb4348b75ec677bf9c77958c7d10e0 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 3 Jun 2011 19:50:45 +0200 Subject: [PATCH 137/595] usb/mv_udc_core: fix compile |drivers/usb/gadget/mv_udc_core.c:2108: error: label `error' used but not defined This seems to be broken since the initial commit. I changed this to a simple return. The other user is the probe code which lets ->probe() fail on error here. |drivers/usb/gadget/mv_udc_core.c:2107: warning: passing argument 1 of `dev_err' from incompatible pointer type |drivers/usb/gadget/mv_udc_core.c:2118: warning: initialization from incompatible pointer type |drivers/usb/gadget/mv_udc_core.c:2119: warning: initialization from incompatible pointer type |drivers/usb/gadget/mv_udc_core.c:2130: error: initializer element is not constant |drivers/usb/gadget/mv_udc_core.c:2130: error: (near initialization for `udc_driver.driver.pm') Cc: Chao Xie Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/mv_udc_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index b62b2640deb0..b1a8146b9d50 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -2083,7 +2083,7 @@ int mv_udc_probe(struct platform_device *dev) } #ifdef CONFIG_PM -static int mv_udc_suspend(struct platform_device *_dev, pm_message_t state) +static int mv_udc_suspend(struct device *_dev) { struct mv_udc *udc = the_controller; @@ -2092,7 +2092,7 @@ static int mv_udc_suspend(struct platform_device *_dev, pm_message_t state) return 0; } -static int mv_udc_resume(struct platform_device *_dev) +static int mv_udc_resume(struct device *_dev) { struct mv_udc *udc = the_controller; int retval; @@ -2100,7 +2100,7 @@ static int mv_udc_resume(struct platform_device *_dev) retval = mv_udc_phy_init(udc->phy_regs); if (retval) { dev_err(_dev, "phy initialization error %d\n", retval); - goto error; + return retval; } udc_reset(udc); ep0_reset(udc); @@ -2122,7 +2122,7 @@ static struct platform_driver udc_driver = { .owner = THIS_MODULE, .name = "pxa-u2o", #ifdef CONFIG_PM - .pm = mv_udc_pm_ops, + .pm = &mv_udc_pm_ops, #endif }, }; From a6207b17ece4ea40c378233b1ddf2a7f4288419d Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 3 Jun 2011 19:50:46 +0200 Subject: [PATCH 138/595] usb/pxa25x_udc: cleanup the LUBBOCK err path this is more backwords than it has to be. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa25x_udc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 365c02fc25fc..774545494cf2 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -2216,7 +2216,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) if (retval != 0) { pr_err("%s: can't get irq %i, err %d\n", driver_name, LUBBOCK_USB_DISC_IRQ, retval); -lubbock_fail0: goto err_irq_lub; } retval = request_irq(LUBBOCK_USB_IRQ, @@ -2226,7 +2225,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) if (retval != 0) { pr_err("%s: can't get irq %i, err %d\n", driver_name, LUBBOCK_USB_IRQ, retval); - free_irq(LUBBOCK_USB_DISC_IRQ, dev); goto lubbock_fail0; } } else @@ -2236,10 +2234,11 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) return 0; #ifdef CONFIG_ARCH_LUBBOCK +lubbock_fail0: free_irq(LUBBOCK_USB_DISC_IRQ, dev); err_irq_lub: -#endif free_irq(irq, dev); +#endif err_irq1: if (gpio_is_valid(dev->mach->gpio_pullup)) gpio_free(dev->mach->gpio_pullup); From 6bc129532176fcafb4202b73b3f431986391a362 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 3 Jun 2011 19:50:47 +0200 Subject: [PATCH 139/595] usb/s3c-hsudc: fix error path I doubt the clock is optional. In case it is it should not return with an error code because we leak everything. Cc: Jingoo Han Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/s3c-hsudc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index 9a1b966e18db..d5e3e1e58626 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -1302,7 +1302,8 @@ static int s3c_hsudc_probe(struct platform_device *pdev) hsudc->uclk = clk_get(&pdev->dev, "usb-device"); if (IS_ERR(hsudc->uclk)) { dev_err(dev, "failed to find usb-device clock source\n"); - return PTR_ERR(hsudc->uclk); + ret = PTR_ERR(hsudc->uclk); + goto err_clk; } clk_enable(hsudc->uclk); @@ -1311,7 +1312,8 @@ static int s3c_hsudc_probe(struct platform_device *pdev) disable_irq(hsudc->irq); local_irq_enable(); return 0; - +err_clk: + free_irq(hsudc->irq, hsudc); err_irq: iounmap(hsudc->regs); From 3af51ac9c0889a188aaa3defe5134ef97c80d7c5 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 3 Jun 2011 19:50:48 +0200 Subject: [PATCH 140/595] usb/renesas_usbhs: free uep on removal Can't find evidence that this is actually done. Cc: Kuninori Morimoto Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/mod_gadget.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 206cfabc9286..547486ccd059 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -1380,5 +1380,6 @@ void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); + kfree(gpriv->uep); kfree(gpriv); } From 3019de124b9f5b1526cb3668b74af14371e21795 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 6 Jun 2011 16:41:33 -0700 Subject: [PATCH 141/595] net: Rework netdev_drivername() to avoid warning. This interface uses a temporary buffer, but for no real reason. And now can generate warnings like: net/sched/sch_generic.c: In function dev_watchdog net/sched/sch_generic.c:254:10: warning: unused variable drivername Just return driver->name directly or "". Reported-by: Connor Hansen Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 +- net/core/dev.c | 16 +++++----------- net/sched/sch_generic.c | 3 +-- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ca333e79e10f..54b8b4d7b68f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2555,7 +2555,7 @@ extern void netdev_class_remove_file(struct class_attribute *class_attr); extern struct kobj_ns_type_operations net_ns_type_operations; -extern char *netdev_drivername(const struct net_device *dev, char *buffer, int len); +extern const char *netdev_drivername(const struct net_device *dev); extern void linkwatch_run_queue(void); diff --git a/net/core/dev.c b/net/core/dev.c index 939307891e71..1af6cb27f67a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6264,29 +6264,23 @@ static int __net_init netdev_init(struct net *net) /** * netdev_drivername - network driver for the device * @dev: network device - * @buffer: buffer for resulting name - * @len: size of buffer * * Determine network driver for device. */ -char *netdev_drivername(const struct net_device *dev, char *buffer, int len) +const char *netdev_drivername(const struct net_device *dev) { const struct device_driver *driver; const struct device *parent; - - if (len <= 0 || !buffer) - return buffer; - buffer[0] = 0; + const char *empty = ""; parent = dev->dev.parent; - if (!parent) - return buffer; + return empty; driver = parent->driver; if (driver && driver->name) - strlcpy(buffer, driver->name, len); - return buffer; + return driver->name; + return empty; } static int __netdev_printk(const char *level, const struct net_device *dev, diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index b1721d71c27c..b4c680900d7a 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -251,9 +251,8 @@ static void dev_watchdog(unsigned long arg) } if (some_queue_timedout) { - char drivername[64]; WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit queue %u timed out\n", - dev->name, netdev_drivername(dev, drivername, 64), i); + dev->name, netdev_drivername(dev), i); dev->netdev_ops->ndo_tx_timeout(dev); } if (!mod_timer(&dev->watchdog_timer, From 79b3891587741dfac72cdfead1f2764b56a567b0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 6 Jun 2011 17:00:35 -0700 Subject: [PATCH 142/595] irda: iriap: Use seperate lockdep class for irias_objects->hb_spinlock The SEQ output functions grab the obj->attrib->hb_spinlock lock of sub-objects found in the hash traversal. These locks are in a different realm than the one used for the irias_objects hash table itself. So put the latter into it's own lockdep class. Reported-by: Dave Jones Signed-off-by: David S. Miller --- net/irda/iriap.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 36477538cea8..f876eed7d4aa 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -87,6 +87,8 @@ static inline void iriap_start_watchdog_timer(struct iriap_cb *self, iriap_watchdog_timer_expired); } +static struct lock_class_key irias_objects_key; + /* * Function iriap_init (void) * @@ -114,6 +116,9 @@ int __init iriap_init(void) return -ENOMEM; } + lockdep_set_class_and_name(&irias_objects->hb_spinlock, &irias_objects_key, + "irias_objects"); + /* * Register some default services for IrLMP */ From 9c4843ea576107a3c1fb94f2f758f198e9fe9e54 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 6 Jun 2011 15:40:23 -0400 Subject: [PATCH 143/595] cifs: silence printk when establishing first session on socket When signing is enabled, the first session that's established on a socket will cause a printk like this to pop: CIFS VFS: Unexpected SMB signature This is because the key exchange hasn't happened yet, so the signature field is bogus. Don't try to check the signature on the socket until the first session has been established. Also, eliminate the specific check for SMB_COM_NEGOTIATE since this check covers that case too. Cc: stable@kernel.org Cc: Shirish Pargaonkar Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsencrypt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index dfbd9f1f373d..5a0ee7f2af06 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -184,7 +184,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, if (cifs_pdu == NULL || server == NULL) return -EINVAL; - if (cifs_pdu->Command == SMB_COM_NEGOTIATE) + if (!server->session_estab) return 0; if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) { From 0aff1c0cef13b34c17e81a502336fad738151c37 Mon Sep 17 00:00:00 2001 From: GuoWen Li Date: Wed, 1 Jun 2011 19:18:47 +0800 Subject: [PATCH 144/595] ftrace: Fix possible undefined return code kernel/trace/ftrace.c: In function 'ftrace_regex_write.clone.15': kernel/trace/ftrace.c:2743:6: warning: 'ret' may be used uninitialized in this function Signed-off-by: GuoWen Li Link: http://lkml.kernel.org/r/201106011918.47939.guowen.li.linux@gmail.com 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 1ee417fcbfa5..204b3eb4e690 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2740,7 +2740,7 @@ static int ftrace_process_regex(struct ftrace_hash *hash, { char *func, *command, *next = buff; struct ftrace_func_command *p; - int ret; + int ret = -EINVAL; func = strsep(&next, ":"); From 0a1896b27b030529ec770aefd790544a1bdb7d5a Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Mon, 6 Jun 2011 18:55:34 -0400 Subject: [PATCH 145/595] ALSA: hda: Fix quirk for Dell Inspiron 910 BugLink: https://launchpad.net/bugs/792712 The original reporter states that sound from the internal speakers is inaudible until using the model=auto quirk. This symptom is due to an existing quirk mask for 0x102802b* that uses the model=dell quirk. To limit the possible regressions, leave the existing quirk mask but add a higher priority specific mask for the reporter's PCI SSID. Reported-and-tested-by: rodni hipp Cc: [2.6.38+] Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai --- 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 7a4e10002f56..d7007896772b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -13860,6 +13860,7 @@ static const struct snd_pci_quirk alc268_cfg_tbl[] = { SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One", ALC268_ACER_ASPIRE_ONE), SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL), + SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron 910", ALC268_AUTO), SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0, "Dell Inspiron Mini9/Vostro A90", ALC268_DELL), /* almost compatible with toshiba but with optional digital outs; From 13fcb7bd322164c67926ffe272846d4860196dc6 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 6 Jun 2011 22:42:06 -0700 Subject: [PATCH 146/595] af_packet: prevent information leak In 2.6.27, commit 393e52e33c6c2 (packet: deliver VLAN TCI to userspace) added a small information leak. Add padding field and make sure its zeroed before copy to user. Signed-off-by: Eric Dumazet CC: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/if_packet.h | 2 ++ net/packet/af_packet.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h index 6d66ce1791a9..7b318630139f 100644 --- a/include/linux/if_packet.h +++ b/include/linux/if_packet.h @@ -62,6 +62,7 @@ struct tpacket_auxdata { __u16 tp_mac; __u16 tp_net; __u16 tp_vlan_tci; + __u16 tp_padding; }; /* Rx ring - header status */ @@ -101,6 +102,7 @@ struct tpacket2_hdr { __u32 tp_sec; __u32 tp_nsec; __u16 tp_vlan_tci; + __u16 tp_padding; }; #define TPACKET2_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll)) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index ba248d93399a..c0c3cda19712 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -804,6 +804,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, } else { h.h2->tp_vlan_tci = 0; } + h.h2->tp_padding = 0; hdrlen = sizeof(*h.h2); break; default: @@ -1736,6 +1737,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, } else { aux.tp_vlan_tci = 0; } + aux.tp_padding = 0; put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux); } From 6407d74c5106bb362b4087693688afd34942b094 Mon Sep 17 00:00:00 2001 From: Alexander Holler Date: Tue, 7 Jun 2011 00:51:35 -0700 Subject: [PATCH 147/595] bridge: provide a cow_metrics method for fake_ops Like in commit 0972ddb237 (provide cow_metrics() methods to blackhole dst_ops), we must provide a cow_metrics for bridges fake_dst_ops as well. This fixes a regression coming from commits 62fa8a846d7d (net: Implement read-only protection and COW'ing of metrics.) and 33eb9873a28 (bridge: initialize fake_rtable metrics) ip link set mybridge mtu 1234 --> [ 136.546243] Pid: 8415, comm: ip Tainted: P 2.6.39.1-00006-g40545b7 #103 ASUSTeK Computer Inc. V1Sn /V1Sn [ 136.546256] EIP: 0060:[<00000000>] EFLAGS: 00010202 CPU: 0 [ 136.546268] EIP is at 0x0 [ 136.546273] EAX: f14a389c EBX: 000005d4 ECX: f80d32c0 EDX: f80d1da1 [ 136.546279] ESI: f14a3000 EDI: f255bf10 EBP: f15c3b54 ESP: f15c3b48 [ 136.546285] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 [ 136.546293] Process ip (pid: 8415, ti=f15c2000 task=f4741f80 task.ti=f15c2000) [ 136.546297] Stack: [ 136.546301] f80c658f f14a3000 ffffffed f15c3b64 c12cb9c8 f80d1b80 ffffffa1 f15c3bbc [ 136.546315] c12da347 c12d9c7d 00000000 f7670b00 00000000 f80d1b80 ffffffa6 f15c3be4 [ 136.546329] 00000004 f14a3000 f255bf20 00000008 f15c3bbc c11d6cae 00000000 00000000 [ 136.546343] Call Trace: [ 136.546359] [] ? br_change_mtu+0x5f/0x80 [bridge] [ 136.546372] [] dev_set_mtu+0x38/0x80 [ 136.546381] [] do_setlink+0x1a7/0x860 [ 136.546390] [] ? rtnl_fill_ifinfo+0x9bd/0xc70 [ 136.546400] [] ? nla_parse+0x6e/0xb0 [ 136.546409] [] rtnl_newlink+0x361/0x510 [ 136.546420] [] ? vmalloc_sync_all+0x100/0x100 [ 136.546429] [] ? error_code+0x5a/0x60 [ 136.546438] [] ? rtnl_configure_link+0x80/0x80 [ 136.546446] [] rtnetlink_rcv_msg+0xfa/0x210 [ 136.546454] [] ? __rtnl_unlock+0x20/0x20 [ 136.546463] [] netlink_rcv_skb+0x8e/0xb0 [ 136.546471] [] rtnetlink_rcv+0x1c/0x30 [ 136.546479] [] netlink_unicast+0x23a/0x280 [ 136.546487] [] netlink_sendmsg+0x26b/0x2f0 [ 136.546497] [] sock_sendmsg+0xc8/0x100 [ 136.546508] [] ? __alloc_pages_nodemask+0xe1/0x750 [ 136.546517] [] ? _copy_from_user+0x42/0x60 [ 136.546525] [] ? verify_iovec+0x4c/0xc0 [ 136.546534] [] sys_sendmsg+0x1c5/0x200 [ 136.546542] [] ? __do_fault+0x310/0x410 [ 136.546549] [] ? do_wp_page+0x1d6/0x6b0 [ 136.546557] [] ? handle_pte_fault+0xe1/0x720 [ 136.546565] [] ? sys_getsockname+0x7f/0x90 [ 136.546574] [] ? handle_mm_fault+0xb1/0x180 [ 136.546582] [] ? vmalloc_sync_all+0x100/0x100 [ 136.546589] [] ? do_page_fault+0x173/0x3d0 [ 136.546596] [] ? sys_recvmsg+0x3b/0x60 [ 136.546605] [] sys_socketcall+0x293/0x2d0 [ 136.546614] [] sysenter_do_call+0x12/0x26 [ 136.546619] Code: Bad EIP value. [ 136.546627] EIP: [<00000000>] 0x0 SS:ESP 0068:f15c3b48 [ 136.546645] CR2: 0000000000000000 [ 136.546652] ---[ end trace 6909b560e78934fa ]--- Signed-off-by: Alexander Holler Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/bridge/br_netfilter.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 3fa123185e89..56149ec36d7f 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -104,10 +104,16 @@ static void fake_update_pmtu(struct dst_entry *dst, u32 mtu) { } +static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old) +{ + return NULL; +} + static struct dst_ops fake_dst_ops = { .family = AF_INET, .protocol = cpu_to_be16(ETH_P_IP), .update_pmtu = fake_update_pmtu, + .cow_metrics = fake_cow_metrics, }; /* From 264524d5e5195f6e0f099bee20253a22b651e272 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 6 Jun 2011 20:50:03 +0000 Subject: [PATCH 148/595] net: cpu offline cause napi stall Frank Blaschka reported : During heavy network load we turn off/on cpus. Sometimes this causes a stall on the network device. Digging into the dump I found out following: napi is scheduled but does not run. From the I/O buffers and the napi state I see napi/rx_softirq processing has stopped because the budget was reached. napi stays in the softnet_data poll_list and the rx_softirq was raised again. I assume at this time the cpu offline comes in, the rx softirq is raised/moved to another cpu but napi stays in the poll_list of the softnet_data of the now offline cpu. Reviewing dev_cpu_callback (net/core/dev.c) I did not find the poll_list is transfered to the new cpu. This patch is a straightforward implementation of Frank suggestion : Transfert poll_list and trigger NET_RX_SOFTIRQ on new cpu. Reported-by: Frank Blaschka Signed-off-by: Heiko Carstens Signed-off-by: Eric Dumazet Tested-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index 1af6cb27f67a..a54c9f87ddbb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6178,6 +6178,11 @@ static int dev_cpu_callback(struct notifier_block *nfb, oldsd->output_queue = NULL; oldsd->output_queue_tailp = &oldsd->output_queue; } + /* Append NAPI poll list from offline CPU. */ + if (!list_empty(&oldsd->poll_list)) { + list_splice_init(&oldsd->poll_list, &sd->poll_list); + raise_softirq_irqoff(NET_RX_SOFTIRQ); + } raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_enable(); From 26018874e3584f1658570d41d57d4c34f6a53aa0 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 6 Jun 2011 16:50:14 +0200 Subject: [PATCH 149/595] x86/amd-iommu: Fix boot crash with hidden PCI devices Some PCIe cards ship with a PCI-PCIe bridge which is not visible as a PCI device in Linux. But the device-id of the bridge is present in the IOMMU tables which causes a boot crash in the IOMMU driver. This patch fixes by removing these cards from the IOMMU handling. This is a pure -stable fix, a real fix to handle this situation appriatly will follow for the next merge window. Cc: stable@kernel.org # > 2.6.32 Signed-off-by: Joerg Roedel --- arch/x86/kernel/amd_iommu.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index b2c309b07427..7c3a95e54ec5 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -155,6 +155,10 @@ static int iommu_init_device(struct device *dev) pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff); if (pdev) dev_data->alias = &pdev->dev; + else { + kfree(dev_data); + return -ENOTSUPP; + } atomic_set(&dev_data->bind, 0); @@ -164,6 +168,20 @@ static int iommu_init_device(struct device *dev) return 0; } +static void iommu_ignore_device(struct device *dev) +{ + u16 devid, alias; + + devid = get_device_id(dev); + alias = amd_iommu_alias_table[devid]; + + memset(&amd_iommu_dev_table[devid], 0, sizeof(struct dev_table_entry)); + memset(&amd_iommu_dev_table[alias], 0, sizeof(struct dev_table_entry)); + + amd_iommu_rlookup_table[devid] = NULL; + amd_iommu_rlookup_table[alias] = NULL; +} + static void iommu_uninit_device(struct device *dev) { kfree(dev->archdata.iommu); @@ -193,7 +211,9 @@ int __init amd_iommu_init_devices(void) continue; ret = iommu_init_device(&pdev->dev); - if (ret) + if (ret == -ENOTSUPP) + iommu_ignore_device(&pdev->dev); + else if (ret) goto out_free; } From 064d58ee3afb8a865a72d24e069c7258ec38640e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 7 Jun 2011 10:24:46 +0200 Subject: [PATCH 150/595] ASoC: Blackfin: bf5xx-ad1836: Fix codec device name Fix the codec_name field of the dai_link to match the actual device name of the codec. Otherwise the card won't be instantiated. Signed-off-by: Lars-Peter Clausen Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/blackfin/bf5xx-ad1836.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index ea4951cf5526..f79d1655e035 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c @@ -75,7 +75,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { .cpu_dai_name = "bfin-tdm.0", .codec_dai_name = "ad1836-hifi", .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "ad1836.0", + .codec_name = "spi0.4", .ops = &bf5xx_ad1836_ops, }, { @@ -84,7 +84,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { .cpu_dai_name = "bfin-tdm.1", .codec_dai_name = "ad1836-hifi", .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "ad1836.0", + .codec_name = "spi0.4", .ops = &bf5xx_ad1836_ops, }, }; From f2513cde93f0957d5dc6c09bc24b0cccd27d8e1d Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 6 Jun 2011 12:32:43 +0200 Subject: [PATCH 151/595] lockdep: Fix lock_is_held() on recursion The main lock_is_held() user is lockdep_assert_held(), avoid false assertions in lockdep_off() sections by unconditionally reporting the lock is taken. [ the reason this is important is a lockdep_assert_held() in ttwu() which triggers a warning under lockdep_off() as in printk() which can trigger another wakeup and lock up due to spinlock recursion, as reported and heroically debugged by Arne Jansen ] Reported-and-tested-by: Arne Jansen Signed-off-by: Peter Zijlstra Cc: Linus Torvalds Cc: Link: http://lkml.kernel.org/r/1307398759.2497.966.camel@laptop Signed-off-by: Ingo Molnar --- kernel/lockdep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 63437d065ac8..298c9276dfdb 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -3426,7 +3426,7 @@ int lock_is_held(struct lockdep_map *lock) int ret = 0; if (unlikely(current->lockdep_recursion)) - return ret; + return 1; /* avoid false negative lockdep_assert_held() */ raw_local_irq_save(flags); check_flags(flags); From 6c6c54e1807faf116724451ef2bd14993780470a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 3 Jun 2011 17:37:07 +0200 Subject: [PATCH 152/595] sched: Fix/clarify set_task_cpu() locking rules Sergey reported a CONFIG_PROVE_RCU warning in push_rt_task where set_task_cpu() was called with both relevant rq->locks held, which should be sufficient for running tasks since holding its rq->lock will serialize against sched_move_task(). Update the comments and fix the task_group() lockdep test. Reported-and-tested-by: Sergey Senozhatsky Cc: Oleg Nesterov Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1307115427.2353.3456.camel@twins Signed-off-by: Ingo Molnar --- kernel/sched.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 2fe98ed474da..3f2e502d609b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -605,10 +605,10 @@ static inline int cpu_of(struct rq *rq) /* * Return the group to which this tasks belongs. * - * We use task_subsys_state_check() and extend the RCU verification - * with lockdep_is_held(&p->pi_lock) because cpu_cgroup_attach() - * holds that lock for each task it moves into the cgroup. Therefore - * by holding that lock, we pin the task to the current cgroup. + * 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. */ static inline struct task_group *task_group(struct task_struct *p) { @@ -616,7 +616,8 @@ static inline struct task_group *task_group(struct task_struct *p) struct cgroup_subsys_state *css; css = task_subsys_state_check(p, cpu_cgroup_subsys_id, - lockdep_is_held(&p->pi_lock)); + 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); @@ -2200,6 +2201,16 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu) !(task_thread_info(p)->preempt_count & PREEMPT_ACTIVE)); #ifdef CONFIG_LOCKDEP + /* + * The caller should hold either p->pi_lock or rq->lock, when changing + * 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(). + * + * Furthermore, all task_rq users should acquire both locks, see + * task_rq_lock(). + */ WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&p->pi_lock) || lockdep_is_held(&task_rq(p)->lock))); #endif From 942fd4225f72826b31d893582b6ae7e172bb3202 Mon Sep 17 00:00:00 2001 From: Austin Zhang Date: Sat, 28 May 2011 02:03:47 +0800 Subject: [PATCH 153/595] HID: hid-multitouch: add support for Chunghwa multi-touch panel Added Chunghwa hid multitouch panel support into hid-multitouch. Signed-off-by: Austin Zhang Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 1 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-multitouch.c | 5 +++++ 4 files changed, 10 insertions(+) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 67d2a7585934..36ca465c00ce 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -305,6 +305,7 @@ config HID_MULTITOUCH - 3M PCT touch screens - ActionStar dual touch panels - Cando dual touch panels + - Chunghwa panels - CVTouch panels - Cypress TrueTouch panels - Elo TouchSystems IntelliTouch Plus panels diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index c957c4b4fe70..f7440e8ce3e7 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1359,6 +1359,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, { 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_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) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 2bbaad70d76d..aecb5a4b8d6d 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -173,6 +173,9 @@ #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d #define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 +#define USB_VENDOR_ID_CHUNGHWAT 0x2247 +#define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 + #define USB_VENDOR_ID_CIDC 0x1677 #define USB_VENDOR_ID_CMEDIA 0x0d8c diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index ecd4d2db9e80..8bc32a0fa00e 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -593,6 +593,11 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, + /* Chunghwa Telecom touch panels */ + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, + USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, + /* CVTouch panels */ { .driver_data = MT_CLS_DEFAULT, HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, From c2f019713df67e09d32e1b3c12f147a83a579d25 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 1 Jun 2011 10:59:13 -0700 Subject: [PATCH 154/595] HID: MAINTAINERS: Update USB HID/HIDBP DRIVERS pattern It was moved by commit 1a978c50c6cf ("HID: Move hiddev.txt to the new Documentation/hid directory") so update the MAINTAINERS pattern too. cc: Jiri Kosina cc: Alan Ott Signed-off-by: Joe Perches Signed-off-by: Jiri Kosina --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 0b415248ae25..8bd7caefd855 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6423,7 +6423,7 @@ M: Jiri Kosina L: linux-usb@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained -F: Documentation/usb/hiddev.txt +F: Documentation/hid/hiddev.txt F: drivers/hid/usbhid/ USB ISP116X DRIVER From 21c13a4f7bc185552c4b402b792c3bbb9aa69df0 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 7 Jun 2011 11:35:52 -0400 Subject: [PATCH 155/595] usb-storage: redo incorrect reads Some USB mass-storage devices have bugs that cause them not to handle the first READ(10) command they receive correctly. The Corsair Padlock v2 returns completely bogus data for its first read (possibly it returns the data in encrypted form even though the device is supposed to be unlocked). The Feiya SD/SDHC card reader fails to complete the first READ(10) command after it is plugged in or after a new card is inserted, returning a status code that indicates it thinks the command was invalid, which prevents the kernel from retrying the read. Since the first read of a new device or a new medium is for the partition sector, the kernel is unable to retrieve the device's partition table. Users have to manually issue an "hdparm -z" or "blockdev --rereadpt" command before they can access the device. This patch (as1470) works around the problem. It adds a new quirk flag, US_FL_INVALID_READ10, indicating that the first READ(10) should always be retried immediately, as should any failing READ(10) commands (provided the preceding READ(10) command succeeded, to avoid getting stuck in a loop). The patch also adds appropriate unusual_devs entries containing the new flag. Signed-off-by: Alan Stern Tested-by: Sven Geggus Tested-by: Paul Hartman CC: Matthew Dharm CC: Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 2 ++ drivers/usb/storage/transport.c | 29 +++++++++++++++++++++++++++++ drivers/usb/storage/unusual_devs.h | 19 +++++++++++++++++++ drivers/usb/storage/usb.c | 13 ++++++++++++- drivers/usb/storage/usb.h | 2 ++ include/linux/usb_usual.h | 4 +++- 6 files changed, 67 insertions(+), 2 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index d9a203b058f1..fd248a318211 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2598,6 +2598,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. unlock ejectable media); m = MAX_SECTORS_64 (don't transfer more than 64 sectors = 32 KB at a time); + n = INITIAL_READ10 (force a retry of the + initial READ(10) command); o = CAPACITY_OK (accept the capacity reported by the device); r = IGNORE_RESIDUE (the device reports diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 00418995d8e9..e8ae21b2d387 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -819,6 +819,35 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) } } + /* + * Some devices don't work or return incorrect data the first + * time they get a READ(10) command, or for the first READ(10) + * after a media change. If the INITIAL_READ10 flag is set, + * keep track of whether READ(10) commands succeed. If the + * previous one succeeded and this one failed, set the REDO_READ10 + * flag to force a retry. + */ + if (unlikely((us->fflags & US_FL_INITIAL_READ10) && + srb->cmnd[0] == READ_10)) { + if (srb->result == SAM_STAT_GOOD) { + set_bit(US_FLIDX_READ10_WORKED, &us->dflags); + } else if (test_bit(US_FLIDX_READ10_WORKED, &us->dflags)) { + clear_bit(US_FLIDX_READ10_WORKED, &us->dflags); + set_bit(US_FLIDX_REDO_READ10, &us->dflags); + } + + /* + * Next, if the REDO_READ10 flag is set, return a result + * code that will cause the SCSI core to retry the READ(10) + * command immediately. + */ + if (test_bit(US_FLIDX_REDO_READ10, &us->dflags)) { + clear_bit(US_FLIDX_REDO_READ10, &us->dflags); + srb->result = DID_IMM_RETRY << 16; + srb->sense_buffer[0] = 0; + } + } + /* Did we transfer less than the minimum amount required? */ if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) && scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index c1602b8c5594..ccff3483eebc 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1114,6 +1114,16 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by Paul Hartman + * This card reader returns "Illegal Request, Logical Block Address + * Out of Range" for the first READ(10) after a new card is inserted. + */ +UNUSUAL_DEV( 0x090c, 0x6000, 0x0100, 0x0100, + "Feiya", + "SD/SDHC Card Reader", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_INITIAL_READ10 ), + /* This Pentax still camera is not conformant * to the USB storage specification: - * - It does not like the INQUIRY command. So we must handle this command @@ -1888,6 +1898,15 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_READ_DISC_INFO ), +/* Reported by Sven Geggus + * This encrypted pen drive returns bogus data for the initial READ(10). + */ +UNUSUAL_DEV( 0x1b1c, 0x1ab5, 0x0200, 0x0200, + "Corsair", + "Padlock v2", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_INITIAL_READ10 ), + /* Patch by Richard Schtz * This external hard drive enclosure uses a JMicron chip which * needs the US_FL_IGNORE_RESIDUE flag to work properly. */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 5ee7ac42e08f..0ca095820f3e 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -440,7 +440,8 @@ static void adjust_quirks(struct us_data *us) US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 | US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE | US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT | - US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16); + US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 | + US_FL_INITIAL_READ10); p = quirks; while (*p) { @@ -490,6 +491,9 @@ static void adjust_quirks(struct us_data *us) case 'm': f |= US_FL_MAX_SECTORS_64; break; + case 'n': + f |= US_FL_INITIAL_READ10; + break; case 'o': f |= US_FL_CAPACITY_OK; break; @@ -953,6 +957,13 @@ int usb_stor_probe2(struct us_data *us) if (result) goto BadDevice; + /* + * If the device returns invalid data for the first READ(10) + * command, indicate the command should be retried. + */ + if (us->fflags & US_FL_INITIAL_READ10) + set_bit(US_FLIDX_REDO_READ10, &us->dflags); + /* Acquire all the other resources and add the host */ result = usb_stor_acquire_resources(us); if (result) diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 89d3bfff98df..7b0f2113632e 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -73,6 +73,8 @@ struct us_unusual_dev { #define US_FLIDX_RESETTING 4 /* device reset in progress */ #define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */ #define US_FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */ +#define US_FLIDX_REDO_READ10 7 /* redo READ(10) command */ +#define US_FLIDX_READ10_WORKED 8 /* previous READ(10) succeeded */ #define USB_STOR_STRING_LEN 32 diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index 71693d4a4fe1..17df3600bcef 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -62,7 +62,9 @@ US_FLAG(NO_READ_DISC_INFO, 0x00040000) \ /* cannot handle READ_DISC_INFO */ \ US_FLAG(NO_READ_CAPACITY_16, 0x00080000) \ - /* cannot handle READ_CAPACITY_16 */ + /* cannot handle READ_CAPACITY_16 */ \ + US_FLAG(INITIAL_READ10, 0x00100000) \ + /* Initial READ(10) (and others) must be retried */ #define US_FLAG(name, value) US_FL_##name = value , enum { US_DO_ALL_FLAGS }; From c5c69f3f0dcf9b569c8f3ad67f3af92cfcedac43 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 7 Jun 2011 11:33:01 -0400 Subject: [PATCH 156/595] USB: dummy-hcd needs the has_tt flag Like with other host controllers capable of operating at both high speed and full speed, we need to indicate that the emulated controller presented by dummy-hcd has this ability. Otherwise usbcore will not accept full-speed gadgets under dummy-hcd. This patch (as1469) sets the appropriate has_tt flag. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/dummy_hcd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 61ff927928ab..d3dcabc1a5fc 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1906,6 +1906,7 @@ static int dummy_hcd_probe(struct platform_device *pdev) if (!hcd) return -ENOMEM; the_controller = hcd_to_dummy (hcd); + hcd->has_tt = 1; retval = usb_add_hcd(hcd, 0, 0); if (retval != 0) { From 97b2f900335befbf6c4323ea6fd560ea5df4d154 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 7 Jun 2011 11:31:05 -0400 Subject: [PATCH 157/595] USB: CONFIG_USB_GADGET_DUALSPEED is not user-configurable This patch (as1468) changes the Kconfig definition for USB_GADGET_DUALSPEED. This option is determined entirely by which device controller drivers are to be built, through Select statements; it does not need to be (and should not be) configurable by the user. Also, the "default n" line is superfluous -- everything defaults to N. Signed-off-by: Alan Stern Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/Kconfig | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 58456d1aec21..029e288805b6 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -632,13 +632,10 @@ config USB_DUMMY_HCD endchoice +# Selected by UDC drivers that support high-speed operation. config USB_GADGET_DUALSPEED bool depends on USB_GADGET - default n - help - Means that gadget drivers should include extra descriptors - and code to handle dual-speed controllers. # # USB Gadget Drivers From 7febe2be36035e5c75128e8cc3baeb1f30fa2bc4 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 1 Jun 2011 19:10:06 +0200 Subject: [PATCH 158/595] drivers/usb/host/ohci-pxa27x.c: add missing clk_put Add a label before the call to clk_put and jump to that in the error handling code that occurs after the call to clk_get has succeeded. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r exists@ expression e1,e2; statement S; @@ e1 = clk_get@p1(...); ... when != e1 = e2 when != clk_put(e1) when any if (...) { ... when != clk_put(e1) when != if (...) { ... clk_put(e1) ... } * return@p3 ...; } else S // Signed-off-by: Julia Lawall Acked-by: Eric Miao Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-pxa27x.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index afef7b0a4195..80be5472783a 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -312,8 +312,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device return PTR_ERR(usb_clk); hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x"); - if (!hcd) - return -ENOMEM; + if (!hcd) { + retval = -ENOMEM; + goto err0; + } r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { @@ -368,6 +370,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err1: usb_put_hcd(hcd); + err0: clk_put(usb_clk); return retval; } From 0bf8fa04e80a562641f687547053f98670f25cf9 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Tue, 7 Jun 2011 14:04:49 +0530 Subject: [PATCH 159/595] gpio/exynos4: Fix incorrect mapping of gpio pull-up macro to register setting The S3C_GPIO_PULL_UP macro value incorrectly maps to a reserved setting of GPIO pull up/down registers on Exynos4 platform. Fix this incorrect mapping by adding wrappers to the s3c_gpio_setpull_updown and s3c_gpio_getpull_updown functions. Signed-off-by: Thomas Abraham Acked-by: Kyungmin Park Signed-off-by: Grant Likely --- drivers/gpio/gpio-exynos4.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-exynos4.c b/drivers/gpio/gpio-exynos4.c index d54ca6adb660..9029835112e7 100644 --- a/drivers/gpio/gpio-exynos4.c +++ b/drivers/gpio/gpio-exynos4.c @@ -21,16 +21,37 @@ #include #include +int s3c_gpio_setpull_exynos4(struct s3c_gpio_chip *chip, + unsigned int off, s3c_gpio_pull_t pull) +{ + if (pull == S3C_GPIO_PULL_UP) + pull = 3; + + return s3c_gpio_setpull_updown(chip, off, pull); +} + +s3c_gpio_pull_t s3c_gpio_getpull_exynos4(struct s3c_gpio_chip *chip, + unsigned int off) +{ + s3c_gpio_pull_t pull; + + pull = s3c_gpio_getpull_updown(chip, off); + if (pull == 3) + pull = S3C_GPIO_PULL_UP; + + return pull; +} + static struct s3c_gpio_cfg gpio_cfg = { .set_config = s3c_gpio_setcfg_s3c64xx_4bit, - .set_pull = s3c_gpio_setpull_updown, - .get_pull = s3c_gpio_getpull_updown, + .set_pull = s3c_gpio_setpull_exynos4, + .get_pull = s3c_gpio_getpull_exynos4, }; static struct s3c_gpio_cfg gpio_cfg_noint = { .set_config = s3c_gpio_setcfg_s3c64xx_4bit, - .set_pull = s3c_gpio_setpull_updown, - .get_pull = s3c_gpio_getpull_updown, + .set_pull = s3c_gpio_setpull_exynos4, + .get_pull = s3c_gpio_getpull_exynos4, }; /* From bb77f6341728624314f488ebd8b4c69f2caa33ea Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 7 Jun 2011 14:03:08 -0400 Subject: [PATCH 160/595] Revert "mac80211: stop queues before rate control updation" This reverts commit 1d38c16ce4156f63b45abbd09dd28ca2ef5172b4. The mac80211 maintainer raised complaints about abuse of the CSA stop reason, and about whether this patch actually serves its intended purpose at all. Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 456cccf26b51..d595265d6c22 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -232,9 +232,6 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type)); } - ieee80211_stop_queues_by_reason(&sdata->local->hw, - IEEE80211_QUEUE_STOP_REASON_CSA); - /* channel_type change automatically detected */ ieee80211_hw_config(local, 0); @@ -248,9 +245,6 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); } - ieee80211_wake_queues_by_reason(&sdata->local->hw, - IEEE80211_QUEUE_STOP_REASON_CSA); - ht_opmode = le16_to_cpu(hti->operation_mode); /* if bss configuration changed store the new one */ From 4fea2e0e59dab863a63fa1638b86d850896cd861 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Tue, 31 May 2011 08:50:24 +0900 Subject: [PATCH 161/595] rtlwifi: Fix logic in rx_interrupt Should pass along packet if there's no CRC and no hardware error. Signed-off-by: Mike McCormack Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 89100e7c553b..3e055c6bad36 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -700,7 +700,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE); - if (!stats.crc || !stats.hwerror) { + if (!stats.crc && !stats.hwerror) { memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); From 6633d649788e72400b02098bd389585e2c56a557 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Tue, 7 Jun 2011 08:58:31 +0900 Subject: [PATCH 162/595] rtlwifi: Avoid modifying skbs that are resubmitted In the case we fail to allocate a new skb, the old skb should be resubmitted unmodified. Fixes bug introduced in a9e12869758430424804. Signed-off-by: Mike McCormack Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 3e055c6bad36..9f8ccae93317 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -669,6 +669,19 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) &rx_status, (u8 *) pdesc, skb); + new_skb = dev_alloc_skb(rtlpci->rxbuffersize); + if (unlikely(!new_skb)) { + RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), + DBG_DMESG, + ("can't alloc skb for rx\n")); + goto done; + } + + pci_unmap_single(rtlpci->pdev, + *((dma_addr_t *) skb->cb), + rtlpci->rxbuffersize, + PCI_DMA_FROMDEVICE); + skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc, false, HW_DESC_RXPKT_LEN)); @@ -685,21 +698,6 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) hdr = rtl_get_hdr(skb); fc = rtl_get_fc(skb); - /* try for new buffer - if allocation fails, drop - * frame and reuse old buffer - */ - new_skb = dev_alloc_skb(rtlpci->rxbuffersize); - if (unlikely(!new_skb)) { - RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), - DBG_DMESG, - ("can't alloc skb for rx\n")); - goto done; - } - pci_unmap_single(rtlpci->pdev, - *((dma_addr_t *) skb->cb), - rtlpci->rxbuffersize, - PCI_DMA_FROMDEVICE); - if (!stats.crc && !stats.hwerror) { memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); From 57a27e1d6a3bb9ad4efeebd3a8c71156d6207536 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Tue, 7 Jun 2011 20:42:26 +0300 Subject: [PATCH 163/595] nl80211: fix overflow in ssid_len When one of the SSID's length passed in a scan or sched_scan request is larger than 255, there will be an overflow in the u8 that is used to store the length before checking. This causes the check to fail and we overrun the buffer when copying the SSID. Fix this by checking the nl80211 attribute length before copying it to the struct. This is a follow up for the previous commit 208c72f4fe44fe09577e7975ba0e7fa0278f3d03, which didn't fix the problem entirely. Reported-by: Ido Yariv Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 88a565f130a5..98fa8eb6cc4b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3406,11 +3406,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) i = 0; if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { - request->ssids[i].ssid_len = nla_len(attr); - if (request->ssids[i].ssid_len > IEEE80211_MAX_SSID_LEN) { + if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) { err = -EINVAL; goto out_free; } + request->ssids[i].ssid_len = nla_len(attr); memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr)); i++; } @@ -3572,12 +3572,11 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { - request->ssids[i].ssid_len = nla_len(attr); - if (request->ssids[i].ssid_len > - IEEE80211_MAX_SSID_LEN) { + if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) { err = -EINVAL; goto out_free; } + request->ssids[i].ssid_len = nla_len(attr); memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr)); i++; From 265a5b7ee3eb21a4d0e53e17d59ba6eada91af39 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 6 Jun 2011 22:35:13 -0400 Subject: [PATCH 164/595] kprobes/trace: Fix kprobe selftest for gcc 4.6 With gcc 4.6, the self test kprobe function: kprobe_trace_selftest_target() is optimized such that kallsyms does not list it. The kprobes test uses this function to insert a probe and test it. But it will fail the test if the function is not listed in kallsyms. Adding a __used annotation keeps the symbol in the kallsyms table. Suggested-by: David Daney Cc: Masami Hiramatsu Signed-off-by: Steven Rostedt --- kernel/trace/trace_kprobe.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index f925c45f0afa..27d13b36b8be 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1870,8 +1870,12 @@ fs_initcall(init_kprobe_trace); #ifdef CONFIG_FTRACE_STARTUP_TEST -static int kprobe_trace_selftest_target(int a1, int a2, int a3, - int a4, int a5, int a6) +/* + * The "__used" keeps gcc from removing the function symbol + * from the kallsyms table. + */ +static __used int kprobe_trace_selftest_target(int a1, int a2, int a3, + int a4, int a5, int a6) { return a1 + a2 + a3 + a4 + a5 + a6; } From a4f18ed11a4ddf327dd91cd19e237278600ad327 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 7 Jun 2011 09:26:46 -0400 Subject: [PATCH 165/595] ftrace: Revert 8ab2b7efd ftrace: Remove unnecessary disabling of irqs Revert the commit that removed the disabling of interrupts around the initial modifying of mcount callers to nops, and update the comment. The original comment was outdated and stated that the interrupts were being disabled to prevent kstop machine, which was required with the old ftrace daemon, but was no longer the case. What the comment failed to mention was that interrupts needed to be disabled to keep interrupts from preempting the modifying of the code and then executing the code that was partially modified. Revert the commit and update the comment. Reported-by: Richard W.M. Jones Tested-by: Richard W.M. Jones Signed-off-by: Steven Rostedt --- kernel/trace/ftrace.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 204b3eb4e690..908038f57440 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3330,6 +3330,7 @@ static int ftrace_process_locs(struct module *mod, { unsigned long *p; unsigned long addr; + unsigned long flags; mutex_lock(&ftrace_lock); p = start; @@ -3346,7 +3347,13 @@ static int ftrace_process_locs(struct module *mod, ftrace_record_ip(addr); } + /* + * Disable interrupts to prevent interrupts from executing + * code that is being modified. + */ + local_irq_save(flags); ftrace_update_code(mod); + local_irq_restore(flags); mutex_unlock(&ftrace_lock); return 0; From 85ab9ee946da58f26d8a1d7b71664748bdc0f3b0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Jun 2011 12:19:14 -0700 Subject: [PATCH 166/595] Staging: altera: move .h file to proper place Staging drivers should be self-contained, without files in the include/ directories. So move the altera.h file back to the driver directory for now, until it moves out of the staging tree. Cc: Igor M. Liplianin Cc: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/staging/altera-stapl/altera-jtag.c | 2 +- drivers/staging/altera-stapl/altera.c | 2 +- {include/staging => drivers/staging/altera-stapl}/altera.h | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename {include/staging => drivers/staging/altera-stapl}/altera.h (100%) diff --git a/drivers/staging/altera-stapl/altera-jtag.c b/drivers/staging/altera-stapl/altera-jtag.c index 876308858b82..8b1620b1b2d0 100644 --- a/drivers/staging/altera-stapl/altera-jtag.c +++ b/drivers/staging/altera-stapl/altera-jtag.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include "altera.h" #include "altera-exprt.h" #include "altera-jtag.h" diff --git a/drivers/staging/altera-stapl/altera.c b/drivers/staging/altera-stapl/altera.c index 05aad351b120..9cd5e76880c0 100644 --- a/drivers/staging/altera-stapl/altera.c +++ b/drivers/staging/altera-stapl/altera.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include "altera.h" #include "altera-exprt.h" #include "altera-jtag.h" diff --git a/include/staging/altera.h b/drivers/staging/altera-stapl/altera.h similarity index 100% rename from include/staging/altera.h rename to drivers/staging/altera-stapl/altera.h From fe35a59e16fbd426194d5d081d59aa18752d1f4d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Jun 2011 12:23:57 -0700 Subject: [PATCH 167/595] Staging: remove STAGING_EXCLUDE_BUILD option Part of the requirement to be in the staging tree is that the code must build, so let's make it easier for people to build the code to test/prove this out. Based on a recommendation from Linus to implement this. Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index dfc16f955eb8..196284dc2f36 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -24,23 +24,6 @@ menuconfig STAGING if STAGING -config STAGING_EXCLUDE_BUILD - bool "Exclude Staging drivers from being built" if STAGING - default y - ---help--- - Are you sure you really want to build the staging drivers? - They taint your kernel, don't live up to the normal Linux - kernel quality standards, are a bit crufty around the edges, - and might go off and kick your dog when you aren't paying - attention. - - Say N here to be able to select and build the Staging drivers. - This option is primarily here to prevent them from being built - when selecting 'make allyesconfg' and 'make allmodconfig' so - don't be all that put off, your dog will be just fine. - -if !STAGING_EXCLUDE_BUILD - source "drivers/staging/tty/Kconfig" source "drivers/staging/generic_serial/Kconfig" @@ -177,5 +160,4 @@ source "drivers/staging/mei/Kconfig" source "drivers/staging/nvec/Kconfig" -endif # !STAGING_EXCLUDE_BUILD endif # STAGING From 91e623deccd5726ff97f1da6ac48dcc26048034a Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 25 May 2011 19:17:06 -0700 Subject: [PATCH 168/595] staging: fix olpc_dcon build, needs BACKLIGHT_CLASS_DEVICE Fix olpc_dcon.c build by selecting the needed kconfig symbol BACKLIGHT_CLASS_DEVICE. olpc_dcon.c:(.text+0x11588b): undefined reference to `backlight_device_register' Signed-off-by: Randy Dunlap Cc: Andres Salomon Cc: Chris Ball Cc: Jon Nettleton Signed-off-by: Greg Kroah-Hartman --- drivers/staging/olpc_dcon/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/olpc_dcon/Kconfig b/drivers/staging/olpc_dcon/Kconfig index b05306766870..fe40e0b6f675 100644 --- a/drivers/staging/olpc_dcon/Kconfig +++ b/drivers/staging/olpc_dcon/Kconfig @@ -2,6 +2,7 @@ config FB_OLPC_DCON tristate "One Laptop Per Child Display CONtroller support" depends on OLPC && FB select I2C + select BACKLIGHT_CLASS_DEVICE ---help--- Add support for the OLPC XO DCON controller. This controller is only available on OLPC platforms. Unless you have one of these From e1c78de9a462f45dacdc8c27baf77aa680bcf8a4 Mon Sep 17 00:00:00 2001 From: Roland Vossen Date: Tue, 24 May 2011 13:35:21 +0200 Subject: [PATCH 169/595] staging: brcm80211: fix for 'multiple definition of wl_msg_level' build err Reported-by: Linus Torvalds Signed-off-by: Roland Vossen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/brcm80211/brcmfmac/wl_iw.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/brcm80211/brcmfmac/wl_iw.c b/drivers/staging/brcm80211/brcmfmac/wl_iw.c index 929ceaf363be..15e1b05ca92d 100644 --- a/drivers/staging/brcm80211/brcmfmac/wl_iw.c +++ b/drivers/staging/brcm80211/brcmfmac/wl_iw.c @@ -64,8 +64,6 @@ wl_iw_extra_params_t g_wl_iw_params; extern bool wl_iw_conn_status_str(u32 event_type, u32 status, u32 reason, char *stringBuf, uint buflen); -uint wl_msg_level = WL_ERROR_VAL; - #define MAX_WLIW_IOCTL_LEN 1024 #ifdef CONFIG_WIRELESS_EXT From 827e4a07e8d0f6cf18e82988ae8daea3b5feab98 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 17 May 2011 15:15:19 -0700 Subject: [PATCH 170/595] staging: fix ath6kl build when CFG80211 is not enabled Fix build errors when CONFIG_CFG80211 is not enabled: drivers/built-in.o: In function `ar6k_cfg80211_deinit': (.text+0x189b71): undefined reference to `cfg80211_scan_done' drivers/built-in.o: In function `ar6k_cfg80211_deinit': (.text+0x189b86): undefined reference to `wiphy_unregister' drivers/built-in.o: In function `ar6k_cfg80211_deinit': (.text+0x189b8d): undefined reference to `wiphy_free' drivers/built-in.o: In function `ar6k_cfg80211_init': (.text+0x18add7): undefined reference to `wiphy_new' drivers/built-in.o: In function `ar6k_cfg80211_init': (.text+0x18ae48): undefined reference to `wiphy_register' drivers/built-in.o: In function `ar6k_cfg80211_tkip_micerr_event': (.text+0x18ae95): undefined reference to `cfg80211_michael_mic_failure' drivers/built-in.o: In function `ar6k_cfg80211_scan_node': (.text+0x18afb5): undefined reference to `__ieee80211_get_channel' drivers/built-in.o: In function `ar6k_cfg80211_scan_node': (.text+0x18afd2): undefined reference to `cfg80211_inform_bss_frame' drivers/built-in.o: In function `ar6k_cfg80211_disconnect_event': (.text+0x18b046): undefined reference to `cfg80211_ibss_joined' drivers/built-in.o: In function `ar6k_cfg80211_disconnect_event': (.text+0x18b176): undefined reference to `cfg80211_connect_result' drivers/built-in.o: In function `ar6k_cfg80211_disconnect_event': (.text+0x18b190): undefined reference to `cfg80211_disconnected' drivers/built-in.o: In function `ar6k_cfg80211_connect_event': (.text+0x18b291): undefined reference to `cfg80211_get_bss' drivers/built-in.o: In function `ar6k_cfg80211_connect_event': (.text+0x18b457): undefined reference to `cfg80211_put_bss' drivers/built-in.o: In function `ar6k_cfg80211_connect_event': (.text+0x18b4fa): undefined reference to `cfg80211_roamed' Signed-off-by: Randy Dunlap Cc: Luis R. Rodriguez Cc: Joe Perches Cc: Naveen Singh Signed-off-by: Peter Foley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ath6kl/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/ath6kl/Kconfig b/drivers/staging/ath6kl/Kconfig index 1f15e1fb1ab2..afd6cc16a2b8 100644 --- a/drivers/staging/ath6kl/Kconfig +++ b/drivers/staging/ath6kl/Kconfig @@ -1,6 +1,7 @@ config ATH6K_LEGACY tristate "Atheros AR6003 support (non mac80211)" depends on MMC && WLAN + depends on CFG80211 select WIRELESS_EXT select WEXT_PRIV help From cddac88f437b0370d3c0ac4c0b2d6c1ff914522d Mon Sep 17 00:00:00 2001 From: Nicolas Kaiser Date: Wed, 25 May 2011 02:03:02 +0200 Subject: [PATCH 171/595] staging: rts_pstor: use bitwise operator instead of logical one Looks like a typo. Signed-off-by: Nicolas Kaiser Reviewed-by: Peter Huewe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts_pstor/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rts_pstor/sd.c b/drivers/staging/rts_pstor/sd.c index bddb0312b31e..cdae497d5467 100644 --- a/drivers/staging/rts_pstor/sd.c +++ b/drivers/staging/rts_pstor/sd.c @@ -2328,7 +2328,7 @@ static int reset_sd(struct rtsx_chip *chip) retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0, SD_RSP_TYPE_R4, rsp, 5); if (retval == STATUS_SUCCESS) { - int func_num = (rsp[1] >> 4) && 0x07; + int func_num = (rsp[1] >> 4) & 0x07; if (func_num) { RTSX_DEBUGP("SD_IO card (Function number: %d)!\n", func_num); chip->sd_io = 1; From c11c4eebdd75fc0f443a3f794a2ddc85afed1932 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 25 May 2011 14:42:07 +0200 Subject: [PATCH 172/595] staging: iio: industrialio-trigger: set iio_poll_func private_data Failure to set iio_poll_func private_data, causes zero pointer access violations in all consumer trigger handlers. Signed-off-by: Michael Hennerich Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/industrialio-trigger.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c index 615902333fb0..d504aa251ced 100644 --- a/drivers/staging/iio/industrialio-trigger.c +++ b/drivers/staging/iio/industrialio-trigger.c @@ -294,6 +294,7 @@ struct iio_poll_func pf->h = h; pf->thread = thread; pf->type = type; + pf->private_data = private; return pf; } From d3ac0778801708caecb2b172328064255a350432 Mon Sep 17 00:00:00 2001 From: Arjan Mels Date: Fri, 20 May 2011 23:25:46 +0200 Subject: [PATCH 173/595] staging: usbip: bugfix prevent driver unbind Implemented pre_reset and post_reset methods of the driver to prevent the driver from being unbound upon a device reset. Because of this also the asynchronous reset introduced to prevent a race condition is no longer necessary (and sometimes causes problems, because it comes later then expected). Signed-off-by: Arjan Mels Cc: Greg Kroah-Hartman Cc: Takahiro Hirofuchi Cc: Max Vozeler Cc: usbip-devel Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/stub_dev.c | 21 +++++++++++++++++++++ drivers/staging/usbip/stub_rx.c | 20 +++++++++++--------- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c index 6e99ec87fee0..8cbea42b69bc 100644 --- a/drivers/staging/usbip/stub_dev.c +++ b/drivers/staging/usbip/stub_dev.c @@ -26,6 +26,8 @@ static int stub_probe(struct usb_interface *interface, const struct usb_device_id *id); static void stub_disconnect(struct usb_interface *interface); +static int stub_pre_reset(struct usb_interface *interface); +static int stub_post_reset(struct usb_interface *interface); /* * Define device IDs here if you want to explicitly limit exportable devices. @@ -59,6 +61,8 @@ struct usb_driver stub_driver = { .probe = stub_probe, .disconnect = stub_disconnect, .id_table = stub_table, + .pre_reset = stub_pre_reset, + .post_reset = stub_post_reset, }; /* @@ -541,3 +545,20 @@ static void stub_disconnect(struct usb_interface *interface) del_match_busid((char *)udev_busid); } } + +/* + * Presence of pre_reset and post_reset prevents the driver from being unbound + * when the device is being reset + */ + +int stub_pre_reset(struct usb_interface *interface) +{ + dev_dbg(&interface->dev, "pre_reset\n"); + return 0; +} + +int stub_post_reset(struct usb_interface *interface) +{ + dev_dbg(&interface->dev, "post_reset\n"); + return 0; +} diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c index a5c1fa1f0430..bc57844600b9 100644 --- a/drivers/staging/usbip/stub_rx.c +++ b/drivers/staging/usbip/stub_rx.c @@ -175,16 +175,18 @@ static int tweak_reset_device_cmd(struct urb *urb) dev_info(&urb->dev->dev, "usb_queue_reset_device\n"); /* - * usb_lock_device_for_reset caused a deadlock: it causes the driver - * to unbind. In the shutdown the rx thread is signalled to shut down - * but this thread is pending in the usb_lock_device_for_reset. - * - * Instead queue the reset. - * - * Unfortunatly an existing usbip connection will be dropped due to - * driver unbinding. + * With the implementation of pre_reset and post_reset the driver no + * longer unbinds. This allows the use of synchronous reset. */ - usb_queue_reset_device(sdev->interface); + + if (usb_lock_device_for_reset(sdev->udev, sdev->interface)<0) + { + dev_err(&urb->dev->dev, "could not obtain lock to reset device\n"); + return 0; + } + usb_reset_device(sdev->udev); + usb_unlock_device(sdev->udev); + return 0; } From 3ab8be53155617fa7ecc5b8cd259a458727a1d90 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Tue, 24 May 2011 13:04:56 +0100 Subject: [PATCH 174/595] staging: gma500: Skip bogus LVDS VBT mode and check for LVDS before adding backlight On the Fit-PC2 the VBT reports an invalid fixed panel mode for LVDS, this gets in the way for SDVO. This patch makes VBT parsing skip the invalid mode. When there is no LVDS output the backlight support crashes so the patch also checks for this before enabling it. Signed-off-by: Patrik Jakobsson Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gma500/psb_drv.c | 15 ++++++++++++++- drivers/staging/gma500/psb_intel_bios.c | 13 +++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c index 1c45c11a774e..aa87b1b6a44a 100644 --- a/drivers/staging/gma500/psb_drv.c +++ b/drivers/staging/gma500/psb_drv.c @@ -542,6 +542,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) unsigned long irqflags; int ret = -ENOMEM; uint32_t tt_pages; + struct drm_connector *connector; + struct psb_intel_output *psb_intel_output; dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); if (dev_priv == NULL) @@ -663,7 +665,18 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) drm_kms_helper_poll_init(dev); } - ret = psb_backlight_init(dev); + /* Only add backlight support if we have LVDS output */ + list_for_each_entry(connector, &dev->mode_config.connector_list, + head) { + psb_intel_output = to_psb_intel_output(connector); + + switch (psb_intel_output->type) { + case INTEL_OUTPUT_LVDS: + ret = psb_backlight_init(dev); + break; + } + } + if (ret) return ret; #if 0 diff --git a/drivers/staging/gma500/psb_intel_bios.c b/drivers/staging/gma500/psb_intel_bios.c index 48ac8ba7f40b..417965da5e24 100644 --- a/drivers/staging/gma500/psb_intel_bios.c +++ b/drivers/staging/gma500/psb_intel_bios.c @@ -154,10 +154,15 @@ static void parse_lfp_panel_data(struct drm_psb_private *dev_priv, fill_detail_timing_data(panel_fixed_mode, dvo_timing); - dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; - - DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); - drm_mode_debug_printmodeline(panel_fixed_mode); + if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) { + dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; + DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); + drm_mode_debug_printmodeline(panel_fixed_mode); + } else { + DRM_DEBUG("Ignoring bogus LVDS VBT mode.\n"); + dev_priv->lvds_vbt = 0; + kfree(panel_fixed_mode); + } return; } From aaa5c677910d313ca1318c905c799c459c6f0078 Mon Sep 17 00:00:00 2001 From: Michael Chang Date: Mon, 30 May 2011 14:28:25 +0800 Subject: [PATCH 175/595] staging: gma500: get control from firmware framebuffer if conflicts Many Linux distributions would enable vesafb in order to display early stage boot splash. In this case, we will get garbled X Window screen if running X fbdev on psbfb. This is because fb0 is occupied by vesafb while psbfb is on fb1. They tried to drive the same pieces of hardware at the same time. With unmodified X start-up, it would try to use default fb0 framebuffer device and unfortunately it is now broken becaues fb1 supersedes it. We should let psbfb takeover framebuffer control from vesafb to get around this problem. See also commit : 4410f3910947dcea8672280b3adecd53cec4e85e Signed-off-by: Michael Chang Cc: Alan Cox Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gma500/psb_fb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c index 99c03a2e06bd..084c36bbfe86 100644 --- a/drivers/staging/gma500/psb_fb.c +++ b/drivers/staging/gma500/psb_fb.c @@ -441,6 +441,16 @@ static int psbfb_create(struct psb_fbdev *fbdev, info->screen_size = size; memset(info->screen_base, 0, size); + if (dev_priv->pg->stolen_size) { + info->apertures = alloc_apertures(1); + if (!info->apertures) { + ret = -ENOMEM; + goto out_err0; + } + info->apertures->ranges[0].base = dev->mode_config.fb_base; + info->apertures->ranges[0].size = dev_priv->pg->stolen_size; + } + drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper, sizes->fb_width, sizes->fb_height); From 0d422f4237ce515678ebbb8781881e5d2e58b9d4 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Wed, 1 Jun 2011 13:44:11 +0530 Subject: [PATCH 176/595] staging: ath6kl: Fix a kernel panic during suspend/resume The kernel panic happens when we try to complete a pending scan request while going to suspend state. The cause for this kernel panic is accessing a freed memory (ar->arWmin). This is freed before ar6k_cfg80211_scanComplete_event() getting called where it is dereferenced. RIP: 0010:[] [] wlan_iterate_nodes+0x16/0xc0 [ath6kl] RSP: 0018:ffff8800719fbce8 EFLAGS: 00010296 RAX: ffff880071bbcc00 RBX: ffff880037b22520 RCX: ffff880077413c80 RDX: ffff880037b221c0 RSI: ffffffffa041ef10 RDI: 0000000000000020 RBP: ffff8800719fbd18 R08: 0000000000000001 R09: 0000000000000001 R10: 0000000000000400 R11: 0000000000000000 R12: 0000000000000010 R13: ffff8800719fbdd8 R14: 00007fff83a84b60 R15: 0000000000000001 FS: 00007fdccb8a7700(0000) GS:ffff880077400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000148 CR3: 0000000070604000 CR4: 00000000000006f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process rmmod (pid: 1998, threadinfo ffff8800719fa000, task ffff880066712d80) Stack: 0000000000000000 ffff880037b22520 0000000000000010 ffff8800719fbdd8 00007fff83a84b60 0000000000000001 ffff8800719fbd28 ffffffffa0429fe2 ffff8800719fbd58 ffffffffa041ee5f ffff8800719fbd58 ffff880037b22520 Call Trace: [] wmi_iterate_nodes+0x12/0x20 [ath6kl] [] ar6k_cfg80211_scanComplete_event+0x3f/0xf0 [ath6kl] [] ar6000_close+0x61/0x100 [ath6kl] [] __dev_close_many+0x96/0x100 [] dev_close_many+0x9d/0x120 [] rollback_registered_many+0xe8/0x290 [] unregister_netdevice_queue+0x96/0x100 [] unregister_netdev+0x20/0x30 [] ar6000_destroy+0x119/0x180 [ath6kl] [] ar6k_cleanup_module+0x2a/0x33 [ath6kl] [] sys_delete_module+0x19e/0x270 [] system_call_fastpath+0x16/0x1b Code: c3 0f 1f 40 00 48 89 df e8 68 ff ff ff eb df 66 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 55 41 54 53 48 83 ec 08 0f 1f 44 00 00 8b af 28 01 00 00 4c 8d 7f 08 49 89 fc 48 89 f3 49 89 d6 41 RIP [] wlan_iterate_nodes+0x16/0xc0 [ath6kl] RSP Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ath6kl/os/linux/cfg80211.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/ath6kl/os/linux/cfg80211.c b/drivers/staging/ath6kl/os/linux/cfg80211.c index 77dfb4070c1d..d3a774dbb7e8 100644 --- a/drivers/staging/ath6kl/os/linux/cfg80211.c +++ b/drivers/staging/ath6kl/os/linux/cfg80211.c @@ -870,7 +870,8 @@ ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status) if(ar->scan_request) { /* Translate data to cfg80211 mgmt format */ - wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy); + if (ar->arWmi) + wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy); cfg80211_scan_done(ar->scan_request, ((status & A_ECANCELED) || (status & A_EBUSY)) ? true : false); From 53aebb5312c797e4b63fb50473a55ed054b3cb2f Mon Sep 17 00:00:00 2001 From: Andre Bartke Date: Thu, 2 Jun 2011 00:21:45 +0200 Subject: [PATCH 177/595] staging: iio: error case memory leak fix The data pointer should be freed in the error cases of adis16400_trigger_handler(). Signed-off-by: Andre Bartke Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/imu/adis16400_ring.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c index 2589a7e167e4..3612373ddede 100644 --- a/drivers/staging/iio/imu/adis16400_ring.c +++ b/drivers/staging/iio/imu/adis16400_ring.c @@ -137,13 +137,13 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) if (st->variant->flags & ADIS16400_NO_BURST) { ret = adis16350_spi_read_all(&indio_dev->dev, st->rx); if (ret < 0) - return ret; + goto err; for (; i < ring->scan_count; i++) data[i] = *(s16 *)(st->rx + i*2); } else { ret = adis16400_spi_read_burst(&indio_dev->dev, st->rx); if (ret < 0) - return ret; + goto err; for (; i < indio_dev->ring->scan_count; i++) { j = __ffs(mask); mask &= ~(1 << j); @@ -158,9 +158,13 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) ring->access->store_to(indio_dev->ring, (u8 *) data, pf->timestamp); iio_trigger_notify_done(indio_dev->trig); - kfree(data); + kfree(data); return IRQ_HANDLED; + +err: + kfree(data); + return ret; } void adis16400_unconfigure_ring(struct iio_dev *indio_dev) From 99592ba4a80edb84938e7e0cf71fdecff1ce67fd Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 7 Jun 2011 21:32:31 +0200 Subject: [PATCH 178/595] PM / Intel IOMMU: Fix init_iommu_pm_ops() for CONFIG_PM unset If CONFIG_PM is not set, init_iommu_pm_ops() introduced by commit 134fac3f457f3dd753ecdb25e6da3e5f6629f696 (PCI / Intel IOMMU: Use syscore_ops instead of sysdev class and sysdev) is not defined appropriately. Fix this issue. Reported-by: Tony Luck Signed-off-by: Rafael J. Wysocki --- drivers/pci/intel-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 59f17acf7f68..f02c34d26d1b 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3388,7 +3388,7 @@ static void __init init_iommu_pm_ops(void) } #else -static inline int init_iommu_pm_ops(void) { } +static inline void init_iommu_pm_ops(void) {} #endif /* CONFIG_PM */ /* From 8c56cacc724c7650b893d43068fa66044aa29a61 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 25 May 2011 13:19:39 +0200 Subject: [PATCH 179/595] libata: fix unexpectedly frozen port after ata_eh_reset() To work around controllers which can't properly plug events while reset, ata_eh_reset() clears error states and ATA_PFLAG_EH_PENDING after reset but before RESET is marked done. As reset is the final recovery action and full verification of devices including onlineness and classfication match is done afterwards, this shouldn't lead to lost devices or missed hotplug events. Unfortunately, it forgot to thaw the port when clearing EH_PENDING, so if the condition happens after resetting an empty port, the port could be left frozen and EH will end without thawing it, making the port unresponsive to further hotplug events. Thaw if the port is frozen after clearing EH_PENDING. This problem is reported by Bruce Stenning in the following thread. http://thread.gmane.org/gmane.linux.kernel/1123265 stable: I think we should weather this patch a bit longer in -rcX before sending it to -stable. Please wait at least a month after this patch makes upstream. Thanks. -v2: Fixed spelling in the comment per Dave Howorth. Signed-off-by: Tejun Heo Reported-by: Bruce Stenning Cc: stable@kernel.org Cc: Dave Howorth Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index dfb6e9d3d759..7f099d6e4e0b 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2802,10 +2802,11 @@ int ata_eh_reset(struct ata_link *link, int classify, } /* - * Some controllers can't be frozen very well and may set - * spuruious error conditions during reset. Clear accumulated - * error information. As reset is the final recovery action, - * nothing is lost by doing this. + * Some controllers can't be frozen very well and may set spurious + * error conditions during reset. Clear accumulated error + * information and re-thaw the port if frozen. As reset is the + * final recovery action and we cross check link onlineness against + * device classification later, no hotplug event is lost by this. */ spin_lock_irqsave(link->ap->lock, flags); memset(&link->eh_info, 0, sizeof(link->eh_info)); @@ -2814,6 +2815,9 @@ int ata_eh_reset(struct ata_link *link, int classify, ap->pflags &= ~ATA_PFLAG_EH_PENDING; spin_unlock_irqrestore(link->ap->lock, flags); + if (ap->pflags & ATA_PFLAG_FROZEN) + ata_eh_thaw_port(ap); + /* * Make sure onlineness and classification result correspond. * Hotplug could have happened during reset and some From 32919a28cc8470b1526f77b2f12cca8841b9ac62 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 7 Jun 2011 14:37:27 -0600 Subject: [PATCH 180/595] gpio/samsung: make Kconfig options def_bool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Samsung GPIO drivers are always built-in when the relevant platform is selected.  Change the Kconfig symbol to def_bool y dependant on the platform. Signed-off-by: H Hartley Sweeten Acked-by: Kyungmin Park Signed-off-by: Grant Likely --- drivers/gpio/Kconfig | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 317199796c5f..2967002a9f82 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -87,32 +87,20 @@ config GPIO_IT8761E Say yes here to support GPIO functionality of IT8761E super I/O chip. config GPIO_EXYNOS4 - bool "Samsung Exynos4 GPIO library support" - default y - depends on ARM && CPU_EXYNOS4210 - help - Say yes here to support Samsung Exynos4 series SoCs GPIO library + def_bool y + depends on CPU_EXYNOS4210 config GPIO_PLAT_SAMSUNG - bool "Samsung SoCs GPIO library support" - default y - depends on ARM && SAMSUNG_GPIOLIB_4BIT - help - Say yes here to support Samsung SoCs GPIO library + def_bool y + depends on SAMSUNG_GPIOLIB_4BIT config GPIO_S5PC100 - bool "Samsung S5PC100 GPIO library support" - default y - depends on ARM && CPU_S5PC100 - help - Say yes here to support Samsung S5PC100 SoCs GPIO library + def_bool y + depends on CPU_S5PC100 config GPIO_S5PV210 - bool "Samsung S5PV210/S5PC110 GPIO library support" - default y - depends on ARM && CPU_S5PV210 - help - Say yes here to support Samsung S5PV210/S5PC110 SoCs GPIO library + def_bool y + depends on CPU_S5PV210 config GPIO_PL061 bool "PrimeCell PL061 GPIO support" From 665c8c8ee405738375b679246b49342ce38ba056 Mon Sep 17 00:00:00 2001 From: "Williams, Mitch A" Date: Tue, 7 Jun 2011 14:22:57 -0700 Subject: [PATCH 181/595] igb: fix i350 SR-IOV failture When SR-IOV is enabled, i350 devices fail to pass traffic. This is due to the driver attempting to enable RSS on the PF device, which is not supported by the i350. When max_vfs is specified on an i350 adapter, set the number of RSS queues to 1. This issue affects 2.6.39 as well. CC: stable@kernel.org Signed-off-by: Mitch Williams Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 18fccf913635..2c28621eb30b 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2373,6 +2373,9 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) } #endif /* CONFIG_PCI_IOV */ adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus()); + /* i350 cannot do RSS and SR-IOV at the same time */ + if (hw->mac.type == e1000_i350 && adapter->vfs_allocated_count) + adapter->rss_queues = 1; /* * if rss_queues > 4 or vfs are going to be allocated with rss_queues From 3b3eca3116861113ccc0e1ca3b98cb43598f46a7 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 7 Jun 2011 23:34:58 +0200 Subject: [PATCH 182/595] PM / Runtime: Fix loops in pm_runtime_clk_notify() The loops over connection ID strings in pm_runtime_clk_notify() should actually iterate over the strings and not over the elements of the first of them, so make them behave as appropriate. This fixes a regression introduced by commit 600b776eb39a13a28b090 (OMAP1 / PM: Use generic clock manipulation routines for runtime PM). Reported-and-tested-by: Janusz Krzysztofik Signed-off-by: Rafael J. Wysocki --- drivers/base/power/clock_ops.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index c0dd09df7be8..eaa8a854af03 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -291,7 +291,7 @@ static int pm_runtime_clk_notify(struct notifier_block *nb, { struct pm_clk_notifier_block *clknb; struct device *dev = data; - char *con_id; + char **con_id; int error; dev_dbg(dev, "%s() %ld\n", __func__, action); @@ -309,8 +309,8 @@ static int pm_runtime_clk_notify(struct notifier_block *nb, dev->pwr_domain = clknb->pwr_domain; if (clknb->con_ids[0]) { - for (con_id = clknb->con_ids[0]; *con_id; con_id++) - pm_runtime_clk_add(dev, con_id); + for (con_id = clknb->con_ids; *con_id; con_id++) + pm_runtime_clk_add(dev, *con_id); } else { pm_runtime_clk_add(dev, NULL); } @@ -380,7 +380,7 @@ static int pm_runtime_clk_notify(struct notifier_block *nb, { struct pm_clk_notifier_block *clknb; struct device *dev = data; - char *con_id; + char **con_id; dev_dbg(dev, "%s() %ld\n", __func__, action); @@ -389,16 +389,16 @@ static int pm_runtime_clk_notify(struct notifier_block *nb, switch (action) { case BUS_NOTIFY_ADD_DEVICE: if (clknb->con_ids[0]) { - for (con_id = clknb->con_ids[0]; *con_id; con_id++) - enable_clock(dev, con_id); + for (con_id = clknb->con_ids; *con_id; con_id++) + enable_clock(dev, *con_id); } else { enable_clock(dev, NULL); } break; case BUS_NOTIFY_DEL_DEVICE: if (clknb->con_ids[0]) { - for (con_id = clknb->con_ids[0]; *con_id; con_id++) - disable_clock(dev, con_id); + for (con_id = clknb->con_ids; *con_id; con_id++) + disable_clock(dev, *con_id); } else { disable_clock(dev, NULL); } From 3095ec895fd5ec19a7cb60b5cbfa766d68a74a24 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Jun 2011 15:03:37 -0700 Subject: [PATCH 183/595] Revert "USB: option: add ID for ZTE MF 330" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit a559d2c8c1bf652ea2d0ecd6ab4a250fcdb37db8. Turns out that device id 0x1d6b:0x0002 is a USB hub, which causes havoc when the option driver tries to bind to it. So revert this as it doesn't seem to be needed at all. Thanks to Michael Tokarev and Paweł Drobek for working on resolving this issue. Cc: Paweł Drobek Cc: Michael Tokarev Cc: Dominik Brodowski Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index f7583f847438..60b25d8ea0e2 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -311,10 +311,6 @@ static void option_instat_callback(struct urb *urb); #define ZTE_PRODUCT_AC2726 0xfff5 #define ZTE_PRODUCT_AC8710T 0xffff -/* ZTE PRODUCTS -- alternate vendor ID */ -#define ZTE_VENDOR_ID2 0x1d6b -#define ZTE_PRODUCT_MF_330 0x0002 - #define BENQ_VENDOR_ID 0x04a5 #define BENQ_PRODUCT_H10 0x4068 @@ -941,7 +937,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) }, - { USB_DEVICE(ZTE_VENDOR_ID2, ZTE_PRODUCT_MF_330) }, { 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 */ From 5fba17084e5d1b00bf24e17b2b580cfa7705e7be Mon Sep 17 00:00:00 2001 From: oftedal Date: Wed, 1 Jun 2011 10:43:50 +0000 Subject: [PATCH 184/595] Restructure sun4d_build_device_irq so that timer interrupts can be allocated sun4d_build_device_irq was called without a valid platform_device when the system timer was initialized on sun4d systems. This caused a NULL pointer crash. Josip Rodin suggested that the current sun4d_build_device_irq should be split into two functions. So that the timer initialization could skip the slot and sbus interface detection code in sun4d_build_device_irq, as this does not make sence due to the timer interrupts not being generated from a device located on sbus. Signed-off-by: Kjetil Oftedal Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4d_irq.c | 78 ++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index a9ea60eb2c10..487c1bb374f5 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -299,19 +299,53 @@ static void __init sun4d_load_profile_irqs(void) } } +unsigned int _sun4d_build_device_irq(unsigned int real_irq, + unsigned int pil, + unsigned int board) +{ + struct sun4d_handler_data *handler_data; + unsigned int irq; + + irq = irq_alloc(real_irq, pil); + if (irq == 0) { + prom_printf("IRQ: allocate for %d %d %d failed\n", + real_irq, pil, board); + goto err_out; + } + + handler_data = irq_get_handler_data(irq); + if (unlikely(handler_data)) + goto err_out; + + handler_data = kzalloc(sizeof(struct sun4d_handler_data), GFP_ATOMIC); + if (unlikely(!handler_data)) { + prom_printf("IRQ: kzalloc(sun4d_handler_data) failed.\n"); + prom_halt(); + } + handler_data->cpuid = board_to_cpu[board]; + handler_data->real_irq = real_irq; + irq_set_chip_and_handler_name(irq, &sun4d_irq, + handle_level_irq, "level"); + irq_set_handler_data(irq, handler_data); + +err_out: + return irq; +} + + + unsigned int sun4d_build_device_irq(struct platform_device *op, unsigned int real_irq) { struct device_node *dp = op->dev.of_node; struct device_node *io_unit, *sbi = dp->parent; const struct linux_prom_registers *regs; - struct sun4d_handler_data *handler_data; unsigned int pil; unsigned int irq; int board, slot; int sbusl; - irq = 0; + irq = real_irq; while (sbi) { if (!strcmp(sbi->name, "sbi")) break; @@ -348,29 +382,17 @@ unsigned int sun4d_build_device_irq(struct platform_device *op, else pil = real_irq; - irq = irq_alloc(real_irq, pil); - if (irq == 0) - goto err_out; - - handler_data = irq_get_handler_data(irq); - if (unlikely(handler_data)) - goto err_out; - - handler_data = kzalloc(sizeof(struct sun4d_handler_data), GFP_ATOMIC); - if (unlikely(!handler_data)) { - prom_printf("IRQ: kzalloc(sun4d_handler_data) failed.\n"); - prom_halt(); - } - handler_data->cpuid = board_to_cpu[board]; - handler_data->real_irq = real_irq; - irq_set_chip_and_handler_name(irq, &sun4d_irq, - handle_level_irq, "level"); - irq_set_handler_data(irq, handler_data); - + irq = _sun4d_build_device_irq(real_irq, pil, board); err_out: - return real_irq; + return irq; } +unsigned int sun4d_build_timer_irq(unsigned int board, unsigned int real_irq) +{ + return _sun4d_build_device_irq(real_irq, real_irq, board); +} + + static void __init sun4d_fixup_trap_table(void) { #ifdef CONFIG_SMP @@ -402,6 +424,7 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) unsigned int irq; const u32 *reg; int err; + int board; dp = of_find_node_by_name(NULL, "cpu-unit"); if (!dp) { @@ -414,12 +437,19 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) * bootbus. */ reg = of_get_property(dp, "reg", NULL); - of_node_put(dp); if (!reg) { prom_printf("sun4d_init_timers: No reg property\n"); prom_halt(); } + board = of_getintprop_default(dp, "board#", -1); + if (board == -1) { + prom_printf("sun4d_init_timers: No board# property on cpu-unit\n"); + prom_halt(); + } + + of_node_put(dp); + res.start = reg[1]; res.end = reg[2] - 1; res.flags = reg[0] & 0xff; @@ -434,7 +464,7 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) master_l10_counter = &sun4d_timers->l10_cur_count; - irq = sun4d_build_device_irq(NULL, SUN4D_TIMER_IRQ); + irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ); err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); if (err) { prom_printf("sun4d_init_timers: request_irq() failed with %d\n", From ea160584574e345495e75ee4a7d3a7dbcad9e16c Mon Sep 17 00:00:00 2001 From: oftedal Date: Wed, 1 Jun 2011 11:04:20 +0000 Subject: [PATCH 185/595] Do not skip interrupt sources in sun4d interrupt handler and acknowledge interrupts correctly During the introduction of genirq on sparc32 bugs were introduced in the interrupt handler for sun4d. The interrupts handler checks the status of the various sbus interfaces in the system and generates a virtual interrupt, based upon the location of the interrupt source. This lookup was broken by restructuring the code in such a way that index and shift operations were performed prior to comparing this against the values read from the interrupt controllers. This could cause the handler to loop eternally as the interrupt source could be skipped before any check was performed. Additionally sun4d_encode_irq performs shifting internally, so it should not be performed twice. In sun4d_unmask interrupts were not correctly acknowledged, as the corresponding bit it the interrupt mask was not actually cleared. Signed-off-by: Kjetil Oftedal Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4d_irq.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 487c1bb374f5..eaec8a90fb9f 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -103,10 +103,9 @@ static void sun4d_sbus_handler_irq(int sbusl) sbil = (sbusl << 2); /* Loop for each pending SBI */ - for (sbino = 0; bus_mask; sbino++) { + for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1) { unsigned int idx, mask; - bus_mask >>= 1; if (!(bus_mask & 1)) continue; /* XXX This seems to ACK the irq twice. acquire_sbi() @@ -118,19 +117,16 @@ static void sun4d_sbus_handler_irq(int sbusl) mask &= (0xf << sbil); /* Loop for each pending SBI slot */ - idx = 0; slot = (1 << sbil); - while (mask != 0) { + for (idx = 0; mask != 0; idx++, slot <<= 1) { unsigned int pil; struct irq_bucket *p; - idx++; - slot <<= 1; if (!(mask & slot)) continue; mask &= ~slot; - pil = sun4d_encode_irq(sbino, sbil, idx); + pil = sun4d_encode_irq(sbino, sbusl, idx); p = irq_map[pil]; while (p) { @@ -218,10 +214,10 @@ static void sun4d_unmask_irq(struct irq_data *data) #ifdef CONFIG_SMP spin_lock_irqsave(&sun4d_imsk_lock, flags); - cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) | ~(1 << real_irq)); + cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) & ~(1 << real_irq)); spin_unlock_irqrestore(&sun4d_imsk_lock, flags); #else - cc_set_imsk(cc_get_imsk() | ~(1 << real_irq)); + cc_set_imsk(cc_get_imsk() & ~(1 << real_irq)); #endif } From 9eeb08986f41c0740306f6f56cf04e619e2fe525 Mon Sep 17 00:00:00 2001 From: oftedal Date: Wed, 1 Jun 2011 11:11:41 +0000 Subject: [PATCH 186/595] Add support for allocating irqs for bootbus devices Some devices that can generate interrupts are connected directly to the CPU through the bootbus on sun4d. This patch allows IRQs to be allocated for such devices. The information used for allocating interrupts for sbus devices are present at the corresponding SBI node. For bootbus devices this information is present in the bootbus node. Signed-off-by: Kjetil Oftedal Signed-off-by: David S. Miller --- arch/sparc/kernel/sun4d_irq.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index eaec8a90fb9f..1d13c5bda0b1 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -334,7 +334,8 @@ unsigned int sun4d_build_device_irq(struct platform_device *op, unsigned int real_irq) { struct device_node *dp = op->dev.of_node; - struct device_node *io_unit, *sbi = dp->parent; + struct device_node *board_parent, *bus = dp->parent; + char *bus_connection; const struct linux_prom_registers *regs; unsigned int pil; unsigned int irq; @@ -342,13 +343,20 @@ unsigned int sun4d_build_device_irq(struct platform_device *op, int sbusl; irq = real_irq; - while (sbi) { - if (!strcmp(sbi->name, "sbi")) + while (bus) { + if (!strcmp(bus->name, "sbi")) { + bus_connection = "io-unit"; break; + } + + if (!strcmp(bus->name, "bootbus")) { + bus_connection = "cpu-unit"; + break; + } - sbi = sbi->parent; + bus = bus->parent; } - if (!sbi) + if (!bus) goto err_out; regs = of_get_property(dp, "reg", NULL); @@ -358,17 +366,19 @@ unsigned int sun4d_build_device_irq(struct platform_device *op, slot = regs->which_io; /* - * If SBI's parent is not io-unit or the io-unit lacks - * a "board#" property, something is very wrong. + * If Bus nodes parent is not io-unit/cpu-unit or the io-unit/cpu-unit + * lacks a "board#" property, something is very wrong. */ - if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) { - printk("%s: Error, parent is not io-unit.\n", sbi->full_name); + if (!bus->parent || strcmp(bus->parent->name, bus_connection)) { + printk(KERN_ERR "%s: Error, parent is not %s.\n", + bus->full_name, bus_connection); goto err_out; } - io_unit = sbi->parent; - board = of_getintprop_default(io_unit, "board#", -1); + board_parent = bus->parent; + board = of_getintprop_default(board_parent, "board#", -1); if (board == -1) { - printk("%s: Error, lacks board# property.\n", io_unit->full_name); + printk(KERN_ERR "%s: Error, lacks board# property.\n", + board_parent->full_name); goto err_out; } From 6cb79b3f3ba2b14590cac02ee13ab7410b6225ed Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 3 Jun 2011 14:45:23 +0000 Subject: [PATCH 187/595] sparc: Remove unnecessary semicolons Semicolons are not necessary after switch/while/for/if braces so remove them. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- arch/sparc/include/asm/floppy_32.h | 8 ++++---- arch/sparc/include/asm/floppy_64.h | 4 ++-- arch/sparc/include/asm/system_32.h | 2 +- arch/sparc/include/asm/system_64.h | 2 +- arch/sparc/kernel/apc.c | 2 +- arch/sparc/kernel/auxio_32.c | 2 +- arch/sparc/kernel/chmc.c | 2 +- arch/sparc/kernel/module.c | 2 +- arch/sparc/kernel/pci_common.c | 4 ++-- arch/sparc/kernel/pci_schizo.c | 6 +++--- arch/sparc/kernel/prom_irqtrans.c | 2 +- arch/sparc/kernel/psycho_common.c | 2 +- arch/sparc/kernel/sbus.c | 4 ++-- arch/sparc/kernel/setup_32.c | 2 +- arch/sparc/kernel/setup_64.c | 2 +- arch/sparc/kernel/smp_32.c | 6 +++--- arch/sparc/kernel/sys_sparc32.c | 2 +- arch/sparc/kernel/sys_sparc_64.c | 6 +++--- arch/sparc/kernel/time_64.c | 2 +- arch/sparc/kernel/traps_64.c | 2 +- arch/sparc/kernel/unaligned_64.c | 6 +++--- arch/sparc/kernel/us2e_cpufreq.c | 6 +++--- arch/sparc/kernel/us3_cpufreq.c | 4 ++-- arch/sparc/kernel/viohs.c | 2 +- arch/sparc/kernel/visemul.c | 14 +++++++------- arch/sparc/mm/fault_32.c | 2 +- arch/sparc/mm/init_32.c | 2 +- arch/sparc/mm/init_64.c | 6 +++--- arch/sparc/mm/srmmu.c | 4 ++-- arch/sparc/mm/sun4c.c | 8 ++++---- arch/sparc/mm/tsb.c | 6 +++--- arch/sparc/prom/console_32.c | 2 +- arch/sparc/prom/init_32.c | 2 +- arch/sparc/prom/mp.c | 2 +- 34 files changed, 65 insertions(+), 65 deletions(-) diff --git a/arch/sparc/include/asm/floppy_32.h b/arch/sparc/include/asm/floppy_32.h index 482c79e2a416..7440915e86d8 100644 --- a/arch/sparc/include/asm/floppy_32.h +++ b/arch/sparc/include/asm/floppy_32.h @@ -138,7 +138,7 @@ static unsigned char sun_82072_fd_inb(int port) return sun_fdc->data_82072; case 7: /* FD_DIR */ return sun_read_dir(); - }; + } panic("sun_82072_fd_inb: How did I get here?"); } @@ -161,7 +161,7 @@ static void sun_82072_fd_outb(unsigned char value, int port) case 4: /* FD_STATUS */ sun_fdc->status_82072 = value; break; - }; + } return; } @@ -186,7 +186,7 @@ static unsigned char sun_82077_fd_inb(int port) return sun_fdc->data_82077; case 7: /* FD_DIR */ return sun_read_dir(); - }; + } panic("sun_82077_fd_inb: How did I get here?"); } @@ -212,7 +212,7 @@ static void sun_82077_fd_outb(unsigned char value, int port) case 3: /* FD_TDR */ sun_fdc->tapectl_82077 = value; break; - }; + } return; } diff --git a/arch/sparc/include/asm/floppy_64.h b/arch/sparc/include/asm/floppy_64.h index 6597ce874d78..bcef1f5a2a6d 100644 --- a/arch/sparc/include/asm/floppy_64.h +++ b/arch/sparc/include/asm/floppy_64.h @@ -111,7 +111,7 @@ static unsigned char sun_82077_fd_inb(unsigned long port) case 7: /* FD_DIR */ /* XXX: Is DCL on 0x80 in sun4m? */ return sbus_readb(&sun_fdc->dir_82077); - }; + } panic("sun_82072_fd_inb: How did I get here?"); } @@ -135,7 +135,7 @@ static void sun_82077_fd_outb(unsigned char value, unsigned long port) case 4: /* FD_STATUS */ sbus_writeb(value, &sun_fdc->status_82077); break; - }; + } return; } diff --git a/arch/sparc/include/asm/system_32.h b/arch/sparc/include/asm/system_32.h index 47a7e862474e..aba16092a81b 100644 --- a/arch/sparc/include/asm/system_32.h +++ b/arch/sparc/include/asm/system_32.h @@ -220,7 +220,7 @@ static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int switch (size) { case 4: return xchg_u32(ptr, x); - }; + } __xchg_called_with_bad_pointer(); return x; } diff --git a/arch/sparc/include/asm/system_64.h b/arch/sparc/include/asm/system_64.h index 3c96d3bb9f15..10bcabce97b2 100644 --- a/arch/sparc/include/asm/system_64.h +++ b/arch/sparc/include/asm/system_64.h @@ -234,7 +234,7 @@ static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, return xchg32(ptr, x); case 8: return xchg64(ptr, x); - }; + } __xchg_called_with_bad_pointer(); return x; } diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c index 1e34f29e58bb..caef9deb5866 100644 --- a/arch/sparc/kernel/apc.c +++ b/arch/sparc/kernel/apc.c @@ -123,7 +123,7 @@ static long apc_ioctl(struct file *f, unsigned int cmd, unsigned long __arg) default: return -EINVAL; - }; + } return 0; } diff --git a/arch/sparc/kernel/auxio_32.c b/arch/sparc/kernel/auxio_32.c index 8505e0ac78ba..acf5151f3c1d 100644 --- a/arch/sparc/kernel/auxio_32.c +++ b/arch/sparc/kernel/auxio_32.c @@ -101,7 +101,7 @@ void set_auxio(unsigned char bits_on, unsigned char bits_off) break; default: panic("Can't set AUXIO register on this machine."); - }; + } spin_unlock_irqrestore(&auxio_lock, flags); } EXPORT_SYMBOL(set_auxio); diff --git a/arch/sparc/kernel/chmc.c b/arch/sparc/kernel/chmc.c index 668c7be5d365..5f450260981d 100644 --- a/arch/sparc/kernel/chmc.c +++ b/arch/sparc/kernel/chmc.c @@ -664,7 +664,7 @@ static void chmc_interpret_one_decode_reg(struct chmc *p, int which_bank, u64 va case 0x0: bp->interleave = 16; break; - }; + } /* UK[10] is reserved, and UK[11] is not set for the SDRAM * bank size definition. diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c index 8d348c474a2f..99ba5baa9497 100644 --- a/arch/sparc/kernel/module.c +++ b/arch/sparc/kernel/module.c @@ -214,7 +214,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, me->name, (int) (ELF_R_TYPE(rel[i].r_info) & 0xff)); return -ENOEXEC; - }; + } } return 0; } diff --git a/arch/sparc/kernel/pci_common.c b/arch/sparc/kernel/pci_common.c index 6e3874b64488..a6895987fb70 100644 --- a/arch/sparc/kernel/pci_common.c +++ b/arch/sparc/kernel/pci_common.c @@ -281,7 +281,7 @@ static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, case 4: *value = ret & 0xffffffff; break; - }; + } return PCIBIOS_SUCCESSFUL; @@ -456,7 +456,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) default: break; - }; + } } if (!saw_io || !saw_mem) { diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c index 283fbc329a43..f030b02edddd 100644 --- a/arch/sparc/kernel/pci_schizo.c +++ b/arch/sparc/kernel/pci_schizo.c @@ -264,7 +264,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, default: type_string = "ECC Error"; break; - }; + } printk("%s: IOMMU Error, type[%s]\n", pbm->name, type_string); @@ -319,7 +319,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, default: type_string = "ECC Error"; break; - }; + } printk("%s: IOMMU TAG(%d)[error(%s) ctx(%x) wr(%d) str(%d) " "sz(%dK) vpg(%08lx)]\n", pbm->name, i, type_string, @@ -1328,7 +1328,7 @@ static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, default: chipset_name = "SCHIZO"; break; - }; + } /* For SCHIZO, three OBP regs: * 1) PBM controller regs diff --git a/arch/sparc/kernel/prom_irqtrans.c b/arch/sparc/kernel/prom_irqtrans.c index 570b98f6e897..40e4936bd479 100644 --- a/arch/sparc/kernel/prom_irqtrans.c +++ b/arch/sparc/kernel/prom_irqtrans.c @@ -694,7 +694,7 @@ static unsigned int sbus_of_build_irq(struct device_node *dp, case 3: iclr = reg_base + SYSIO_ICLR_SLOT3; break; - }; + } iclr += ((unsigned long)sbus_level - 1UL) * 8UL; } diff --git a/arch/sparc/kernel/psycho_common.c b/arch/sparc/kernel/psycho_common.c index fe2af66bb198..8db48e808ed4 100644 --- a/arch/sparc/kernel/psycho_common.c +++ b/arch/sparc/kernel/psycho_common.c @@ -228,7 +228,7 @@ void psycho_check_iommu_error(struct pci_pbm_info *pbm, default: type_str = "ECC Error"; break; - }; + } printk(KERN_ERR "%s: IOMMU Error, type[%s]\n", pbm->name, type_str); diff --git a/arch/sparc/kernel/sbus.c b/arch/sparc/kernel/sbus.c index 2ca32d13abcf..a161b9c77f05 100644 --- a/arch/sparc/kernel/sbus.c +++ b/arch/sparc/kernel/sbus.c @@ -97,7 +97,7 @@ void sbus_set_sbus64(struct device *dev, int bursts) default: return; - }; + } val = upa_readq(cfg_reg); if (val & (1UL << 14UL)) { @@ -244,7 +244,7 @@ static unsigned int sbus_build_irq(struct platform_device *op, unsigned int ino) case 3: iclr = reg_base + SYSIO_ICLR_SLOT3; break; - }; + } iclr += ((unsigned long)sbus_level - 1UL) * 8UL; } diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c index 3249d3f3234d..d26e1f6c717a 100644 --- a/arch/sparc/kernel/setup_32.c +++ b/arch/sparc/kernel/setup_32.c @@ -267,7 +267,7 @@ void __init setup_arch(char **cmdline_p) default: printk("UNKNOWN!\n"); break; - }; + } #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index f3b6850cc8db..c4dd0999da86 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -209,7 +209,7 @@ void __init per_cpu_patch(void) default: prom_printf("Unknown cpu type, halting.\n"); prom_halt(); - }; + } *(unsigned int *) (addr + 0) = insns[0]; wmb(); diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index d5b3958be0b4..21b125341bf7 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c @@ -114,7 +114,7 @@ void __init smp_cpus_done(unsigned int max_cpus) printk("UNKNOWN!\n"); BUG(); break; - }; + } } void cpu_panic(void) @@ -374,7 +374,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) printk("UNKNOWN!\n"); BUG(); break; - }; + } } /* Set this up early so that things like the scheduler can init @@ -447,7 +447,7 @@ int __cpuinit __cpu_up(unsigned int cpu) printk("UNKNOWN!\n"); BUG(); break; - }; + } if (!ret) { cpumask_set_cpu(cpu, &smp_commenced_mask); diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index 6db18c6927fb..170cd8e8eb2a 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c @@ -109,7 +109,7 @@ asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compa default: return -ENOSYS; - }; + } return -ENOSYS; } diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 96082d30def0..908b47a5ee24 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -460,7 +460,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second default: err = -ENOSYS; goto out; - }; + } } if (call <= MSGCTL) { switch (call) { @@ -481,7 +481,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second default: err = -ENOSYS; goto out; - }; + } } if (call <= SHMCTL) { switch (call) { @@ -507,7 +507,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second default: err = -ENOSYS; goto out; - }; + } } else { err = -ENOSYS; } diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 2b8d54b2d850..1db6b18964d2 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -708,7 +708,7 @@ static void sparc64_timer_setup(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: WARN_ON(1); break; - }; + } } static struct clock_event_device sparc64_clockevent = { diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index 1ed547bd850f..0cbdaa41cd1e 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c @@ -1804,7 +1804,7 @@ static const char *sun4v_err_type_to_str(u32 type) return "warning resumable"; default: return "unknown"; - }; + } } static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt) diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c index c752c4c479bd..b2b019ea8caa 100644 --- a/arch/sparc/kernel/unaligned_64.c +++ b/arch/sparc/kernel/unaligned_64.c @@ -211,7 +211,7 @@ static inline int do_int_store(int reg_num, int size, unsigned long *dst_addr, default: BUG(); break; - }; + } } return __do_int_store(dst_addr, size, src_val, asi); } @@ -328,7 +328,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) case ASI_SNFL: asi &= ~0x08; break; - }; + } switch (dir) { case load: reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs); @@ -351,7 +351,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) default: BUG(); break; - }; + } *reg_addr = val_in; } break; diff --git a/arch/sparc/kernel/us2e_cpufreq.c b/arch/sparc/kernel/us2e_cpufreq.c index 531d54fc9829..489fc15f3194 100644 --- a/arch/sparc/kernel/us2e_cpufreq.c +++ b/arch/sparc/kernel/us2e_cpufreq.c @@ -176,7 +176,7 @@ static unsigned long index_to_estar_mode(unsigned int index) default: BUG(); - }; + } } static unsigned long index_to_divisor(unsigned int index) @@ -199,7 +199,7 @@ static unsigned long index_to_divisor(unsigned int index) default: BUG(); - }; + } } static unsigned long estar_to_divisor(unsigned long estar) @@ -224,7 +224,7 @@ static unsigned long estar_to_divisor(unsigned long estar) break; default: BUG(); - }; + } return ret; } diff --git a/arch/sparc/kernel/us3_cpufreq.c b/arch/sparc/kernel/us3_cpufreq.c index 9a8ceb700833..eb1624b931d9 100644 --- a/arch/sparc/kernel/us3_cpufreq.c +++ b/arch/sparc/kernel/us3_cpufreq.c @@ -71,7 +71,7 @@ static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg break; default: BUG(); - }; + } return ret; } @@ -125,7 +125,7 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index) default: BUG(); - }; + } reg = read_safari_cfg(); diff --git a/arch/sparc/kernel/viohs.c b/arch/sparc/kernel/viohs.c index aa6ac70d4fd5..29348ea139c3 100644 --- a/arch/sparc/kernel/viohs.c +++ b/arch/sparc/kernel/viohs.c @@ -363,7 +363,7 @@ static int process_ver(struct vio_driver_state *vio, struct vio_ver_info *pkt) default: return handshake_failure(vio); - }; + } } static int process_attr(struct vio_driver_state *vio, void *pkt) diff --git a/arch/sparc/kernel/visemul.c b/arch/sparc/kernel/visemul.c index 9dfd2ebcb157..36357717d691 100644 --- a/arch/sparc/kernel/visemul.c +++ b/arch/sparc/kernel/visemul.c @@ -334,7 +334,7 @@ static void edge(struct pt_regs *regs, unsigned int insn, unsigned int opf) left = edge32_tab_l[(rs1 >> 2) & 0x1].left; right = edge32_tab_l[(rs2 >> 2) & 0x1].right; break; - }; + } if ((rs1 & ~0x7UL) == (rs2 & ~0x7UL)) rd_val = right & left; @@ -360,7 +360,7 @@ static void edge(struct pt_regs *regs, unsigned int insn, unsigned int opf) tstate = regs->tstate & ~(TSTATE_XCC | TSTATE_ICC); regs->tstate = tstate | (ccr << 32UL); } - }; + } } static void array(struct pt_regs *regs, unsigned int insn, unsigned int opf) @@ -392,7 +392,7 @@ static void array(struct pt_regs *regs, unsigned int insn, unsigned int opf) case ARRAY32_OPF: rd_val <<= 2; - }; + } store_reg(regs, rd_val, RD(insn)); } @@ -577,7 +577,7 @@ static void pformat(struct pt_regs *regs, unsigned int insn, unsigned int opf) *fpd_regaddr(f, RD(insn)) = rd_val; break; } - }; + } } static void pmul(struct pt_regs *regs, unsigned int insn, unsigned int opf) @@ -693,7 +693,7 @@ static void pmul(struct pt_regs *regs, unsigned int insn, unsigned int opf) *fpd_regaddr(f, RD(insn)) = rd_val; break; } - }; + } } static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf) @@ -786,7 +786,7 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf) rd_val |= 1 << i; } break; - }; + } maybe_flush_windows(0, 0, RD(insn), 0); store_reg(regs, rd_val, RD(insn)); @@ -885,7 +885,7 @@ int vis_emul(struct pt_regs *regs, unsigned int insn) case BSHUFFLE_OPF: bshuffle(regs, insn); break; - }; + } regs->tpc = regs->tnpc; regs->tnpc += 4; diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c index b10ac4d62378..7543ddbdadb2 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c @@ -135,7 +135,7 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, default: break; - }; + } memset(®s, 0, sizeof (regs)); regs.pc = pc; diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c index ca217327e8d2..7b00de61c5f1 100644 --- a/arch/sparc/mm/init_32.c +++ b/arch/sparc/mm/init_32.c @@ -340,7 +340,7 @@ void __init paging_init(void) prom_printf("paging_init: sparc_cpu_model = %d\n", sparc_cpu_model); prom_printf("paging_init: Halting...\n"); prom_halt(); - }; + } /* Initialize the protection map with non-constant, MMU dependent values. */ protection_map[0] = PAGE_NONE; diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index e10cd03fab80..3fd8e18bed80 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -1625,7 +1625,7 @@ static void __init sun4v_ktsb_init(void) ktsb_descr[0].pgsz_idx = HV_PGSZ_IDX_4MB; ktsb_descr[0].pgsz_mask = HV_PGSZ_MASK_4MB; break; - }; + } ktsb_descr[0].assoc = 1; ktsb_descr[0].num_ttes = KERNEL_TSB_NENTRIES; @@ -2266,7 +2266,7 @@ unsigned long pte_sz_bits(unsigned long sz) return _PAGE_SZ512K_4V; case 4 * 1024 * 1024: return _PAGE_SZ4MB_4V; - }; + } } else { switch (sz) { case 8 * 1024: @@ -2278,7 +2278,7 @@ unsigned long pte_sz_bits(unsigned long sz) return _PAGE_SZ512K_4U; case 4 * 1024 * 1024: return _PAGE_SZ4MB_4U; - }; + } } } diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index fe09fd8be695..cbef74e793b8 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -1665,7 +1665,7 @@ static void __init init_swift(void) default: srmmu_modtype = Swift_ok; break; - }; + } BTFIXUPSET_CALL(flush_cache_all, swift_flush_cache_all, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_cache_mm, swift_flush_cache_mm, BTFIXUPCALL_NORM); @@ -2069,7 +2069,7 @@ static void __init get_srmmu_type(void) /* Some other Cypress revision, assume a 605. */ init_cypress_605(mod_rev); break; - }; + } return; } diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index a2350b5e68aa..1cf4f198709a 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -318,7 +318,7 @@ void __init sun4c_probe_vac(void) prom_printf("probe_vac: Didn't expect vac-linesize of %d, halting\n", sun4c_vacinfo.linesize); prom_halt(); - }; + } sun4c_flush_all(); sun4c_enable_vac(); @@ -364,7 +364,7 @@ static void __init patch_kernel_fault_handler(void) prom_printf("Unhandled number of segmaps: %d\n", num_segmaps); prom_halt(); - }; + } switch (num_contexts) { case 8: /* Default, nothing to do. */ @@ -377,7 +377,7 @@ static void __init patch_kernel_fault_handler(void) prom_printf("Unhandled number of contexts: %d\n", num_contexts); prom_halt(); - }; + } if (sun4c_vacinfo.do_hwflushes != 0) { PATCH_INSN(vac_hwflush_patch1_on, vac_hwflush_patch1); @@ -394,7 +394,7 @@ static void __init patch_kernel_fault_handler(void) prom_printf("Impossible VAC linesize %d, halting...\n", sun4c_vacinfo.linesize); prom_halt(); - }; + } } } diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c index 948461513499..a5f51b22fcbe 100644 --- a/arch/sparc/mm/tsb.c +++ b/arch/sparc/mm/tsb.c @@ -180,7 +180,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign printk(KERN_ERR "TSB[%s:%d]: Impossible TSB size %lu, killing process.\n", current->comm, current->pid, tsb_bytes); do_exit(SIGSEGV); - }; + } tte |= pte_sz_bits(page_sz); if (tlb_type == cheetah_plus || tlb_type == hypervisor) { @@ -215,7 +215,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign #endif default: BUG(); - }; + } hp->assoc = 1; hp->num_ttes = tsb_bytes / 16; hp->ctx_idx = 0; @@ -230,7 +230,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign #endif default: BUG(); - }; + } hp->tsb_base = tsb_paddr; hp->resv = 0; } diff --git a/arch/sparc/prom/console_32.c b/arch/sparc/prom/console_32.c index b05e3db5fa63..a00f47b16c10 100644 --- a/arch/sparc/prom/console_32.c +++ b/arch/sparc/prom/console_32.c @@ -38,7 +38,7 @@ static int prom_nbputchar(const char *buf) break; default: break; - }; + } restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return i; /* Ugh, we could spin forever on unsupported proms ;( */ diff --git a/arch/sparc/prom/init_32.c b/arch/sparc/prom/init_32.c index 0a601b300639..26c64cea3c9c 100644 --- a/arch/sparc/prom/init_32.c +++ b/arch/sparc/prom/init_32.c @@ -53,7 +53,7 @@ void __init prom_init(struct linux_romvec *rp) romvec->pv_romvers); prom_halt(); break; - }; + } prom_rev = romvec->pv_plugin_revision; prom_prev = romvec->pv_printrev; diff --git a/arch/sparc/prom/mp.c b/arch/sparc/prom/mp.c index 97c44c9ddbc8..0da8256cf76f 100644 --- a/arch/sparc/prom/mp.c +++ b/arch/sparc/prom/mp.c @@ -35,7 +35,7 @@ prom_startcpu(int cpunode, struct linux_prom_registers *ctable_reg, int ctx, cha case PROM_V3: ret = (*(romvec->v3_cpustart))(cpunode, (int) ctable_reg, ctx, pc); break; - }; + } restore_current(); spin_unlock_irqrestore(&prom_lock, flags); From e756682c8baa47da1648c0c016e9f48ed66bc32d Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Sun, 5 Jun 2011 20:46:03 +0000 Subject: [PATCH 188/595] xfrm: Fix off by one in the replay advance functions We may write 4 byte too much when we reinitialize the anti replay window in the replay advance functions. This patch fixes this by adjusting the last index of the initialization loop. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- net/xfrm/xfrm_replay.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 47f1b8638df9..b11ea692bd7d 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c @@ -265,7 +265,7 @@ static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq) bitnr = bitnr & 0x1F; replay_esn->bmp[nr] |= (1U << bitnr); } else { - nr = replay_esn->replay_window >> 5; + nr = (replay_esn->replay_window - 1) >> 5; for (i = 0; i <= nr; i++) replay_esn->bmp[i] = 0; @@ -471,7 +471,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) bitnr = bitnr & 0x1F; replay_esn->bmp[nr] |= (1U << bitnr); } else { - nr = replay_esn->replay_window >> 5; + nr = (replay_esn->replay_window - 1) >> 5; for (i = 0; i <= nr; i++) replay_esn->bmp[i] = 0; From 70b666c3b4cb2b96098d80e6f515e4bc6d37db5a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 27 May 2011 09:24:26 -0700 Subject: [PATCH 189/595] ceph: use ihold when we already have an inode ref We should use ihold whenever we already have a stable inode ref, even when we aren't holding i_lock. This avoids adding new and unnecessary locking dependencies. Signed-off-by: Sage Weil --- fs/ceph/addr.c | 2 +- fs/ceph/caps.c | 10 ++++------ fs/ceph/dir.c | 11 +++++++---- fs/ceph/export.c | 4 ++-- fs/ceph/file.c | 3 ++- fs/ceph/inode.c | 18 ++++++++++-------- fs/ceph/ioctl.c | 6 ++++-- fs/ceph/locks.c | 3 ++- fs/ceph/snap.c | 2 +- fs/ceph/xattr.c | 6 ++++-- 10 files changed, 37 insertions(+), 28 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 33da49dc3cc6..5a3953db8118 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -453,7 +453,7 @@ static int ceph_writepage(struct page *page, struct writeback_control *wbc) int err; struct inode *inode = page->mapping->host; BUG_ON(!inode); - igrab(inode); + ihold(inode); err = writepage_nounlock(page, wbc); unlock_page(page); iput(inode); diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 1f72b00447c4..f605753c8fe9 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -2940,14 +2940,12 @@ void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc) while (!list_empty(&mdsc->cap_dirty)) { ci = list_first_entry(&mdsc->cap_dirty, struct ceph_inode_info, i_dirty_item); - inode = igrab(&ci->vfs_inode); + inode = &ci->vfs_inode; + ihold(inode); dout("flush_dirty_caps %p\n", inode); spin_unlock(&mdsc->cap_dirty_lock); - if (inode) { - ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_FLUSH, - NULL); - iput(inode); - } + ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_FLUSH, NULL); + iput(inode); spin_lock(&mdsc->cap_dirty_lock); } spin_unlock(&mdsc->cap_dirty_lock); diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 33729e822bb9..ef8f08c343e8 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -308,7 +308,8 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS); if (IS_ERR(req)) return PTR_ERR(req); - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_dentry = dget(filp->f_dentry); /* hints to request -> mds selection code */ req->r_direct_mode = USE_AUTH_MDS; @@ -787,10 +788,12 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir, req->r_dentry_drop = CEPH_CAP_FILE_SHARED; req->r_dentry_unless = CEPH_CAP_FILE_EXCL; err = ceph_mdsc_do_request(mdsc, dir, req); - if (err) + if (err) { d_drop(dentry); - else if (!req->r_reply_info.head->is_dentry) - d_instantiate(dentry, igrab(old_dentry->d_inode)); + } else if (!req->r_reply_info.head->is_dentry) { + ihold(old_dentry->d_inode); + d_instantiate(dentry, old_dentry->d_inode); + } ceph_mdsc_put_request(req); return err; } diff --git a/fs/ceph/export.c b/fs/ceph/export.c index a610d3d67488..f67b687550de 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -109,7 +109,7 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, err = ceph_mdsc_do_request(mdsc, NULL, req); inode = req->r_target_inode; if (inode) - igrab(inode); + ihold(inode); ceph_mdsc_put_request(req); if (!inode) return ERR_PTR(-ESTALE); @@ -167,7 +167,7 @@ static struct dentry *__cfh_to_dentry(struct super_block *sb, err = ceph_mdsc_do_request(mdsc, NULL, req); inode = req->r_target_inode; if (inode) - igrab(inode); + ihold(inode); ceph_mdsc_put_request(req); if (!inode) return ERR_PTR(err ? err : -ESTALE); diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 203252d88d9f..8c5ac4e72832 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -191,7 +191,8 @@ int ceph_open(struct inode *inode, struct file *file) err = PTR_ERR(req); goto out; } - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_num_caps = 1; err = ceph_mdsc_do_request(mdsc, parent_inode, req); if (!err) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 70b6a4839c38..d8858e96ab18 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1101,10 +1101,10 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, goto done; } req->r_dentry = dn; /* may have spliced */ - igrab(in); + ihold(in); } else if (ceph_ino(in) == vino.ino && ceph_snap(in) == vino.snap) { - igrab(in); + ihold(in); } else { dout(" %p links to %p %llx.%llx, not %llx.%llx\n", dn, in, ceph_ino(in), ceph_snap(in), @@ -1144,7 +1144,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, goto done; } req->r_dentry = dn; /* may have spliced */ - igrab(in); + ihold(in); rinfo->head->is_dentry = 1; /* fool notrace handlers */ } @@ -1328,7 +1328,7 @@ void ceph_queue_writeback(struct inode *inode) if (queue_work(ceph_inode_to_client(inode)->wb_wq, &ceph_inode(inode)->i_wb_work)) { dout("ceph_queue_writeback %p\n", inode); - igrab(inode); + ihold(inode); } else { dout("ceph_queue_writeback %p failed\n", inode); } @@ -1353,7 +1353,7 @@ void ceph_queue_invalidate(struct inode *inode) if (queue_work(ceph_inode_to_client(inode)->pg_inv_wq, &ceph_inode(inode)->i_pg_inv_work)) { dout("ceph_queue_invalidate %p\n", inode); - igrab(inode); + ihold(inode); } else { dout("ceph_queue_invalidate %p failed\n", inode); } @@ -1477,7 +1477,7 @@ void ceph_queue_vmtruncate(struct inode *inode) if (queue_work(ceph_sb_to_client(inode->i_sb)->trunc_wq, &ci->i_vmtruncate_work)) { dout("ceph_queue_vmtruncate %p\n", inode); - igrab(inode); + ihold(inode); } else { dout("ceph_queue_vmtruncate %p failed, pending=%d\n", inode, ci->i_truncate_pending); @@ -1738,7 +1738,8 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) __mark_inode_dirty(inode, inode_dirty_flags); if (mask) { - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_inode_drop = release; req->r_args.setattr.mask = cpu_to_le32(mask); req->r_num_caps = 1; @@ -1779,7 +1780,8 @@ int ceph_do_getattr(struct inode *inode, int mask) req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS); if (IS_ERR(req)) return PTR_ERR(req); - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_num_caps = 1; req->r_args.getattr.mask = cpu_to_le32(mask); err = ceph_mdsc_do_request(mdsc, NULL, req); diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c index 8888c9ba68db..ef0b5f48e13a 100644 --- a/fs/ceph/ioctl.c +++ b/fs/ceph/ioctl.c @@ -73,7 +73,8 @@ static long ceph_ioctl_set_layout(struct file *file, void __user *arg) USE_AUTH_MDS); if (IS_ERR(req)) return PTR_ERR(req); - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_inode_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_EXCL; req->r_args.setlayout.layout.fl_stripe_unit = @@ -135,7 +136,8 @@ static long ceph_ioctl_set_layout_policy (struct file *file, void __user *arg) if (IS_ERR(req)) return PTR_ERR(req); - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_args.setlayout.layout.fl_stripe_unit = cpu_to_le32(l.stripe_unit); diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c index 476b329867d4..7f0f72c53f7e 100644 --- a/fs/ceph/locks.c +++ b/fs/ceph/locks.c @@ -23,7 +23,8 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS); if (IS_ERR(req)) return PTR_ERR(req); - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); /* mds requires start and length rather than start and end */ if (LLONG_MAX == fl->fl_end) diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index 24067d68a554..54b14de2e729 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c @@ -722,7 +722,7 @@ static void flush_snaps(struct ceph_mds_client *mdsc) ci = list_first_entry(&mdsc->snap_flush_list, struct ceph_inode_info, i_snap_flush_item); inode = &ci->vfs_inode; - igrab(inode); + ihold(inode); spin_unlock(&mdsc->snap_flush_lock); spin_lock(&inode->i_lock); __ceph_flush_snaps(ci, &session, 0); diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index f2b628696180..f42d730f1b66 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -665,7 +665,8 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name, err = PTR_ERR(req); goto out; } - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_inode_drop = CEPH_CAP_XATTR_SHARED; req->r_num_caps = 1; req->r_args.setxattr.flags = cpu_to_le32(flags); @@ -795,7 +796,8 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name) USE_AUTH_MDS); if (IS_ERR(req)) return PTR_ERR(req); - req->r_inode = igrab(inode); + req->r_inode = inode; + ihold(inode); req->r_inode_drop = CEPH_CAP_XATTR_SHARED; req->r_num_caps = 1; req->r_path2 = kstrdup(name, GFP_NOFS); From 2584547230ae49b8de91ab3bb5e0a81898905b45 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 3 Jun 2011 09:37:09 -0700 Subject: [PATCH 190/595] ceph: fix sync vs canceled write If we cancel a write, trigger the safe completions to prevent a sync from blocking indefinitely in ceph_osdc_sync(). Signed-off-by: Sage Weil --- net/ceph/osd_client.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 6ea2b892f44b..9cb627a4073a 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -1144,6 +1144,13 @@ static void handle_osds_timeout(struct work_struct *work) round_jiffies_relative(delay)); } +static void complete_request(struct ceph_osd_request *req) +{ + if (req->r_safe_callback) + req->r_safe_callback(req, NULL); + complete_all(&req->r_safe_completion); /* fsync waiter */ +} + /* * handle osd op reply. either call the callback if it is specified, * or do the completion to wake up the waiting thread. @@ -1226,11 +1233,8 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, else complete_all(&req->r_completion); - if (flags & CEPH_OSD_FLAG_ONDISK) { - if (req->r_safe_callback) - req->r_safe_callback(req, msg); - complete_all(&req->r_safe_completion); /* fsync waiter */ - } + if (flags & CEPH_OSD_FLAG_ONDISK) + complete_request(req); done: dout("req=%p req->r_linger=%d\n", req, req->r_linger); @@ -1732,6 +1736,7 @@ int ceph_osdc_wait_request(struct ceph_osd_client *osdc, __cancel_request(req); __unregister_request(osdc, req); mutex_unlock(&osdc->request_mutex); + complete_request(req); dout("wait_request tid %llu canceled/timed out\n", req->r_tid); return rc; } From c3cd62839aaa2cdb2b99687c9e44f1b300a4aece Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 1 Jun 2011 16:08:44 -0700 Subject: [PATCH 191/595] ceph: fix short sync reads from the OSD If we get a short read from the OSD because the object is small, we need to zero the remainder of the buffer. For O_DIRECT reads, the attempted range is not trimmed to i_size by the VFS, so we were actually looping indefinitely. Fix by trimming by i_size, and the unconditionally zeroing the trailing range. Reported-by: Jeff Wu Signed-off-by: Sage Weil --- fs/ceph/file.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 8c5ac4e72832..b654f403139e 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -283,7 +283,7 @@ int ceph_release(struct inode *inode, struct file *file) static int striped_read(struct inode *inode, u64 off, u64 len, struct page **pages, int num_pages, - int *checkeof, bool align_to_pages, + int *checkeof, bool o_direct, unsigned long buf_align) { struct ceph_fs_client *fsc = ceph_inode_to_client(inode); @@ -308,7 +308,7 @@ static int striped_read(struct inode *inode, io_align = off & ~PAGE_MASK; more: - if (align_to_pages) + if (o_direct) page_align = (pos - io_align + buf_align) & ~PAGE_MASK; else page_align = pos & ~PAGE_MASK; @@ -346,20 +346,22 @@ static int striped_read(struct inode *inode, } if (was_short) { - /* was original extent fully inside i_size? */ - if (pos + left <= inode->i_size) { - dout("zero tail\n"); - ceph_zero_page_vector_range(page_off + read, len - read, + /* did we bounce off eof? */ + if (pos + left > inode->i_size) + *checkeof = 1; + + /* zero trailing bytes (inside i_size) */ + if (left > 0 && pos < inode->i_size) { + if (pos + left > inode->i_size) + left = inode->i_size - pos; + + dout("zero tail %d\n", left); + ceph_zero_page_vector_range(page_off + read, left, pages); - read = len; - goto out; + read += left; } - - /* check i_size */ - *checkeof = 1; } -out: if (ret >= 0) ret = read; dout("striped_read returns %d\n", ret); @@ -659,7 +661,7 @@ static ssize_t ceph_aio_read(struct kiocb *iocb, const struct iovec *iov, /* hit EOF or hole? */ if (statret == 0 && *ppos < inode->i_size) { - dout("aio_read sync_read hit hole, reading more\n"); + dout("aio_read sync_read hit hole, ppos %lld < size %lld, reading more\n", *ppos, inode->i_size); read += ret; base += ret; len -= ret; From 0e98728fa32d338907631349a8cc2afa07c0cb9a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 7 Jun 2011 20:40:35 -0700 Subject: [PATCH 192/595] ceph: fix ENOENT logic in striped_read Getting ENOENT is equivalent to reading 0 bytes. Make that correction before setting up the hit_stripe and was_short flags. Fixes the following case: dd if=/dev/zero of=/mnt/fs_depot/dd3 bs=1 seek=1048576 count=0 dd if=/mnt/fs_depot/dd3 of=/root/ddout1 skip=8 bs=500 count=2 iflag=direct Reported-by: Henry C Chang Signed-off-by: Sage Weil --- fs/ceph/file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index b654f403139e..9542f07d0b93 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -318,10 +318,10 @@ static int striped_read(struct inode *inode, ci->i_truncate_seq, ci->i_truncate_size, page_pos, pages_left, page_align); - hit_stripe = this_len < left; - was_short = ret >= 0 && ret < this_len; if (ret == -ENOENT) ret = 0; + hit_stripe = this_len < left; + was_short = ret >= 0 && ret < this_len; dout("striped_read %llu~%u (read %u) got %d%s%s\n", pos, left, read, ret, hit_stripe ? " HITSTRIPE" : "", was_short ? " SHORT" : ""); From 0c1f91f27140cf3b6e38dc4e892adac241c73a20 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 25 May 2011 14:56:12 -0700 Subject: [PATCH 193/595] ceph: unwind canceled flock state If we request a lock and then abort (e.g., ^C), we need to send a matching unlock request to the MDS to unwind our lock attempt to avoid indefinitely blocking other clients. Reported-by: Brian Chrisman Signed-off-by: Sage Weil --- fs/ceph/locks.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c index 7f0f72c53f7e..80576d05d687 100644 --- a/fs/ceph/locks.c +++ b/fs/ceph/locks.c @@ -33,11 +33,10 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, length = fl->fl_end - fl->fl_start + 1; dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, " - "length: %llu, wait: %d, type`: %d", (int)lock_type, + "length: %llu, wait: %d, type: %d", (int)lock_type, (int)operation, (u64)fl->fl_pid, fl->fl_start, length, wait, fl->fl_type); - req->r_args.filelock_change.rule = lock_type; req->r_args.filelock_change.type = cmd; req->r_args.filelock_change.pid = cpu_to_le64((u64)fl->fl_pid); @@ -71,7 +70,7 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, } ceph_mdsc_put_request(req); dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, " - "length: %llu, wait: %d, type`: %d, err code %d", (int)lock_type, + "length: %llu, wait: %d, type: %d, err code %d", (int)lock_type, (int)operation, (u64)fl->fl_pid, fl->fl_start, length, wait, fl->fl_type, err); return err; @@ -110,16 +109,20 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl) dout("mds locked, locking locally"); err = posix_lock_file(file, fl, NULL); if (err && (CEPH_MDS_OP_SETFILELOCK == op)) { - /* undo! This should only happen if the kernel detects - * local deadlock. */ + /* undo! This should only happen if + * the kernel detects local + * deadlock. */ ceph_lock_message(CEPH_LOCK_FCNTL, op, file, CEPH_LOCK_UNLOCK, 0, fl); - dout("got %d on posix_lock_file, undid lock", err); + dout("got %d on posix_lock_file, undid lock", + err); } } - } else { - dout("mds returned error code %d", err); + } else if (err == -ERESTARTSYS) { + dout("undoing lock\n"); + ceph_lock_message(CEPH_LOCK_FCNTL, op, file, + CEPH_LOCK_UNLOCK, 0, fl); } return err; } @@ -156,8 +159,11 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl) file, CEPH_LOCK_UNLOCK, 0, fl); dout("got %d on flock_lock_file_wait, undid lock", err); } - } else { - dout("mds error code %d", err); + } else if (err == -ERESTARTSYS) { + dout("undoing lock\n"); + ceph_lock_message(CEPH_LOCK_FLOCK, + CEPH_MDS_OP_SETFILELOCK, + file, CEPH_LOCK_UNLOCK, 0, fl); } return err; } From 629acb6abac0ef217ee579e14084af2ce7381dbc Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Wed, 8 Jun 2011 15:10:08 +1000 Subject: [PATCH 194/595] MD: no integrity register if no gendisk Don't attempt md_integrity_register if there is no gendisk struct available. When MD arrays are built via device-mapper, the gendisk structure is not available via mddev. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- 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 aa640a85bb21..4ea02c634d33 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1781,8 +1781,8 @@ int md_integrity_register(mddev_t *mddev) if (list_empty(&mddev->disks)) return 0; /* nothing to do */ - if (blk_get_integrity(mddev->gendisk)) - return 0; /* already registered */ + if (!mddev->gendisk || blk_get_integrity(mddev->gendisk)) + return 0; /* shouldn't register, or already is */ list_for_each_entry(rdev, &mddev->disks, same_set) { /* skip spares and non-functional disks */ if (test_bit(Faulty, &rdev->flags)) From 68866e425be2ef2664aa5c691bb3ab789736acf5 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Wed, 8 Jun 2011 15:10:08 +1000 Subject: [PATCH 195/595] MD: no sync IO while suspended Disallow resync I/O while the RAID array is suspended. Recovery, resync, and metadata I/O should not be allowed while a device is suspended. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/md.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 4ea02c634d33..4fa915a21d0d 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7045,7 +7045,6 @@ void md_do_sync(mddev_t *mddev) } EXPORT_SYMBOL_GPL(md_do_sync); - static int remove_and_add_spares(mddev_t *mddev) { mdk_rdev_t *rdev; @@ -7157,6 +7156,9 @@ static void reap_sync_thread(mddev_t *mddev) */ void md_check_recovery(mddev_t *mddev) { + if (mddev->suspended) + return; + if (mddev->bitmap) bitmap_daemon_work(mddev); From ac42450c7c814769bee963ae4b897c149bb0ab53 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 7 Jun 2011 17:48:35 -0500 Subject: [PATCH 196/595] MD: possible typo Make message a bit clearer by s/blocks/k/ I chose 'k' vs 'kiB' or 'kB' because it is what is used earlier in the message. 'k' may be a bit ambigous, but I think it's better than "blocks" which normally means 512, but means 1024 in MD. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- 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 4fa915a21d0d..3715e89dcaae 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -6866,8 +6866,8 @@ void md_do_sync(mddev_t *mddev) * Tune reconstruction: */ window = 32*(PAGE_SIZE/512); - printk(KERN_INFO "md: using %dk window, over a total of %llu blocks.\n", - window/2,(unsigned long long) max_sectors/2); + printk(KERN_INFO "md: using %dk window, over a total of %lluk.\n", + window/2, (unsigned long long)max_sectors/2); atomic_set(&mddev->recovery_active, 0); last_check = 0; From 0fd018af37dadbb7826850883ad8abfecdb1a00b Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 7 Jun 2011 17:49:36 -0500 Subject: [PATCH 197/595] MD: move thread wakeups into resume Move personality and sync/recovery thread starting outside md_run. Moving the wakeup's of the personality and sync/recovery threads out of md_run and into do_md_run and mddev_resume solves two issues: 1) It allows bitmap_load to be called before the sync_thread is run and 2) when MD personalities are used by device-mapper (dm-raid.c), the start-up of the array is better alligned with device-mapper primatives (CTR/resume/suspend/DTR). I/O - in this case, recovery operations - should not happen until after a resume has taken place. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/md.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 3715e89dcaae..d5385188c445 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -351,6 +351,9 @@ void mddev_resume(mddev_t *mddev) mddev->suspended = 0; wake_up(&mddev->sb_wait); mddev->pers->quiesce(mddev, 0); + + md_wakeup_thread(mddev->thread); + md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ } EXPORT_SYMBOL_GPL(mddev_resume); @@ -4619,9 +4622,6 @@ int md_run(mddev_t *mddev) if (mddev->flags) md_update_sb(mddev, 0); - md_wakeup_thread(mddev->thread); - md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ - md_new_event(mddev); sysfs_notify_dirent_safe(mddev->sysfs_state); sysfs_notify_dirent_safe(mddev->sysfs_action); @@ -4642,6 +4642,10 @@ static int do_md_run(mddev_t *mddev) bitmap_destroy(mddev); goto out; } + + md_wakeup_thread(mddev->thread); + md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ + set_capacity(mddev->gendisk, mddev->array_sectors); revalidate_disk(mddev->gendisk); mddev->changed = 1; From 1ed7242e591af7e233234d483f12d33818b189d9 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 7 Jun 2011 17:50:35 -0500 Subject: [PATCH 198/595] MD: raid1 changes to allow use by device mapper MD RAID1: Changes to allow RAID1 to be used by device-mapper (dm-raid.c) Added the necessary congestion function and conditionalize calls requiring an array 'queue' or 'gendisk'. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/raid1.c | 24 +++++++++++++++++------- drivers/md/raid1.h | 2 ++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 5d096096f958..f7431b6d8447 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -497,21 +497,19 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) return best_disk; } -static int raid1_congested(void *data, int bits) +int md_raid1_congested(mddev_t *mddev, int bits) { - mddev_t *mddev = data; conf_t *conf = mddev->private; int i, ret = 0; - if (mddev_congested(mddev, bits)) - return 1; - rcu_read_lock(); for (i = 0; i < mddev->raid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags)) { struct request_queue *q = bdev_get_queue(rdev->bdev); + BUG_ON(!q); + /* Note the '|| 1' - when read_balance prefers * non-congested targets, it can be removed */ @@ -524,7 +522,15 @@ static int raid1_congested(void *data, int bits) rcu_read_unlock(); return ret; } +EXPORT_SYMBOL_GPL(md_raid1_congested); +static int raid1_congested(void *data, int bits) +{ + mddev_t *mddev = data; + + return mddev_congested(mddev, bits) || + md_raid1_congested(mddev, bits); +} static void flush_pending_writes(conf_t *conf) { @@ -1972,6 +1978,8 @@ static int run(mddev_t *mddev) return PTR_ERR(conf); list_for_each_entry(rdev, &mddev->disks, same_set) { + if (!mddev->gendisk) + continue; disk_stack_limits(mddev->gendisk, rdev->bdev, rdev->data_offset << 9); /* as we don't honour merge_bvec_fn, we must never risk @@ -2013,8 +2021,10 @@ static int run(mddev_t *mddev) md_set_array_sectors(mddev, raid1_size(mddev, 0, 0)); - mddev->queue->backing_dev_info.congested_fn = raid1_congested; - mddev->queue->backing_dev_info.congested_data = mddev; + if (mddev->queue) { + mddev->queue->backing_dev_info.congested_fn = raid1_congested; + mddev->queue->backing_dev_info.congested_data = mddev; + } return md_integrity_register(mddev); } diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h index 5fc4ca1af863..e743a64fac4f 100644 --- a/drivers/md/raid1.h +++ b/drivers/md/raid1.h @@ -126,4 +126,6 @@ struct r1bio_s { */ #define R1BIO_Returned 6 +extern int md_raid1_congested(mddev_t *mddev, int bits); + #endif From 076f968b37f0232d883749da8f5031df5dea7ade Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 7 Jun 2011 17:51:30 -0500 Subject: [PATCH 199/595] MD: add sync_super to mddev_t struct Add the 'sync_super' function pointer to MD array structure (struct mddev_s) If device-mapper (dm-raid.c) is to define its own on-disk superblock and be able to load it, there must still be a way for MD to initiate superblock updates. The simplest way to make this happen is to provide a pointer in the MD array structure that can be set by device-mapper (or other module) with a function to do this. If the function has been set, it will be used; otherwise, the method with be looked up via 'super_types' as usual. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/md.c | 15 +++++++++++++-- drivers/md/md.h | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index d5385188c445..9160463b5f68 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1753,6 +1753,18 @@ static struct super_type super_types[] = { }, }; +static void sync_super(mddev_t *mddev, mdk_rdev_t *rdev) +{ + if (mddev->sync_super) { + mddev->sync_super(mddev, rdev); + return; + } + + BUG_ON(mddev->major_version >= ARRAY_SIZE(super_types)); + + super_types[mddev->major_version].sync_super(mddev, rdev); +} + static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) { mdk_rdev_t *rdev, *rdev2; @@ -2171,8 +2183,7 @@ static void sync_sbs(mddev_t * mddev, int nospares) /* Don't update this superblock */ rdev->sb_loaded = 2; } else { - super_types[mddev->major_version]. - sync_super(mddev, rdev); + sync_super(mddev, rdev); rdev->sb_loaded = 1; } } diff --git a/drivers/md/md.h b/drivers/md/md.h index 0b1fd3f1d85b..5e35535ab7c3 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -330,6 +330,7 @@ struct mddev_s atomic_t flush_pending; struct work_struct flush_work; struct work_struct event_work; /* used by dm to report failure event */ + void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev); }; From 5bdbd4fa4df6891a6644d588c9a30d30e7c0af8e Mon Sep 17 00:00:00 2001 From: Srinivas KANDAGATLA Date: Wed, 8 Jun 2011 15:22:39 +0900 Subject: [PATCH 200/595] sh: Fix up xchg/cmpxchg corruption with gUSA RB. gUSA special cases r15 for part of its login/out sequence, meaning that any parameters need to be explicitly prohibited from accidentally being assigned that particular register, and the compiler ultimately needs to use a temporary instead. Certain configurations have begun generating code paths that do indeed get allocated r15, resulting in immediate corruption of the exchanged value. This was observed in (amongst others) exit_mm() code generation where the xchg_u32 call was immediately corrupting a structure address. As this is a general gUSA restriction, the rest of the users likewise need to be updated to ensure sensible constraints. References: https://bugzilla.stlinux.com/show_bug.cgi?id=11229 Signed-off-by: Srinivas Kandagatla Reviewed-by: Stuart Menefy Signed-off-by: Paul Mundt --- arch/sh/include/asm/cmpxchg-grb.h | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/arch/sh/include/asm/cmpxchg-grb.h b/arch/sh/include/asm/cmpxchg-grb.h index 4676bf57693a..f848dec9e483 100644 --- a/arch/sh/include/asm/cmpxchg-grb.h +++ b/arch/sh/include/asm/cmpxchg-grb.h @@ -15,8 +15,9 @@ static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val) " mov.l %2, @%1 \n\t" /* store new value */ "1: mov r1, r15 \n\t" /* LOGOUT */ : "=&r" (retval), - "+r" (m) - : "r" (val) + "+r" (m), + "+r" (val) /* inhibit r15 overloading */ + : : "memory", "r0", "r1"); return retval; @@ -36,8 +37,9 @@ static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val) " mov.b %2, @%1 \n\t" /* store new value */ "1: mov r1, r15 \n\t" /* LOGOUT */ : "=&r" (retval), - "+r" (m) - : "r" (val) + "+r" (m), + "+r" (val) /* inhibit r15 overloading */ + : : "memory" , "r0", "r1"); return retval; @@ -54,13 +56,14 @@ static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old, " nop \n\t" " mov r15, r1 \n\t" /* r1 = saved sp */ " mov #-8, r15 \n\t" /* LOGIN */ - " mov.l @%1, %0 \n\t" /* load old value */ - " cmp/eq %0, %2 \n\t" + " mov.l @%3, %0 \n\t" /* load old value */ + " cmp/eq %0, %1 \n\t" " bf 1f \n\t" /* if not equal */ - " mov.l %3, @%1 \n\t" /* store new value */ + " mov.l %2, @%3 \n\t" /* store new value */ "1: mov r1, r15 \n\t" /* LOGOUT */ - : "=&r" (retval) - : "r" (m), "r" (old), "r" (new) + : "=&r" (retval), + "+r" (old), "+r" (new) /* old or new can be r15 */ + : "r" (m) : "memory" , "r0", "r1", "t"); return retval; From 7416401661fad5c7ee9edb17cb54e7bff7a74dfe Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 6 Jun 2011 11:51:43 +0200 Subject: [PATCH 201/595] arm: davinci: Fix fallout from generic irq chip conversion The code which does the chained handler setup was overwriting chip_data. Signed-off-by: Thomas Gleixner Tested-by: Holger Hans Peter Freyther Signed-off-by: Kevin Hilman Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/gpio.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index a0b838894ac9..e7221398e5af 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -252,9 +252,11 @@ static struct irq_chip gpio_irqchip = { static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) { - struct davinci_gpio_regs __iomem *g = irq2regs(irq); + struct davinci_gpio_regs __iomem *g; u32 mask = 0xffff; + g = (__force struct davinci_gpio_regs __iomem *) irq_desc_get_handler_data(desc); + /* we only care about one bank */ if (irq & 1) mask <<= 16; @@ -422,8 +424,7 @@ static int __init davinci_gpio_irq_setup(void) /* set up all irqs in this bank */ irq_set_chained_handler(bank_irq, gpio_irq_handler); - irq_set_chip_data(bank_irq, (__force void *)g); - irq_set_handler_data(bank_irq, (void *)irq); + irq_set_handler_data(bank_irq, (__force void *)g); for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) { irq_set_chip(irq, &gpio_irqchip); From 7e9f1945213cdd7cd11f29346ded07a81854b5af Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Sun, 5 Jun 2011 17:33:33 +0530 Subject: [PATCH 202/595] davinci: make PCM platform devices static Make the PCM device structures used in devices.c and devices-da8xx.c static as they are used only in the respective files. This was found when trying to build a single image for DaVinci and DA8x devices using runtime P2V support. Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/devices-da8xx.c | 2 +- arch/arm/mach-davinci/devices.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 4e66881c7aee..fc4e98ea7543 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -494,7 +494,7 @@ static struct platform_device da850_mcasp_device = { .resource = da850_mcasp_resources, }; -struct platform_device davinci_pcm_device = { +static struct platform_device davinci_pcm_device = { .name = "davinci-pcm-audio", .id = -1, }; diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index 8f4f736aa267..806a2f02b980 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -298,7 +298,7 @@ static void davinci_init_wdt(void) /*-------------------------------------------------------------------------*/ -struct platform_device davinci_pcm_device = { +static struct platform_device davinci_pcm_device = { .name = "davinci-pcm-audio", .id = -1, }; From fd8a7de177b6f56a0fc59ad211c197a7df06b1ad Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 20 Jul 2010 14:34:50 +0200 Subject: [PATCH 203/595] x86: cpu-hotplug: Prevent softirq wakeup on wrong CPU After a newly plugged CPU sets the cpu_online bit it enables interrupts and goes idle. The cpu which brought up the new cpu waits for the cpu_online bit and when it observes it, it sets the cpu_active bit for this cpu. The cpu_active bit is the relevant one for the scheduler to consider the cpu as a viable target. With forced threaded interrupt handlers which imply forced threaded softirqs we observed the following race: cpu 0 cpu 1 bringup(cpu1); set_cpu_online(smp_processor_id(), true); local_irq_enable(); while (!cpu_online(cpu1)); timer_interrupt() -> wake_up(softirq_thread_cpu1); -> enqueue_on(softirq_thread_cpu1, cpu0); ^^^^ cpu_notify(CPU_ONLINE, cpu1); -> sched_cpu_active(cpu1) -> set_cpu_active((cpu1, true); When an interrupt happens before the cpu_active bit is set by the cpu which brought up the newly onlined cpu, then the scheduler refuses to enqueue the woken thread which is bound to that newly onlined cpu on that newly onlined cpu due to the not yet set cpu_active bit and selects a fallback runqueue. Not really an expected and desirable behaviour. So far this has only been observed with forced hard/softirq threading, but in theory this could happen without forced threaded hard/softirqs as well. It's probably unobservable as it would take a massive interrupt storm on the newly onlined cpu which causes the softirq loop to wake up the softirq thread and an even longer delay of the cpu which waits for the cpu_online bit. Signed-off-by: Thomas Gleixner Reviewed-by: Peter Zijlstra Cc: stable@kernel.org # 2.6.39 --- arch/x86/kernel/smpboot.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 33a0c11797de..9fd3137230d4 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -285,6 +285,19 @@ notrace static void __cpuinit start_secondary(void *unused) per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; x86_platform.nmi_init(); + /* + * Wait until the cpu which brought this one up marked it + * online before enabling interrupts. If we don't do that then + * we can end up waking up the softirq thread before this cpu + * reached the active state, which makes the scheduler unhappy + * and schedule the softirq thread on the wrong cpu. This is + * only observable with forced threaded interrupts, but in + * theory it could also happen w/o them. It's just way harder + * to achieve. + */ + while (!cpumask_test_cpu(smp_processor_id(), cpu_active_mask)) + cpu_relax(); + /* enable local interrupts */ local_irq_enable(); From 428c6e3630b343d5b3034af914015d10c94bb90e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 8 Jun 2011 19:58:29 +1000 Subject: [PATCH 204/595] drm/radeon/kms: set family for use in parser. Wierdly the kms parser never initialised the family, it wasn't really used much, but the fmt checker patch started using it and it fell over. Reported-by: Markus Trippelsdorf Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_cs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 8c1916941871..fae00c0d75aa 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -228,6 +228,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) parser.filp = filp; parser.rdev = rdev; parser.dev = rdev->dev; + parser.family = rdev->family; r = radeon_cs_parser_init(&parser, data); if (r) { DRM_ERROR("Failed to initialize parser !\n"); From 62fff811d73095bd95579d72f558f03c78f7914a Mon Sep 17 00:00:00 2001 From: Daniel Haid Date: Wed, 8 Jun 2011 20:04:45 +1000 Subject: [PATCH 205/595] drm/radeon/kms: fix for radeon on systems >4GB without hardware iommu On my x86_64 system with >4GB of ram and swiotlb instead of a hardware iommu (because I have a VIA chipset), the call to pci_set_dma_mask (see below) with 40bits returns an error. But it seems that the radeon driver is designed to have need_dma32 = true exactly if pci_set_dma_mask is called with 32 bits and false if it is called with 40 bits. I have read somewhere that the default are 32 bits. So if the call fails I suppose that need_dma32 should be set to true. And indeed the patch fixes the problem I have had before and which I had described here: http://choon.net/forum/read.php?21,106131,115940 Acked-by: Alex Deucher cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index d77ede3e67ce..e680501c78ea 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -754,6 +754,7 @@ int radeon_device_init(struct radeon_device *rdev, dma_bits = rdev->need_dma32 ? 32 : 40; r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); if (r) { + rdev->need_dma32 = true; printk(KERN_WARNING "radeon: No suitable DMA available.\n"); } From 805c22168da76a65c978017d0fe0d59cd048e995 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 6 Jun 2011 17:39:16 -0400 Subject: [PATCH 206/595] drm/radeon/kms: disable hdmi audio by default The current RE'd code causes blank screens and display problems on a lot of systems. So disable it by default for now. It can still be enabled by setting the audio parameter to 1. E.g.: radeon.audio=1 Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=38010 https://bugs.freedesktop.org/show_bug.cgi?id=27731 https://bugs.freedesktop.org/show_bug.cgi?id=35970 https://bugs.freedesktop.org/show_bug.cgi?id=26195 and many other reported problems. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 1d330606292f..73dfbe8e5f9e 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -113,7 +113,7 @@ int radeon_benchmarking = 0; int radeon_testing = 0; int radeon_connector_table = 0; int radeon_tv = 1; -int radeon_audio = 1; +int radeon_audio = 0; int radeon_disp_priority = 0; int radeon_hw_i2c = 0; int radeon_pcie_gen2 = 0; @@ -151,7 +151,7 @@ module_param_named(connector_table, radeon_connector_table, int, 0444); MODULE_PARM_DESC(tv, "TV enable (0 = disable)"); module_param_named(tv, radeon_tv, int, 0444); -MODULE_PARM_DESC(audio, "Audio enable (0 = disable)"); +MODULE_PARM_DESC(audio, "Audio enable (1 = enable)"); module_param_named(audio, radeon_audio, int, 0444); MODULE_PARM_DESC(disp_priority, "Display Priority (0 = auto, 1 = normal, 2 = high)"); From 0f82bdf572fc6e42147151aa4d52542f7fc6d793 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 7 Jun 2011 23:42:04 +0100 Subject: [PATCH 207/595] ASoC: Fix WM8962 headphone volume update for use of advanced caches Signed-off-by: Mark Brown Acked-by: Liam Girdwood Cc: stable@kernel.org --- sound/soc/codecs/wm8962.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index f90ae427242b..5e05eed96c38 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1999,12 +1999,12 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, return 0; /* If the left PGA is enabled hit that VU bit... */ - if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTL_PGA_ENA) + if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTL_PGA_ENA) return snd_soc_write(codec, WM8962_HPOUTL_VOLUME, reg_cache[WM8962_HPOUTL_VOLUME]); /* ...otherwise the right. The VU is stereo. */ - if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTR_PGA_ENA) + if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTR_PGA_ENA) return snd_soc_write(codec, WM8962_HPOUTR_VOLUME, reg_cache[WM8962_HPOUTR_VOLUME]); From 81de916f19cf5f1437c0b9ed817364f0f7c81961 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 8 Jun 2011 07:46:30 -0700 Subject: [PATCH 208/595] tty_buffer: get rid of 'seen_tail' logic in flush_to_ldisc The flush_to_ldisc() work entry has special logic to notice when it has seen the original tail of the data queue, and it avoids continuing the flush if it sees that _original_ tail rather than the current tail. This logic can trigger in case somebody is constantly adding new data to the tty while the flushing is active - and the intent is to avoid excessive CPU usage while flushing the tty, especially as we used to do this from a softirq context which made it non-preemptible. However, since we no longer re-arm the work-queue from within itself (because that causes other trouble: see commit a5660b41af6a "tty: fix endless work loop when the buffer fills up"), this just leads to possible hung tty's (most easily seen in SMP and with a test-program that floods a pty with data - nobody seems to have reported this for any real-life situation yet). And since the workqueue isn't done from timers and softirq's any more, it's doubtful whether the CPU useage issue is really relevant any more. So just remove the logic entirely, and see if anybody ever notices. Alternatively, we might want to re-introduce the "re-arm the work" for just this case, but then we'd have to re-introduce the delayed work model or some explicit timer, which really doesn't seem worth it for this. Reported-and-tested-by: Guillaume Chazarain Cc: Alan Cox Cc: Felipe Balbi Cc: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/tty/tty_buffer.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index f1a7918d71aa..6c9b7cd6778a 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -413,8 +413,7 @@ static void flush_to_ldisc(struct work_struct *work) spin_lock_irqsave(&tty->buf.lock, flags); if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) { - struct tty_buffer *head, *tail = tty->buf.tail; - int seen_tail = 0; + struct tty_buffer *head; while ((head = tty->buf.head) != NULL) { int count; char *char_buf; @@ -424,15 +423,6 @@ static void flush_to_ldisc(struct work_struct *work) if (!count) { if (head->next == NULL) break; - /* - There's a possibility tty might get new buffer - added during the unlock window below. We could - end up spinning in here forever hogging the CPU - completely. To avoid this let's have a rest each - time we processed the tail buffer. - */ - if (tail == head) - seen_tail = 1; tty->buf.head = head->next; tty_buffer_free(tty, head); continue; @@ -442,7 +432,7 @@ static void flush_to_ldisc(struct work_struct *work) line discipline as we want to empty the queue */ if (test_bit(TTY_FLUSHPENDING, &tty->flags)) break; - if (!tty->receive_room || seen_tail) + if (!tty->receive_room) break; if (count > tty->receive_room) count = tty->receive_room; From 83fb086e0ecd879a4676cf12fc7afc1f9ecd1784 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 8 Jun 2011 07:35:24 -0400 Subject: [PATCH 209/595] cifs: trivial: add space in fsc error message Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index fb31c2c1bb17..bb659eb73810 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1391,7 +1391,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, "/proc/fs/cifs/LookupCacheEnabled to 0\n"); } else if (strnicmp(data, "fsc", 3) == 0) { #ifndef CONFIG_CIFS_FSCACHE - cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE" + cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE " "kernel config option set"); goto cifs_parse_mount_err; #endif From e2d4dc5af36673e64e29973c974246eafe63548f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Jun 2011 09:18:32 -0700 Subject: [PATCH 210/595] Staging: cx23885: fix include of altera.h The cx23885 driver was including staging/altera.h, but that file has moved back into the driver directory. Why a non-staging driver was including a staging driver is beyond me, but this fixes the build so everything is happy for now. For the record, it's not ok for a non-staging driver to depend on a staging one, as that implies that the non-staging one should also be in the staging tree if that's needed. Cc: Igor M. Liplianin Cc: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/cx23885/cx23885-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 2354336862cf..934185cca758 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -25,8 +25,8 @@ #include #include #include -#include +#include "../../../staging/altera-stapl/altera.h" #include "cx23885.h" #include "tuner-xc2028.h" #include "netup-init.h" From 43e4e0b94984b45d52048e3ac027cac15c718b65 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 27 May 2011 08:40:24 -0700 Subject: [PATCH 211/595] iwlagn: send tx power command if defer cause by RXON not match During channge channel, tx power will not send to uCode, the tx power command should send after scan complete. but should also can send after RXON command. Stable fix identified by Stanislaw Gruszka . Signed-off-by: Wey-Yi Guy Cc: stable@kernel.org [2.6.38+] Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 018874964602..09f679d6046f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -370,6 +370,11 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } memcpy(active, &ctx->staging, sizeof(*active)); + /* + * We do not commit tx power settings while channel changing, + * do it now if after settings changed. + */ + iwl_set_tx_power(priv, priv->tx_power_next, false); return 0; } From f3209bea110cade12e2b133da8b8499689cb0e2e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 8 Jun 2011 13:27:29 +0200 Subject: [PATCH 212/595] mac80211: fix IBSS teardown race Ignacy reports that sometimes after leaving an IBSS joining a new one didn't work because there still were stations on the list. He fixed it by flushing stations when attempting to join a new IBSS, but this shouldn't be happening in the first case. When I looked into it I saw a race condition in teardown that could cause stations to be added after flush, and thus cause this situation. Ignacy confirms that after applying my patch he hasn't seen this happen again. Reported-by: Ignacy Gawedzki Debugged-by: Ignacy Gawedzki Tested-by: Ignacy Gawedzki Cc: stable@kernel.org Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 421eaa6b0c2b..56c24cabf26d 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -965,6 +965,10 @@ 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)) { @@ -999,8 +1003,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) kfree_skb(skb); skb_queue_purge(&sdata->skb_queue); - memset(sdata->u.ibss.bssid, 0, ETH_ALEN); - sdata->u.ibss.ssid_len = 0; del_timer_sync(&sdata->u.ibss.timer); From 51e65257142a87fe46a1ce5c35c86c5baf012614 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 8 Jun 2011 15:26:31 +0200 Subject: [PATCH 213/595] iwlegacy: fix channel switch locking We use priv->mutex to avoid race conditions between chswitch_done() and mac_channel_switch(), when marking channel switch in progress. But chswitch_done() can be called in atomic context from rx_csa() or with mutex already taken from commit_rxon(). To fix remove mutex from chswitch_done() and use atomic bitops for marking channel switch pending. Cc: stable@kernel.org # 2.6.39+ Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-4965.c | 9 ++---- drivers/net/wireless/iwlegacy/iwl-core.c | 30 +++++++++----------- drivers/net/wireless/iwlegacy/iwl-core.h | 2 +- drivers/net/wireless/iwlegacy/iwl-dev.h | 13 +-------- drivers/net/wireless/iwlegacy/iwl4965-base.c | 20 ++++++------- 5 files changed, 28 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c index e1b89220c186..facc94e74b07 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965.c @@ -1218,10 +1218,10 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c * receive commit_rxon request * abort any previous channel switch if still in process */ - if (priv->switch_rxon.switch_in_progress && - (priv->switch_rxon.channel != ctx->staging.channel)) { + if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) && + (priv->switch_channel != ctx->staging.channel)) { IWL_DEBUG_11H(priv, "abort channel switch on %d\n", - le16_to_cpu(priv->switch_rxon.channel)); + le16_to_cpu(priv->switch_channel)); iwl_legacy_chswitch_done(priv, false); } @@ -1404,9 +1404,6 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, return rc; } - priv->switch_rxon.channel = cmd.channel; - priv->switch_rxon.switch_in_progress = true; - return iwl_legacy_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); } diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c index 42df8321dae8..3be76bd5499a 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.c +++ b/drivers/net/wireless/iwlegacy/iwl-core.c @@ -859,12 +859,8 @@ void iwl_legacy_chswitch_done(struct iwl_priv *priv, bool is_success) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (priv->switch_rxon.switch_in_progress) { + if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) ieee80211_chswitch_done(ctx->vif, is_success); - mutex_lock(&priv->mutex); - priv->switch_rxon.switch_in_progress = false; - mutex_unlock(&priv->mutex); - } } EXPORT_SYMBOL(iwl_legacy_chswitch_done); @@ -876,19 +872,19 @@ void iwl_legacy_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_legacy_rxon_cmd *rxon = (void *)&ctx->active; - if (priv->switch_rxon.switch_in_progress) { - if (!le32_to_cpu(csa->status) && - (csa->channel == priv->switch_rxon.channel)) { - rxon->channel = csa->channel; - ctx->staging.channel = csa->channel; - IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", - le16_to_cpu(csa->channel)); - iwl_legacy_chswitch_done(priv, true); - } else { - IWL_ERR(priv, "CSA notif (fail) : channel %d\n", + if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) + return; + + if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { + rxon->channel = csa->channel; + ctx->staging.channel = csa->channel; + IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", le16_to_cpu(csa->channel)); - iwl_legacy_chswitch_done(priv, false); - } + iwl_legacy_chswitch_done(priv, true); + } else { + IWL_ERR(priv, "CSA notif (fail) : channel %d\n", + le16_to_cpu(csa->channel)); + iwl_legacy_chswitch_done(priv, false); } } EXPORT_SYMBOL(iwl_legacy_rx_csa); diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h index bc66c604106c..c5fbda0760de 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.h +++ b/drivers/net/wireless/iwlegacy/iwl-core.h @@ -560,7 +560,7 @@ void iwl_legacy_free_geos(struct iwl_priv *priv); #define STATUS_SCAN_HW 15 #define STATUS_POWER_PMI 16 #define STATUS_FW_ERROR 17 - +#define STATUS_CHANNEL_SWITCH_PENDING 18 static inline int iwl_legacy_is_ready(struct iwl_priv *priv) { diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h index be0106c6a2da..ea30122669ee 100644 --- a/drivers/net/wireless/iwlegacy/iwl-dev.h +++ b/drivers/net/wireless/iwlegacy/iwl-dev.h @@ -854,17 +854,6 @@ struct traffic_stats { #endif }; -/* - * iwl_switch_rxon: "channel switch" structure - * - * @ switch_in_progress: channel switch in progress - * @ channel: new channel - */ -struct iwl_switch_rxon { - bool switch_in_progress; - __le16 channel; -}; - /* * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds * to perform continuous uCode event logging operation if enabled @@ -1115,7 +1104,7 @@ struct iwl_priv { struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX]; - struct iwl_switch_rxon switch_rxon; + __le16 switch_channel; /* 1st responses from initialize and runtime uCode images. * _4965's initialize alive response contains some calibration data. */ diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c index af2ae22fcfd3..7157ba529680 100644 --- a/drivers/net/wireless/iwlegacy/iwl4965-base.c +++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c @@ -2861,16 +2861,13 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw, goto out; if (test_bit(STATUS_EXIT_PENDING, &priv->status) || - test_bit(STATUS_SCANNING, &priv->status)) + test_bit(STATUS_SCANNING, &priv->status) || + test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) goto out; if (!iwl_legacy_is_associated_ctx(ctx)) goto out; - /* channel switch in progress */ - if (priv->switch_rxon.switch_in_progress == true) - goto out; - if (priv->cfg->ops->lib->set_channel_switch) { ch = channel->hw_value; @@ -2919,15 +2916,18 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw, * at this point, staging_rxon has the * configuration for channel switch */ - if (priv->cfg->ops->lib->set_channel_switch(priv, - ch_switch)) - priv->switch_rxon.switch_in_progress = false; + set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); + priv->switch_channel = cpu_to_le16(ch); + if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) { + clear_bit(STATUS_CHANNEL_SWITCH_PENDING, + &priv->status); + priv->switch_channel = 0; + ieee80211_chswitch_done(ctx->vif, false); + } } } out: mutex_unlock(&priv->mutex); - if (!priv->switch_rxon.switch_in_progress) - ieee80211_chswitch_done(ctx->vif, false); IWL_DEBUG_MAC80211(priv, "leave\n"); } From 86d4a77ba3dc4ace238a0556541a41df2bd71d49 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 25 May 2011 13:03:16 -0400 Subject: [PATCH 214/595] Btrfs: cache bitmaps when searching for a cluster If we are looking for a cluster in a particularly sparse or fragmented block group, we will do a lot of looping through the free space tree looking for various things, and if we need to look at bitmaps we will endup doing the whole dance twice. So instead add the bitmap entries to a temporary list so if we have to do the bitmap search we can just look through the list of entries we've found quickly instead of having to loop through the entire tree again. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/free-space-cache.c | 54 +++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index ad144736a5fd..930c07f79b3d 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2144,6 +2144,7 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group, */ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, struct btrfs_free_cluster *cluster, + struct list_head *bitmaps, u64 offset, u64 bytes, u64 min_bytes) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; @@ -2166,6 +2167,8 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, * extent entry. */ while (entry->bitmap) { + if (list_empty(&entry->list)) + list_add_tail(&entry->list, bitmaps); node = rb_next(&entry->offset_index); if (!node) return -ENOSPC; @@ -2185,8 +2188,12 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, return -ENOSPC; entry = rb_entry(node, struct btrfs_free_space, offset_index); - if (entry->bitmap) + if (entry->bitmap) { + if (list_empty(&entry->list)) + list_add_tail(&entry->list, bitmaps); continue; + } + /* * we haven't filled the empty size and the window is * very large. reset and try again @@ -2240,6 +2247,7 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, */ static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, struct btrfs_free_cluster *cluster, + struct list_head *bitmaps, u64 offset, u64 bytes, u64 min_bytes) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; @@ -2250,10 +2258,39 @@ static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, if (ctl->total_bitmaps == 0) return -ENOSPC; + /* + * First check our cached list of bitmaps and see if there is an entry + * here that will work. + */ + list_for_each_entry(entry, bitmaps, list) { + if (entry->bytes < min_bytes) + continue; + ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset, + bytes, min_bytes); + if (!ret) + return 0; + } + + /* + * If we do have entries on our list and we are here then we didn't find + * anything, so go ahead and get the next entry after the last entry in + * this list and start the search from there. + */ + if (!list_empty(bitmaps)) { + entry = list_entry(bitmaps->prev, struct btrfs_free_space, + list); + node = rb_next(&entry->offset_index); + if (!node) + return -ENOSPC; + entry = rb_entry(node, struct btrfs_free_space, offset_index); + goto search; + } + entry = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 0, 1); if (!entry) return -ENOSPC; +search: node = &entry->offset_index; do { entry = rb_entry(node, struct btrfs_free_space, offset_index); @@ -2284,6 +2321,8 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, u64 offset, u64 bytes, u64 empty_size) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; + struct list_head bitmaps; + struct btrfs_free_space *entry, *tmp; u64 min_bytes; int ret; @@ -2322,11 +2361,16 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, goto out; } - ret = setup_cluster_no_bitmap(block_group, cluster, offset, bytes, - min_bytes); + INIT_LIST_HEAD(&bitmaps); + ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset, + bytes, min_bytes); if (ret) - ret = setup_cluster_bitmap(block_group, cluster, offset, - bytes, min_bytes); + ret = setup_cluster_bitmap(block_group, cluster, &bitmaps, + offset, bytes, min_bytes); + + /* Clear our temporary list */ + list_for_each_entry_safe(entry, tmp, &bitmaps, list) + list_del_init(&entry->list); if (!ret) { atomic_inc(&block_group->count); From 3de85bb95cc50d0977cbb7a0c605e894be4c790d Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 25 May 2011 13:07:37 -0400 Subject: [PATCH 215/595] Btrfs: noinline the cluster searching functions When profiling the find cluster code it's hard to tell where we are spending our time because the bitmap and non-bitmap functions get inlined by the compiler, so make that not happen. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/free-space-cache.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 930c07f79b3d..f56caacfd8ad 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2142,10 +2142,11 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group, /* * This searches the block group for just extents to fill the cluster with. */ -static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, - struct btrfs_free_cluster *cluster, - struct list_head *bitmaps, - u64 offset, u64 bytes, u64 min_bytes) +static noinline int +setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, + struct btrfs_free_cluster *cluster, + struct list_head *bitmaps, u64 offset, u64 bytes, + u64 min_bytes) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_free_space *first = NULL; @@ -2245,10 +2246,11 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, * This specifically looks for bitmaps that may work in the cluster, we assume * that we have already failed to find extents that will work. */ -static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, - struct btrfs_free_cluster *cluster, - struct list_head *bitmaps, - u64 offset, u64 bytes, u64 min_bytes) +static noinline int +setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, + struct btrfs_free_cluster *cluster, + struct list_head *bitmaps, u64 offset, u64 bytes, + u64 min_bytes) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_free_space *entry; From f2bb8f5cfb3bce595b2de251ed7638047fc4e530 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 25 May 2011 13:10:16 -0400 Subject: [PATCH 216/595] Btrfs: don't commit the transaction if we dont have enough pinned bytes I noticed when running an enospc test that we would get stuck committing the transaction in check_data_space even though we truly didn't have enough space. So check to see if bytes_pinned is bigger than num_bytes, if it's not don't commit the transaction. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/extent-tree.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 5b9b6b6df242..0d0a3fe77bb7 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3089,6 +3089,13 @@ int btrfs_check_data_free_space(struct inode *inode, u64 bytes) } goto again; } + + /* + * If we have less pinned bytes than we want to allocate then + * don't bother committing the transaction, it won't help us. + */ + if (data_sinfo->bytes_pinned < bytes) + committed = 1; spin_unlock(&data_sinfo->lock); /* commit the current transaction and try again */ From a80fd9db0e1909a03e5d5a29e2e73001e38d12f5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 8 Jun 2011 21:48:03 +0200 Subject: [PATCH 217/595] spi/rtc-m41t93: Use spi_get_drvdata() for SPI devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One new offender detected by the recently increased type checking in platform_get_drvdata(): drivers/rtc/rtc-m41t93.c: In function ‘m41t93_remove’: drivers/rtc/rtc-m41t93.c:192: warning: passing argument 1 of ‘platform_get_drvdata’ from incompatible pointer type Use spi_get_drvdata() instead of platform_get_drvdata(), cfr. commit 42fea15d6dc410e62dac6a764142045280624a5b ("spi/rtc-{ds1390,ds3234,m41t94}: Use spi_get_drvdata() for SPI devices") Signed-off-by: Geert Uytterhoeven Signed-off-by: Grant Likely --- drivers/rtc/rtc-m41t93.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c index 1a84b3e227d1..7317d3b9a3d5 100644 --- a/drivers/rtc/rtc-m41t93.c +++ b/drivers/rtc/rtc-m41t93.c @@ -189,7 +189,7 @@ static int __devinit m41t93_probe(struct spi_device *spi) static int __devexit m41t93_remove(struct spi_device *spi) { - struct rtc_device *rtc = platform_get_drvdata(spi); + struct rtc_device *rtc = spi_get_drvdata(spi); if (rtc) rtc_device_unregister(rtc); From 2cdc342c204dba69ca3b2ec43d8e6ff41ed920b8 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 27 May 2011 14:07:49 -0400 Subject: [PATCH 218/595] Btrfs: fix bitmap regression In cleaning up the clustering code I accidently introduced a regression by adding bitmap entries to the cluster rb tree. The problem is if we've maxed out the number of bitmaps we can have for the block group we can only add free space to the bitmaps, but since the bitmap is on the cluster we can't find it and we try to create another one. This would result in a panic because the total bitmaps was bigger than the max bitmaps that were allowed. This patch fixes this by checking to see if we have a cluster, and then looking at the cluster rb tree to see if it has a bitmap entry and if it does and that space belongs to that bitmap, go ahead and add it to that bitmap. I could hit this panic every time with an fs_mark test within a couple of minutes. With this patch I no longer hit the panic and fs_mark goes to completion. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/free-space-cache.c | 88 +++++++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 19 deletions(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index f56caacfd8ad..8258ccf85dbd 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1417,6 +1417,23 @@ static noinline int remove_from_bitmap(struct btrfs_free_space_ctl *ctl, return 0; } +static u64 add_bytes_to_bitmap(struct btrfs_free_space_ctl *ctl, + struct btrfs_free_space *info, u64 offset, + u64 bytes) +{ + u64 bytes_to_set = 0; + u64 end; + + end = info->offset + (u64)(BITS_PER_BITMAP * ctl->unit); + + bytes_to_set = min(end - offset, bytes); + + bitmap_set_bits(ctl, info, offset, bytes_to_set); + + return bytes_to_set; + +} + static bool use_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info) { @@ -1453,12 +1470,18 @@ static bool use_bitmap(struct btrfs_free_space_ctl *ctl, return true; } +static struct btrfs_free_space_op free_space_op = { + .recalc_thresholds = recalculate_thresholds, + .use_bitmap = use_bitmap, +}; + static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info) { struct btrfs_free_space *bitmap_info; + struct btrfs_block_group_cache *block_group = NULL; int added = 0; - u64 bytes, offset, end; + u64 bytes, offset, bytes_added; int ret; bytes = info->bytes; @@ -1467,6 +1490,47 @@ static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl, if (!ctl->op->use_bitmap(ctl, info)) return 0; + if (ctl->op == &free_space_op) + block_group = ctl->private; + + /* + * Since we link bitmaps right into the cluster we need to see if we + * have a cluster here, and if so and it has our bitmap we need to add + * the free space to that bitmap. + */ + if (block_group && !list_empty(&block_group->cluster_list)) { + struct btrfs_free_cluster *cluster; + struct rb_node *node; + struct btrfs_free_space *entry; + + cluster = list_entry(block_group->cluster_list.next, + struct btrfs_free_cluster, + block_group_list); + spin_lock(&cluster->lock); + node = rb_first(&cluster->root); + if (!node) { + spin_unlock(&cluster->lock); + goto again; + } + + entry = rb_entry(node, struct btrfs_free_space, offset_index); + if (!entry->bitmap) { + spin_unlock(&cluster->lock); + goto again; + } + + if (entry->offset == offset_to_bitmap(ctl, offset)) { + bytes_added = add_bytes_to_bitmap(ctl, entry, + offset, bytes); + bytes -= bytes_added; + offset += bytes_added; + } + spin_unlock(&cluster->lock); + if (!bytes) { + ret = 1; + goto out; + } + } again: bitmap_info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 1, 0); @@ -1475,19 +1539,10 @@ static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl, goto new_bitmap; } - end = bitmap_info->offset + (u64)(BITS_PER_BITMAP * ctl->unit); - - if (offset >= bitmap_info->offset && offset + bytes > end) { - bitmap_set_bits(ctl, bitmap_info, offset, end - offset); - bytes -= end - offset; - offset = end; - added = 0; - } else if (offset >= bitmap_info->offset && offset + bytes <= end) { - bitmap_set_bits(ctl, bitmap_info, offset, bytes); - bytes = 0; - } else { - BUG(); - } + bytes_added = add_bytes_to_bitmap(ctl, bitmap_info, offset, bytes); + bytes -= bytes_added; + offset += bytes_added; + added = 0; if (!bytes) { ret = 1; @@ -1766,11 +1821,6 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group, "\n", count); } -static struct btrfs_free_space_op free_space_op = { - .recalc_thresholds = recalculate_thresholds, - .use_bitmap = use_bitmap, -}; - void btrfs_init_free_space_ctl(struct btrfs_block_group_cache *block_group) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; From 723bda2083d44edbd6be0f0b09f902120dc07442 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 27 May 2011 16:11:38 -0400 Subject: [PATCH 219/595] Btrfs: fix the allocator loop logic I was testing with empty_cluster = 0 to try and reproduce a problem and kept hitting early enospc panics. This was because our loop logic was a little confused. So this is what I did 1) Make the loop variable the ultimate decider on wether we should loop again isntead of checking to see if we had an uncached bg, empty size or empty cluster. 2) Increment loop before checking to see what we are on to make the loop definitions make more sense. 3) If we are on the chunk alloc loop don't set empty_size/empty_cluster to 0 unless we didn't actually allocate a chunk. If we did allocate a chunk we should be able to easily setup a new cluster so clearing empty_size/empty_cluster makes us less efficient. This kept me from hitting panics while trying to reproduce the other problem. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/extent-tree.c | 48 ++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 0d0a3fe77bb7..b42efc2ded51 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -5218,9 +5218,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, * LOOP_NO_EMPTY_SIZE, set empty_size and empty_cluster to 0 and try * again */ - if (!ins->objectid && loop < LOOP_NO_EMPTY_SIZE && - (found_uncached_bg || empty_size || empty_cluster || - allowed_chunk_alloc)) { + if (!ins->objectid && loop < LOOP_NO_EMPTY_SIZE) { index = 0; if (loop == LOOP_FIND_IDEAL && found_uncached_bg) { found_uncached_bg = false; @@ -5260,32 +5258,36 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, goto search; } - if (loop < LOOP_CACHING_WAIT) { - loop++; - goto search; - } + loop++; if (loop == LOOP_ALLOC_CHUNK) { - empty_size = 0; - empty_cluster = 0; - } + if (allowed_chunk_alloc) { + ret = do_chunk_alloc(trans, root, num_bytes + + 2 * 1024 * 1024, data, + CHUNK_ALLOC_LIMITED); + allowed_chunk_alloc = 0; + if (ret == 1) + done_chunk_alloc = 1; + } else if (!done_chunk_alloc && + space_info->force_alloc == + CHUNK_ALLOC_NO_FORCE) { + space_info->force_alloc = CHUNK_ALLOC_LIMITED; + } - if (allowed_chunk_alloc) { - ret = do_chunk_alloc(trans, root, num_bytes + - 2 * 1024 * 1024, data, - CHUNK_ALLOC_LIMITED); - allowed_chunk_alloc = 0; - done_chunk_alloc = 1; - } else if (!done_chunk_alloc && - space_info->force_alloc == CHUNK_ALLOC_NO_FORCE) { - space_info->force_alloc = CHUNK_ALLOC_LIMITED; + /* + * We didn't allocate a chunk, go ahead and drop the + * empty size and loop again. + */ + if (!done_chunk_alloc) + loop = LOOP_NO_EMPTY_SIZE; } - if (loop < LOOP_NO_EMPTY_SIZE) { - loop++; - goto search; + if (loop == LOOP_NO_EMPTY_SIZE) { + empty_size = 0; + empty_cluster = 0; } - ret = -ENOSPC; + + goto search; } else if (!ins->objectid) { ret = -ENOSPC; } else if (ins->objectid) { From f6a398298d34af66ec3a2d82a44a4dbc5277357d Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 6 Jun 2011 10:50:35 -0400 Subject: [PATCH 220/595] Btrfs: fix duplicate checking logic When merging my code into the integration test the second check for duplicate entries got screwed up. This patch fixes it by dropping ret2 and just using ret for the return value, and checking if we got an error before adding the bitmap to the local list. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/free-space-cache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 8258ccf85dbd..38f3fd923043 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -250,7 +250,7 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, pgoff_t index = 0; unsigned long first_page_offset; int num_checksums; - int ret = 0, ret2; + int ret = 0; INIT_LIST_HEAD(&bitmaps); @@ -421,11 +421,10 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, goto free_cache; } spin_lock(&ctl->tree_lock); - ret2 = link_free_space(ctl, e); + ret = link_free_space(ctl, e); ctl->total_bitmaps++; ctl->op->recalc_thresholds(ctl); spin_unlock(&ctl->tree_lock); - list_add_tail(&e->list, &bitmaps); if (ret) { printk(KERN_ERR "Duplicate entries in " "free space cache, dumping\n"); @@ -434,6 +433,7 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, page_cache_release(page); goto free_cache; } + list_add_tail(&e->list, &bitmaps); } num_entries--; From a26d31cef06f43a76327c21235e75450869df2b8 Mon Sep 17 00:00:00 2001 From: Steffen Sledz Date: Tue, 7 Jun 2011 14:01:56 +0200 Subject: [PATCH 221/595] USB: serial: add another 4N-GALAXY.DE PID to ftdi_sio driver E.g. newer CAN 2.0 A/B <=> USB 2.0 converters report idProduct=f3c2. Signed-off-by: Steffen Sledz Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index e8dbde55f6c5..162728977553 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -647,6 +647,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) }, { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_3_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 1d946cd238ba..ab1fcdf3c378 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -351,6 +351,7 @@ */ #define FTDI_4N_GALAXY_DE_1_PID 0xF3C0 #define FTDI_4N_GALAXY_DE_2_PID 0xF3C1 +#define FTDI_4N_GALAXY_DE_3_PID 0xF3C2 /* * Linx Technologies product ids From d6d0f665ad869c8ad8b8a42c4393e02dfe227e12 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 8 Jun 2011 19:16:28 +0300 Subject: [PATCH 222/595] MAINTAINERS: add a maintainer to Gadget Framework I'll be continuing the amazing work Dave has done with the Gadget Framework. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index fb0294919adc..b5ea4d033730 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6444,9 +6444,11 @@ S: Maintained F: drivers/media/video/et61x251/ USB GADGET/PERIPHERAL SUBSYSTEM +M: Felipe Balbi L: linux-usb@vger.kernel.org W: http://www.linux-usb.org/gadget -S: Orphan +T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git +S: Maintained F: drivers/usb/gadget/ F: include/linux/usb/gadget* From 95f4efb2d78661065aaf0be57f5bf00e4d2aea1d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 8 Jun 2011 15:11:56 -0700 Subject: [PATCH 223/595] selinux: simplify and clean up inode_has_perm() This is a rather hot function that is called with a potentially NULL "struct common_audit_data" pointer argument. And in that case it has to provide and initialize its own dummy common_audit_data structure. However, all the _common_ cases already pass it a real audit-data structure, so that uncommon NULL case not only creates a silly run-time test, more importantly it causes that function to have a big stack frame for the dummy variable that isn't even used in the common case! So get rid of that stupid run-time behavior, and make the (few) functions that currently call with a NULL pointer just call a new helper function instead (naturally called inode_has_perm_noapd(), since it has no adp argument). This makes the run-time test be a static code generation issue instead, and allows for a much denser stack since none of the common callers need the dummy structure. And a denser stack not only means less stack space usage, it means better cache behavior. So we have a win-win-win from this simplification: less code executed, smaller stack footprint, and better cache behavior. Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a0d38459d650..20219ef5439a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1476,7 +1476,6 @@ static int inode_has_perm(const struct cred *cred, unsigned flags) { struct inode_security_struct *isec; - struct common_audit_data ad; u32 sid; validate_creds(cred); @@ -1487,15 +1486,21 @@ static int inode_has_perm(const struct cred *cred, sid = cred_sid(cred); isec = inode->i_security; - if (!adp) { - adp = &ad; - COMMON_AUDIT_DATA_INIT(&ad, INODE); - ad.u.inode = inode; - } - return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); } +static int inode_has_perm_noadp(const struct cred *cred, + struct inode *inode, + u32 perms, + unsigned flags) +{ + struct common_audit_data ad; + + COMMON_AUDIT_DATA_INIT(&ad, INODE); + ad.u.inode = inode; + return inode_has_perm(cred, inode, perms, &ad, flags); +} + /* Same as inode_has_perm, but pass explicit audit data containing the dentry to help the auditing code to more easily generate the pathname if needed. */ @@ -2122,8 +2127,8 @@ static inline void flush_unauthorized_files(const struct cred *cred, struct tty_file_private, list); file = file_priv->file; inode = file->f_path.dentry->d_inode; - if (inode_has_perm(cred, inode, - FILE__READ | FILE__WRITE, NULL, 0)) { + if (inode_has_perm_noadp(cred, inode, + FILE__READ | FILE__WRITE, 0)) { drop_tty = 1; } } @@ -3228,7 +3233,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred) * new inode label or new policy. * This check is not redundant - do not remove. */ - return inode_has_perm(cred, inode, open_file_to_av(file), NULL, 0); + return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0); } /* task security operations */ From 13e12d14e2dccc7995b8f15a5678a338ab4e6a8c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 8 Jun 2011 15:18:19 -0700 Subject: [PATCH 224/595] vfs: reorganize 'struct inode' layout a bit This tries to make the 'struct inode' accesses denser in the data cache by moving a commonly accessed field (i_security) closer to other fields that are accessed often. It also makes 'i_state' just an 'unsigned int' rather than 'unsigned long', since we only use a few bits of that field, and moves it next to the existing 'i_flags' so that we potentially get better structure layout (although depending on config options, i_flags may already have packed in the same word as i_lock, so this improves packing only for the case of spinlock debugging) Out 'struct inode' is still way too big, and we should probably move some other fields around too (the acl fields in particular) for better data cache access density. Other fields (like the inode hash) are likely to be entirely irrelevant under most loads. Signed-off-by: Linus Torvalds --- include/linux/fs.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 646a1836152a..1c777878f1ea 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -744,9 +744,13 @@ struct inode { spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ unsigned int i_flags; + unsigned int i_state; +#ifdef CONFIG_SECURITY + void *i_security; +#endif struct mutex i_mutex; - unsigned long i_state; + unsigned long dirtied_when; /* jiffies of first dirtying */ struct hlist_node i_hash; @@ -798,9 +802,6 @@ struct inode { atomic_t i_readcount; /* struct files open RO */ #endif atomic_t i_writecount; -#ifdef CONFIG_SECURITY - void *i_security; -#endif #ifdef CONFIG_FS_POSIX_ACL struct posix_acl *i_acl; struct posix_acl *i_default_acl; From c49f8789f532ae39019135ca038e9bc0d15aaa4a Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 12 Mar 2011 17:44:10 +0100 Subject: [PATCH 225/595] dtc/powerpc: remove obsolete .gitignore entries dtc was moved and .gitignores have been added to the new location. So, we can delete the old, forgotten ones. Signed-off-by: Wolfram Sang Cc: Benjamin Herrenschmidt Signed-off-by: Grant Likely --- arch/powerpc/boot/.gitignore | 1 - arch/powerpc/boot/dtc-src/.gitignore | 3 --- 2 files changed, 4 deletions(-) delete mode 100644 arch/powerpc/boot/dtc-src/.gitignore diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore index 3d80c3e9cf60..12da77ec0228 100644 --- a/arch/powerpc/boot/.gitignore +++ b/arch/powerpc/boot/.gitignore @@ -1,5 +1,4 @@ addnote -dtc empty.c hack-coff infblock.c diff --git a/arch/powerpc/boot/dtc-src/.gitignore b/arch/powerpc/boot/dtc-src/.gitignore deleted file mode 100644 index a7c3f94e5e75..000000000000 --- a/arch/powerpc/boot/dtc-src/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -dtc-lexer.lex.c -dtc-parser.tab.c -dtc-parser.tab.h From 9c81075f436f867f580c2edf2350c0898cffc9d0 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Wed, 8 Jun 2011 17:59:30 -0500 Subject: [PATCH 226/595] MD: support initial bitmap creation in-kernel Add bitmap support to the device-mapper specific metadata area. This patch allows the creation of the bitmap metadata area upon initial array creation via device-mapper. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 93 ++++++++++++++++++++++++++++++++++++++++++--- drivers/md/md.h | 1 + 2 files changed, 89 insertions(+), 5 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 70bd738b8b99..f0769b34d656 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -534,6 +534,82 @@ void bitmap_print_sb(struct bitmap *bitmap) kunmap_atomic(sb, KM_USER0); } +/* + * bitmap_new_disk_sb + * @bitmap + * + * This function is somewhat the reverse of bitmap_read_sb. bitmap_read_sb + * reads and verifies the on-disk bitmap superblock and populates bitmap_info. + * This function verifies 'bitmap_info' and populates the on-disk bitmap + * structure, which is to be written to disk. + * + * Returns: 0 on success, -Exxx on error + */ +static int bitmap_new_disk_sb(struct bitmap *bitmap) +{ + bitmap_super_t *sb; + unsigned long chunksize, daemon_sleep, write_behind; + int err = -EINVAL; + + bitmap->sb_page = alloc_page(GFP_KERNEL); + if (IS_ERR(bitmap->sb_page)) { + err = PTR_ERR(bitmap->sb_page); + bitmap->sb_page = NULL; + return err; + } + bitmap->sb_page->index = 0; + + sb = kmap_atomic(bitmap->sb_page, KM_USER0); + + sb->magic = cpu_to_le32(BITMAP_MAGIC); + sb->version = cpu_to_le32(BITMAP_MAJOR_HI); + + chunksize = bitmap->mddev->bitmap_info.chunksize; + BUG_ON(!chunksize); + if (!is_power_of_2(chunksize)) { + kunmap_atomic(sb, KM_USER0); + printk(KERN_ERR "bitmap chunksize not a power of 2\n"); + return -EINVAL; + } + sb->chunksize = cpu_to_le32(chunksize); + + daemon_sleep = bitmap->mddev->bitmap_info.daemon_sleep; + if (!daemon_sleep || + (daemon_sleep < 1) || (daemon_sleep > MAX_SCHEDULE_TIMEOUT)) { + printk(KERN_INFO "Choosing daemon_sleep default (5 sec)\n"); + daemon_sleep = 5 * HZ; + } + sb->daemon_sleep = cpu_to_le32(daemon_sleep); + bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep; + + /* + * FIXME: write_behind for RAID1. If not specified, what + * is a good choice? We choose COUNTER_MAX / 2 arbitrarily. + */ + write_behind = bitmap->mddev->bitmap_info.max_write_behind; + if (write_behind > COUNTER_MAX) + write_behind = COUNTER_MAX / 2; + sb->write_behind = cpu_to_le32(write_behind); + bitmap->mddev->bitmap_info.max_write_behind = write_behind; + + /* keep the array size field of the bitmap superblock up to date */ + sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors); + + memcpy(sb->uuid, bitmap->mddev->uuid, 16); + + bitmap->flags |= BITMAP_STALE; + sb->state |= cpu_to_le32(BITMAP_STALE); + bitmap->events_cleared = bitmap->mddev->events; + sb->events_cleared = cpu_to_le64(bitmap->mddev->events); + + bitmap->flags |= BITMAP_HOSTENDIAN; + sb->version = cpu_to_le32(BITMAP_MAJOR_HOSTENDIAN); + + kunmap_atomic(sb, KM_USER0); + + return 0; +} + /* read the superblock from the bitmap file and initialize some bitmap fields */ static int bitmap_read_sb(struct bitmap *bitmap) { @@ -1076,8 +1152,8 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) } printk(KERN_INFO "%s: bitmap initialized from disk: " - "read %lu/%lu pages, set %lu bits\n", - bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt); + "read %lu/%lu pages, set %lu of %lu bits\n", + bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt, chunks); return 0; @@ -1728,9 +1804,16 @@ int bitmap_create(mddev_t *mddev) vfs_fsync(file, 1); } /* read superblock from bitmap file (this sets mddev->bitmap_info.chunksize) */ - if (!mddev->bitmap_info.external) - err = bitmap_read_sb(bitmap); - else { + if (!mddev->bitmap_info.external) { + /* + * If 'MD_ARRAY_FIRST_USE' is set, then device-mapper is + * instructing us to create a new on-disk bitmap instance. + */ + if (test_and_clear_bit(MD_ARRAY_FIRST_USE, &mddev->flags)) + err = bitmap_new_disk_sb(bitmap); + else + err = bitmap_read_sb(bitmap); + } else { err = 0; if (mddev->bitmap_info.chunksize == 0 || mddev->bitmap_info.daemon_sleep == 0) diff --git a/drivers/md/md.h b/drivers/md/md.h index 5e35535ab7c3..1c26c7a08ae6 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -124,6 +124,7 @@ struct mddev_s #define MD_CHANGE_DEVS 0 /* Some device status has changed */ #define MD_CHANGE_CLEAN 1 /* transition to or from 'clean' */ #define MD_CHANGE_PENDING 2 /* switch from 'clean' to 'active' in progress */ +#define MD_ARRAY_FIRST_USE 3 /* First use of array, needs initialization */ int suspended; atomic_t active_io; From d6b212f4b19da5301e6b6eca562e5c7a2a6e8c8d Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Wed, 8 Jun 2011 18:00:28 -0500 Subject: [PATCH 227/595] MD: raid5 do not set fullsync Add check to determine if a device needs full resync or if partial resync will do RAID 5 was assuming that if a device was not In_sync, it must undergo a full resync. We add a check to see if 'saved_raid_disk' is the same as 'raid_disk'. If it is, we can safely skip the full resync and rely on the bitmap for partial recovery instead. This is the legitimate purpose of 'saved_raid_disk', from md.h: int saved_raid_disk; /* role that device used to have in the * array and could again if we did a partial * resync from the bitmap */ Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/raid5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 346e69bfdab3..f9d2fbc64977 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4858,7 +4858,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev) printk(KERN_INFO "md/raid:%s: device %s operational as raid" " disk %d\n", mdname(mddev), bdevname(rdev->bdev, b), raid_disk); - } else + } else if (rdev->saved_raid_disk != raid_disk) /* Cannot rely on bitmap to complete recovery */ conf->fullsync = 1; } From d744540cd39e93976c4c8401e140232444ef3b0b Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Wed, 8 Jun 2011 18:01:10 -0500 Subject: [PATCH 228/595] MD: use is_power_of_2 macro Make use of is_power_of_2 macro. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index f0769b34d656..7fc028f9701e 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -651,7 +651,7 @@ static int bitmap_read_sb(struct bitmap *bitmap) reason = "unrecognized superblock version"; else if (chunksize < 512) reason = "bitmap chunksize too small"; - else if ((1 << ffz(~chunksize)) != chunksize) + else if (!is_power_of_2(chunksize)) reason = "bitmap chunksize not a power of 2"; else if (daemon_sleep < 1 || daemon_sleep > MAX_SCHEDULE_TIMEOUT) reason = "daemon sleep period out of range"; From 9864c0053d3da4c5731ac8a6c4835179310bd40a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E5=BB=BA=E6=9C=8B?= Date: Thu, 9 Jun 2011 11:42:48 +1000 Subject: [PATCH 229/595] md: Using poll /proc/mdstat can monitor the events of adding a spare disks Signed-off-by: majianpeng Signed-off-by: NeilBrown --- drivers/md/md.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index 9160463b5f68..734bc0996390 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5274,6 +5274,8 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) if (mddev->degraded) set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + if (!err) + md_new_event(mddev); md_wakeup_thread(mddev->thread); return err; } From 01393f3d5836b7d62e925e6f4658a7eb22b83a11 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 9 Jun 2011 11:42:54 +1000 Subject: [PATCH 230/595] md: check ->hot_remove_disk when removing disk Check pers->hot_remove_disk instead of pers->hot_add_disk in slot_store() during disk removal. The linear personality only has ->hot_add_disk and no ->hot_remove_disk, so that removing disk in the array resulted to following kernel bug: $ sudo mdadm --create /dev/md0 --level=linear --raid-devices=4 /dev/loop[0-3] $ echo none | sudo tee /sys/block/md0/md/dev-loop2/slot BUG: unable to handle kernel NULL pointer dereference at (null) IP: [< (null)>] (null) PGD c9f5d067 PUD 8575a067 PMD 0 Oops: 0010 [#1] SMP CPU 2 Modules linked in: linear loop bridge stp llc kvm_intel kvm asus_atk0110 sr_mod cdrom sg Pid: 10450, comm: tee Not tainted 3.0.0-rc1-leonard+ #173 System manufacturer System Product Name/P5G41TD-M PRO RIP: 0010:[<0000000000000000>] [< (null)>] (null) RSP: 0018:ffff880085757df0 EFLAGS: 00010282 RAX: ffffffffa00168e0 RBX: ffff8800d1431800 RCX: 000000000000006e RDX: 0000000000000001 RSI: 0000000000000002 RDI: ffff88008543c000 RBP: ffff880085757e48 R08: 0000000000000002 R09: 000000000000000a R10: 0000000000000000 R11: ffff88008543c2e0 R12: 00000000ffffffff R13: ffff8800b4641000 R14: 0000000000000005 R15: 0000000000000000 FS: 00007fe8c9e05700(0000) GS:ffff88011fa00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000000 CR3: 00000000b4502000 CR4: 00000000000406e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process tee (pid: 10450, threadinfo ffff880085756000, task ffff8800c9f08000) Stack: ffffffff8138496a ffff8800b4641000 ffff88008543c268 0000000000000000 ffff8800b4641000 ffff88008543c000 ffff8800d1431868 ffffffff81a78a90 ffff8800b4641000 ffff88008543c000 ffff8800d1431800 ffff880085757e98 Call Trace: [] ? slot_store+0xaa/0x265 [] rdev_attr_store+0x89/0xa8 [] sysfs_write_file+0x108/0x144 [] vfs_write+0xb1/0x10d [] ? trace_hardirqs_on_caller+0x111/0x135 [] sys_write+0x4d/0x77 [] system_call_fastpath+0x16/0x1b Code: Bad RIP value. RIP [< (null)>] (null) RSP CR2: 0000000000000000 ---[ end trace ba5fc64319a826fb ]--- Signed-off-by: Namhyung Kim Cc: stable@kernel.org Signed-off-by: NeilBrown --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 734bc0996390..4332fc2f25d4 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2476,7 +2476,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) if (rdev->raid_disk == -1) return -EEXIST; /* personality does all needed checks */ - if (rdev->mddev->pers->hot_add_disk == NULL) + if (rdev->mddev->pers->hot_remove_disk == NULL) return -EINVAL; err = rdev->mddev->pers-> hot_remove_disk(rdev->mddev, rdev->raid_disk); From 27d5ea04d08bea37bf651090e5f3c573d2390df8 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 9 Jun 2011 11:42:57 +1000 Subject: [PATCH 231/595] md/bitmap: use proper accessor macro Use COUNTER()/NEEDED() macro instead of open-coding them. Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 7fc028f9701e..663e6051bbad 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1408,7 +1408,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect return 0; } - if (unlikely((*bmc & COUNTER_MAX) == COUNTER_MAX)) { + if (unlikely(COUNTER(*bmc) == COUNTER_MAX)) { DEFINE_WAIT(__wait); /* note that it is safe to do the prepare_to_wait * after the test as long as we do it before dropping @@ -1480,10 +1480,10 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto sysfs_notify_dirent_safe(bitmap->sysfs_can_clear); } - if (!success && ! (*bmc & NEEDED_MASK)) + if (!success && !NEEDED(*bmc)) *bmc |= NEEDED_MASK; - if ((*bmc & COUNTER_MAX) == COUNTER_MAX) + if (COUNTER(*bmc) == COUNTER_MAX) wake_up(&bitmap->overflow_wait); (*bmc)--; From 97b3d4aacfbd7186faf34597fcf1f55b8579be17 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 9 Jun 2011 11:43:01 +1000 Subject: [PATCH 232/595] md/bitmap: remove unused fields from struct bitmap Get rid of ->syncchunk and ->counter_bits since they're never used. Also discard COUNTER_BYTE_RATIO which is unused. Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 3 --- drivers/md/bitmap.h | 10 ---------- 2 files changed, 13 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 663e6051bbad..574b09afedd3 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1837,9 +1837,6 @@ int bitmap_create(mddev_t *mddev) bitmap->chunks = chunks; bitmap->pages = pages; bitmap->missing_pages = pages; - bitmap->counter_bits = COUNTER_BITS; - - bitmap->syncchunk = ~0UL; #ifdef INJECT_FATAL_FAULT_1 bitmap->bp = NULL; diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h index d0aeaf46d932..b2a127e891ac 100644 --- a/drivers/md/bitmap.h +++ b/drivers/md/bitmap.h @@ -85,7 +85,6 @@ typedef __u16 bitmap_counter_t; #define COUNTER_BITS 16 #define COUNTER_BIT_SHIFT 4 -#define COUNTER_BYTE_RATIO (COUNTER_BITS / 8) #define COUNTER_BYTE_SHIFT (COUNTER_BIT_SHIFT - 3) #define NEEDED_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 1))) @@ -196,19 +195,10 @@ struct bitmap { mddev_t *mddev; /* the md device that the bitmap is for */ - int counter_bits; /* how many bits per block counter */ - /* bitmap chunksize -- how much data does each bit represent? */ unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */ unsigned long chunks; /* total number of data chunks for the array */ - /* We hold a count on the chunk currently being synced, and drop - * it when the last block is started. If the resync is aborted - * midway, we need to be able to drop that count, so we remember - * the counted chunk.. - */ - unsigned long syncchunk; - __u64 events_cleared; int need_sync; From f699bf2328521cc3e20c412fcdb9ffe1255c360f Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 9 Jun 2011 11:43:04 +1000 Subject: [PATCH 233/595] md:Documentation/md.txt - fix typo Reported-by: CoolCold Signed-off-by: NeilBrown --- Documentation/md.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/md.txt b/Documentation/md.txt index 2366b1c8cf19..f0eee83ff78a 100644 --- a/Documentation/md.txt +++ b/Documentation/md.txt @@ -555,7 +555,7 @@ also have sync_min sync_max The two values, given as numbers of sectors, indicate a range - withing the array where 'check'/'repair' will operate. Must be + within the array where 'check'/'repair' will operate. Must be a multiple of chunk_size. When it reaches "sync_max" it will pause, rather than complete. You can use 'select' or 'poll' on "sync_completed" to wait for From 1780f2d3839a0d3eb85ee014a708f9e2c8f8ba0e Mon Sep 17 00:00:00 2001 From: John Johansen Date: Wed, 8 Jun 2011 15:07:47 -0700 Subject: [PATCH 234/595] AppArmor: Fix sleep in invalid context from task_setrlimit Affected kernels 2.6.36 - 3.0 AppArmor may do a GFP_KERNEL memory allocation with task_lock(tsk->group_leader); held when called from security_task_setrlimit. This will only occur when the task's current policy has been replaced, and the task's creds have not been updated before entering the LSM security_task_setrlimit() hook. BUG: sleeping function called from invalid context at mm/slub.c:847 in_atomic(): 1, irqs_disabled(): 0, pid: 1583, name: cupsd 2 locks held by cupsd/1583: #0: (tasklist_lock){.+.+.+}, at: [] do_prlimit+0x61/0x189 #1: (&(&p->alloc_lock)->rlock){+.+.+.}, at: [] do_prlimit+0x94/0x189 Pid: 1583, comm: cupsd Not tainted 3.0.0-rc2-git1 #7 Call Trace: [] __might_sleep+0x10d/0x112 [] slab_pre_alloc_hook.isra.49+0x2d/0x33 [] kmem_cache_alloc+0x22/0x132 [] prepare_creds+0x35/0xe4 [] aa_replace_current_profile+0x35/0xb2 [] aa_current_profile+0x45/0x4c [] apparmor_task_setrlimit+0x19/0x3a [] security_task_setrlimit+0x11/0x13 [] do_prlimit+0xd2/0x189 [] sys_setrlimit+0x3b/0x48 [] system_call_fastpath+0x16/0x1b Signed-off-by: John Johansen Reported-by: Miles Lane Cc: stable@kernel.org Signed-off-by: James Morris --- security/apparmor/lsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index ec1bcecf2cda..3d2fd141dff7 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -612,7 +612,7 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, static int apparmor_task_setrlimit(struct task_struct *task, unsigned int resource, struct rlimit *new_rlim) { - struct aa_profile *profile = aa_current_profile(); + struct aa_profile *profile = __aa_current_profile(); int error = 0; if (!unconfined(profile)) From 618c75e491a5a50cd3819eaf5f853fd87df3ae42 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 3 Jun 2011 12:54:14 +0200 Subject: [PATCH 235/595] drm: fix fbs in DRM_IOCTL_MODE_GETRESOURCES ioctl The DRM_IOCTL_MODE_GETRESOURCES ioctl just returns bogus framebuffers. That is because the framebuffers for each file are in the filp_head member of struct drm_framebuffer, not in the head member. Signed-off-by: Sascha Hauer Signed-off-by: Dave Airlie --- 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 872747c5a544..21058e6ad2b8 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1113,7 +1113,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data, if (card_res->count_fbs >= fb_count) { copied = 0; fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr; - list_for_each_entry(fb, &file_priv->fbs, head) { + list_for_each_entry(fb, &file_priv->fbs, filp_head) { if (put_user(fb->base.id, fb_id + copied)) { ret = -EFAULT; goto out; From b20f9bef8d9ff54be266062eae365ebf4b12ca64 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 8 Jun 2011 13:01:11 -0400 Subject: [PATCH 236/595] drm/radeon/kms: check modes against max pixel clock Filter out modes that are higher than the max pixel clock. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_atombios.c | 4 ++++ drivers/gpu/drm/radeon/radeon_clocks.c | 8 +++++--- drivers/gpu/drm/radeon/radeon_combios.c | 5 +++++ drivers/gpu/drm/radeon/radeon_connectors.c | 13 ++++++++++++- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index ba643b576054..27f45579e64b 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -165,6 +165,7 @@ struct radeon_clock { uint32_t default_sclk; uint32_t default_dispclk; uint32_t dp_extclk; + uint32_t max_pixel_clock; }; /* diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 90dfb2b8cf03..fa62a503ae70 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1246,6 +1246,10 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) } *dcpll = *p1pll; + rdev->clock.max_pixel_clock = le16_to_cpu(firmware_info->info.usMaxPixelClock); + if (rdev->clock.max_pixel_clock == 0) + rdev->clock.max_pixel_clock = 40000; + return true; } diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index 5249af8931e6..2d48e7a1474b 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c @@ -117,7 +117,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; if (p1pll->reference_div < 2) p1pll->reference_div = 12; - p2pll->reference_div = p1pll->reference_div; + p2pll->reference_div = p1pll->reference_div; /* These aren't in the device-tree */ if (rdev->family >= CHIP_R420) { @@ -139,6 +139,8 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) p2pll->pll_out_min = 12500; p2pll->pll_out_max = 35000; } + /* not sure what the max should be in all cases */ + rdev->clock.max_pixel_clock = 35000; spll->reference_freq = mpll->reference_freq = p1pll->reference_freq; spll->reference_div = mpll->reference_div = @@ -151,7 +153,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) else rdev->clock.default_sclk = radeon_legacy_get_engine_clock(rdev); - + val = of_get_property(dp, "ATY,MCLK", NULL); if (val && *val) rdev->clock.default_mclk = (*val) / 10; @@ -160,7 +162,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) radeon_legacy_get_memory_clock(rdev); DRM_INFO("Using device-tree clock info\n"); - + return true; } #else diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 5b991f7c6e2a..d1b95b70af61 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -866,6 +866,11 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) rdev->clock.default_sclk = sclk; rdev->clock.default_mclk = mclk; + if (RBIOS32(pll_info + 0x16)) + rdev->clock.max_pixel_clock = RBIOS32(pll_info + 0x16); + else + rdev->clock.max_pixel_clock = 35000; /* might need something asic specific */ + return true; } return false; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index ee1dccb3fec9..9c2929c7e79f 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -626,8 +626,14 @@ static int radeon_vga_get_modes(struct drm_connector *connector) static int radeon_vga_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + /* XXX check mode bandwidth */ - /* XXX verify against max DAC output frequency */ + + if ((mode->clock / 10) > rdev->clock.max_pixel_clock) + return MODE_CLOCK_HIGH; + return MODE_OK; } @@ -1015,6 +1021,11 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector, } else return MODE_CLOCK_HIGH; } + + /* check against the max pixel clock */ + if ((mode->clock / 10) > rdev->clock.max_pixel_clock) + return MODE_CLOCK_HIGH; + return MODE_OK; } From 303c805cb4dc1f5bc1d21f1c3757da0eae1e4f84 Mon Sep 17 00:00:00 2001 From: Ilija Hadzic Date: Tue, 7 Jun 2011 14:54:48 -0400 Subject: [PATCH 237/595] drm/radeon: fix GUI idle IH debug statements debug statement for GUI idle interrupt is wrong and incorrectly reports CP EOP interrupt; trivial issue, but confusing for someone trying to distinguish interrupt sources while debugging ... fixed Signed-off-by: Ilija Hadzic Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 2 +- drivers/gpu/drm/radeon/r600.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 98ea597bc76d..86157b172c88 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2944,7 +2944,7 @@ int evergreen_irq_process(struct radeon_device *rdev) radeon_fence_process(rdev); break; case 233: /* GUI IDLE */ - DRM_DEBUG("IH: CP EOP\n"); + DRM_DEBUG("IH: GUI idle\n"); rdev->pm.gui_idle = true; wake_up(&rdev->irq.idle_queue); break; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index d74d4d71437f..7dd45ca64e29 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3444,7 +3444,7 @@ int r600_irq_process(struct radeon_device *rdev) radeon_fence_process(rdev); break; case 233: /* GUI IDLE */ - DRM_DEBUG("IH: CP EOP\n"); + DRM_DEBUG("IH: GUI idle\n"); rdev->pm.gui_idle = true; wake_up(&rdev->irq.idle_queue); break; From 72ba4cb608e7937792f3d61349ef616bbffda832 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 9 Jun 2011 04:26:31 +0000 Subject: [PATCH 238/595] video: s3c-fb: fix misleading kfree in remove function This patch fixes misleading kfree in remove function. Signed-off-by: Jingoo Han Signed-off-by: Paul Mundt --- drivers/video/s3c-fb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 0352afa49a39..148e19dbdbc5 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -1487,11 +1487,10 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev) release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res)); - kfree(sfb); - pm_runtime_put_sync(sfb->dev); pm_runtime_disable(sfb->dev); + kfree(sfb); return 0; } From 13e6af8886f3225fb9141dc3b6915d84bd4ad4de Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 9 Jun 2011 04:26:38 +0000 Subject: [PATCH 239/595] video: s3c-fb: fix virtual resolution checking This patch fixes mishandling in virtual resolution checking. Previously, virtual resolution is changed to virtual_x and virtual_y which mean the size for buffer allocation, when s3c_fb_check_var is called by fb_check_var. However, it is meaningless, since virtual_x and virtual_y are fixed and user cannot change virtual resolution. Therefore, virtual resolution should be more than resolution such as xres and yres. Signed-off-by: Jingoo Han Signed-off-by: Paul Mundt --- drivers/video/s3c-fb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 148e19dbdbc5..dfc2b64dde25 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -235,13 +235,12 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct s3c_fb_win *win = info->par; - struct s3c_fb_pd_win *windata = win->windata; struct s3c_fb *sfb = win->parent; dev_dbg(sfb->dev, "checking parameters\n"); - var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres); - var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres); + var->xres_virtual = max(var->xres_virtual, var->xres); + var->yres_virtual = max(var->yres_virtual, var->yres); if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) { dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n", From fab7c5b778b1e0ee89e75679b2d6a1405318bb11 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 9 Jun 2011 04:26:45 +0000 Subject: [PATCH 240/595] video: s3c-fb: move enabling channel for window This patch moves enabling channel for window, because there should be enabling channel before enabling window. If the sequence is reversed, it makes the problem in displaying images to lcd panel. Signed-off-by: Jingoo Han Signed-off-by: Paul Mundt --- drivers/video/s3c-fb.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index dfc2b64dde25..4aecf213c9be 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -557,6 +557,13 @@ static int s3c_fb_set_par(struct fb_info *info) vidosd_set_alpha(win, alpha); vidosd_set_size(win, data); + /* Enable DMA channel for this window */ + if (sfb->variant.has_shadowcon) { + data = readl(sfb->regs + SHADOWCON); + data |= SHADOWCON_CHx_ENABLE(win_no); + writel(data, sfb->regs + SHADOWCON); + } + data = WINCONx_ENWIN; /* note, since we have to round up the bits-per-pixel, we end up @@ -636,13 +643,6 @@ static int s3c_fb_set_par(struct fb_info *info) writel(data, regs + sfb->variant.wincon + (win_no * 4)); writel(0x0, regs + sfb->variant.winmap + (win_no * 4)); - /* Enable DMA channel for this window */ - if (sfb->variant.has_shadowcon) { - data = readl(sfb->regs + SHADOWCON); - data |= SHADOWCON_CHx_ENABLE(win_no); - writel(data, sfb->regs + SHADOWCON); - } - shadow_protect_win(win, 0); return 0; From 307cfe715344e15eda12dad3bb14f794115ca823 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 9 Jun 2011 16:52:38 +1000 Subject: [PATCH 241/595] powerpc: Force page alignment for initrd reserved memory When using 64K pages with a separate cpio rootfs, U-Boot will align the rootfs on a 4K page boundary. When the memory is reserved, and subsequent early memblock_alloc is called, it will allocate memory between the 64K page alignment and reserved memory. When the reserved memory is subsequently freed, it is done so by pages, causing the early memblock_alloc requests to be re-used, which in my case, caused the device-tree to be clobbered. This patch forces the reserved memory for initrd to be kernel page aligned, and will move the device tree if it overlaps with the range extension of initrd. This patch will also consolidate the identical function free_initrd_mem() from mm/init_32.c, init_64.c to mm/mem.c, and adds the same range extension when freeing initrd. free_initrd_mem() is also moved to the __init section. Many thanks to Milton Miller for his input on this patch. [BenH: Fixed build without CONFIG_BLK_DEV_INITRD] Signed-off-by: Dave Carroll Cc: Benjamin Herrenschmidt Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/prom.c | 27 ++++++++++++++++++++++++--- arch/powerpc/mm/init_32.c | 15 --------------- arch/powerpc/mm/init_64.c | 14 -------------- arch/powerpc/mm/mem.c | 19 +++++++++++++++++++ 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index f2c906b1d8d3..8c3112a57cf2 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -82,11 +82,29 @@ static int __init early_parse_mem(char *p) } early_param("mem", early_parse_mem); +/* + * overlaps_initrd - check for overlap with page aligned extension of + * initrd. + */ +static inline int overlaps_initrd(unsigned long start, unsigned long size) +{ +#ifdef CONFIG_BLK_DEV_INITRD + if (!initrd_start) + return 0; + + return (start + size) > _ALIGN_DOWN(initrd_start, PAGE_SIZE) && + start <= _ALIGN_UP(initrd_end, PAGE_SIZE); +#else + return 0; +#endif +} + /** * move_device_tree - move tree to an unused area, if needed. * * The device tree may be allocated beyond our memory limit, or inside the - * crash kernel region for kdump. If so, move it out of the way. + * crash kernel region for kdump, or within the page aligned range of initrd. + * If so, move it out of the way. */ static void __init move_device_tree(void) { @@ -99,7 +117,8 @@ static void __init move_device_tree(void) size = be32_to_cpu(initial_boot_params->totalsize); if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) || - overlaps_crashkernel(start, size)) { + overlaps_crashkernel(start, size) || + overlaps_initrd(start, size)) { p = __va(memblock_alloc(size, PAGE_SIZE)); memcpy(p, initial_boot_params, size); initial_boot_params = (struct boot_param_header *)p; @@ -555,7 +574,9 @@ static void __init early_reserve_mem(void) #ifdef CONFIG_BLK_DEV_INITRD /* then reserve the initrd, if any */ if (initrd_start && (initrd_end > initrd_start)) - memblock_reserve(__pa(initrd_start), initrd_end - initrd_start); + memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE), + _ALIGN_UP(initrd_end, PAGE_SIZE) - + _ALIGN_DOWN(initrd_start, PAGE_SIZE)); #endif /* CONFIG_BLK_DEV_INITRD */ #ifdef CONFIG_PPC32 diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index d65b591e5556..5de0f254dbb5 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c @@ -223,21 +223,6 @@ void free_initmem(void) #undef FREESEC } -#ifdef CONFIG_BLK_DEV_INITRD -void free_initrd_mem(unsigned long start, unsigned long end) -{ - if (start < end) - printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); - for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(virt_to_page(start)); - init_page_count(virt_to_page(start)); - free_page(start); - totalram_pages++; - } -} -#endif - - #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */ void setup_initial_memory_limit(phys_addr_t first_memblock_base, phys_addr_t first_memblock_size) diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 6374b2196a17..f6dbb4c20e64 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -99,20 +99,6 @@ void free_initmem(void) ((unsigned long)__init_end - (unsigned long)__init_begin) >> 10); } -#ifdef CONFIG_BLK_DEV_INITRD -void free_initrd_mem(unsigned long start, unsigned long end) -{ - if (start < end) - printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); - for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(virt_to_page(start)); - init_page_count(virt_to_page(start)); - free_page(start); - totalram_pages++; - } -} -#endif - static void pgd_ctor(void *addr) { memset(addr, 0, PGD_TABLE_SIZE); diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 57e545b84bf1..29d4dde65c45 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -382,6 +382,25 @@ void __init mem_init(void) mem_init_done = 1; } +#ifdef CONFIG_BLK_DEV_INITRD +void __init free_initrd_mem(unsigned long start, unsigned long end) +{ + if (start >= end) + return; + + start = _ALIGN_DOWN(start, PAGE_SIZE); + end = _ALIGN_UP(end, PAGE_SIZE); + pr_info("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); + + for (; start < end; start += PAGE_SIZE) { + ClearPageReserved(virt_to_page(start)); + init_page_count(virt_to_page(start)); + free_page(start); + totalram_pages++; + } +} +#endif + /* * This is called when a page has been modified by the kernel. * It just marks the page as not i-cache clean. We do the i-cache From 6c43e0465f56248d9da56f2c4665ce1696766814 Mon Sep 17 00:00:00 2001 From: Wu Jiajun-B06378 Date: Tue, 7 Jun 2011 21:46:51 +0000 Subject: [PATCH 242/595] gianfar:localized filer table Each eTSEC device should own localized filer table. Signed-off-by: Jiajun Wu Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 29 +++++++--------- drivers/net/gianfar.h | 8 +++-- drivers/net/gianfar_ethtool.c | 64 ++++++++++++++++++----------------- 3 files changed, 51 insertions(+), 50 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index ff60b23a5b74..2dfcc8047847 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -10,7 +10,7 @@ * Maintainer: Kumar Gala * Modifier: Sandeep Gopalpet * - * Copyright 2002-2009 Freescale Semiconductor, Inc. + * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc. * Copyright 2007 MontaVista Software, Inc. * * This program is free software; you can redistribute it and/or modify it @@ -476,9 +476,6 @@ static const struct net_device_ops gfar_netdev_ops = { #endif }; -unsigned int ftp_rqfpr[MAX_FILER_IDX + 1]; -unsigned int ftp_rqfcr[MAX_FILER_IDX + 1]; - void lock_rx_qs(struct gfar_private *priv) { int i = 0x0; @@ -868,28 +865,28 @@ static u32 cluster_entry_per_class(struct gfar_private *priv, u32 rqfar, rqfar--; rqfcr = RQFCR_CLE | RQFCR_PID_MASK | RQFCR_CMP_EXACT; - ftp_rqfpr[rqfar] = rqfpr; - ftp_rqfcr[rqfar] = rqfcr; + priv->ftp_rqfpr[rqfar] = rqfpr; + priv->ftp_rqfcr[rqfar] = rqfcr; gfar_write_filer(priv, rqfar, rqfcr, rqfpr); rqfar--; rqfcr = RQFCR_CMP_NOMATCH; - ftp_rqfpr[rqfar] = rqfpr; - ftp_rqfcr[rqfar] = rqfcr; + priv->ftp_rqfpr[rqfar] = rqfpr; + priv->ftp_rqfcr[rqfar] = rqfcr; gfar_write_filer(priv, rqfar, rqfcr, rqfpr); rqfar--; rqfcr = RQFCR_CMP_EXACT | RQFCR_PID_PARSE | RQFCR_CLE | RQFCR_AND; rqfpr = class; - ftp_rqfcr[rqfar] = rqfcr; - ftp_rqfpr[rqfar] = rqfpr; + priv->ftp_rqfcr[rqfar] = rqfcr; + priv->ftp_rqfpr[rqfar] = rqfpr; gfar_write_filer(priv, rqfar, rqfcr, rqfpr); rqfar--; rqfcr = RQFCR_CMP_EXACT | RQFCR_PID_MASK | RQFCR_AND; rqfpr = class; - ftp_rqfcr[rqfar] = rqfcr; - ftp_rqfpr[rqfar] = rqfpr; + priv->ftp_rqfcr[rqfar] = rqfcr; + priv->ftp_rqfpr[rqfar] = rqfpr; gfar_write_filer(priv, rqfar, rqfcr, rqfpr); return rqfar; @@ -904,8 +901,8 @@ static void gfar_init_filer_table(struct gfar_private *priv) /* Default rule */ rqfcr = RQFCR_CMP_MATCH; - ftp_rqfcr[rqfar] = rqfcr; - ftp_rqfpr[rqfar] = rqfpr; + priv->ftp_rqfcr[rqfar] = rqfcr; + priv->ftp_rqfpr[rqfar] = rqfpr; gfar_write_filer(priv, rqfar, rqfcr, rqfpr); rqfar = cluster_entry_per_class(priv, rqfar, RQFPR_IPV6); @@ -921,8 +918,8 @@ static void gfar_init_filer_table(struct gfar_private *priv) /* Rest are masked rules */ rqfcr = RQFCR_CMP_NOMATCH; for (i = 0; i < rqfar; i++) { - ftp_rqfcr[i] = rqfcr; - ftp_rqfpr[i] = rqfpr; + priv->ftp_rqfcr[i] = rqfcr; + priv->ftp_rqfpr[i] = rqfpr; gfar_write_filer(priv, i, rqfcr, rqfpr); } } diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index fc86f5195445..ba36dc7a3435 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -9,7 +9,7 @@ * Maintainer: Kumar Gala * Modifier: Sandeep Gopalpet * - * Copyright 2002-2009 Freescale Semiconductor, Inc. + * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -1107,10 +1107,12 @@ struct gfar_private { /* HW time stamping enabled flag */ int hwts_rx_en; int hwts_tx_en; + + /*Filer table*/ + unsigned int ftp_rqfpr[MAX_FILER_IDX + 1]; + unsigned int ftp_rqfcr[MAX_FILER_IDX + 1]; }; -extern unsigned int ftp_rqfpr[MAX_FILER_IDX + 1]; -extern unsigned int ftp_rqfcr[MAX_FILER_IDX + 1]; static inline int gfar_has_errata(struct gfar_private *priv, enum gfar_errata err) diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 493d743839d9..239e3330495f 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -9,7 +9,7 @@ * Maintainer: Kumar Gala * Modifier: Sandeep Gopalpet * - * Copyright 2003-2006, 2008-2009 Freescale Semiconductor, Inc. + * Copyright 2003-2006, 2008-2009, 2011 Freescale Semiconductor, Inc. * * This software may be used and distributed according to * the terms of the GNU Public License, Version 2, incorporated herein @@ -609,15 +609,15 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) if (ethflow & RXH_L2DA) { fcr = RQFCR_PID_DAH |RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; fcr = RQFCR_PID_DAL | RQFCR_AND | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; } @@ -626,16 +626,16 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) fcr = RQFCR_PID_VID | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; priv->cur_filer_idx = priv->cur_filer_idx - 1; } if (ethflow & RXH_IP_SRC) { fcr = RQFCR_PID_SIA | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; } @@ -643,8 +643,8 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) if (ethflow & (RXH_IP_DST)) { fcr = RQFCR_PID_DIA | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; } @@ -652,8 +652,8 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) if (ethflow & RXH_L3_PROTO) { fcr = RQFCR_PID_L4P | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; } @@ -661,8 +661,8 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) if (ethflow & RXH_L4_B_0_1) { fcr = RQFCR_PID_SPT | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; } @@ -670,8 +670,8 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) if (ethflow & RXH_L4_B_2_3) { fcr = RQFCR_PID_DPT | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; - ftp_rqfpr[priv->cur_filer_idx] = fpr; - ftp_rqfcr[priv->cur_filer_idx] = fcr; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; } @@ -705,12 +705,12 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u } for (i = 0; i < MAX_FILER_IDX + 1; i++) { - local_rqfpr[j] = ftp_rqfpr[i]; - local_rqfcr[j] = ftp_rqfcr[i]; + local_rqfpr[j] = priv->ftp_rqfpr[i]; + local_rqfcr[j] = priv->ftp_rqfcr[i]; j--; - if ((ftp_rqfcr[i] == (RQFCR_PID_PARSE | + if ((priv->ftp_rqfcr[i] == (RQFCR_PID_PARSE | RQFCR_CLE |RQFCR_AND)) && - (ftp_rqfpr[i] == cmp_rqfpr)) + (priv->ftp_rqfpr[i] == cmp_rqfpr)) break; } @@ -724,20 +724,22 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u * if it was already programmed, we need to overwrite these rules */ for (l = i+1; l < MAX_FILER_IDX; l++) { - if ((ftp_rqfcr[l] & RQFCR_CLE) && - !(ftp_rqfcr[l] & RQFCR_AND)) { - ftp_rqfcr[l] = RQFCR_CLE | RQFCR_CMP_EXACT | + if ((priv->ftp_rqfcr[l] & RQFCR_CLE) && + !(priv->ftp_rqfcr[l] & RQFCR_AND)) { + priv->ftp_rqfcr[l] = RQFCR_CLE | RQFCR_CMP_EXACT | RQFCR_HASHTBL_0 | RQFCR_PID_MASK; - ftp_rqfpr[l] = FPR_FILER_MASK; - gfar_write_filer(priv, l, ftp_rqfcr[l], ftp_rqfpr[l]); + priv->ftp_rqfpr[l] = FPR_FILER_MASK; + gfar_write_filer(priv, l, priv->ftp_rqfcr[l], + priv->ftp_rqfpr[l]); break; } - if (!(ftp_rqfcr[l] & RQFCR_CLE) && (ftp_rqfcr[l] & RQFCR_AND)) + if (!(priv->ftp_rqfcr[l] & RQFCR_CLE) && + (priv->ftp_rqfcr[l] & RQFCR_AND)) continue; else { - local_rqfpr[j] = ftp_rqfpr[l]; - local_rqfcr[j] = ftp_rqfcr[l]; + local_rqfpr[j] = priv->ftp_rqfpr[l]; + local_rqfcr[j] = priv->ftp_rqfcr[l]; j--; } } @@ -750,8 +752,8 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u /* Write back the popped out rules again */ for (k = j+1; k < MAX_FILER_IDX; k++) { - ftp_rqfpr[priv->cur_filer_idx] = local_rqfpr[k]; - ftp_rqfcr[priv->cur_filer_idx] = local_rqfcr[k]; + priv->ftp_rqfpr[priv->cur_filer_idx] = local_rqfpr[k]; + priv->ftp_rqfcr[priv->cur_filer_idx] = local_rqfcr[k]; gfar_write_filer(priv, priv->cur_filer_idx, local_rqfcr[k], local_rqfpr[k]); if (!priv->cur_filer_idx) From fe6fe792faec3fc2d2db39b69651682b8c4e7fcb Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 8 Jun 2011 06:07:07 +0000 Subject: [PATCH 243/595] net: pmtu_expires fixes commit 2c8cec5c10bc (ipv4: Cache learned PMTU information in inetpeer) added some racy peer->pmtu_expires accesses. As its value can be changed by another cpu/thread, we should be more careful, reading its value once. Add peer_pmtu_expired() and peer_pmtu_cleaned() helpers Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/route.c | 78 +++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 52b0b956508b..045f0ec6a4a0 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1316,6 +1316,23 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, ; } +static bool peer_pmtu_expired(struct inet_peer *peer) +{ + unsigned long orig = ACCESS_ONCE(peer->pmtu_expires); + + return orig && + time_after_eq(jiffies, orig) && + cmpxchg(&peer->pmtu_expires, orig, 0) == orig; +} + +static bool peer_pmtu_cleaned(struct inet_peer *peer) +{ + unsigned long orig = ACCESS_ONCE(peer->pmtu_expires); + + return orig && + cmpxchg(&peer->pmtu_expires, orig, 0) == orig; +} + static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) { struct rtable *rt = (struct rtable *)dst; @@ -1331,14 +1348,8 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) rt_genid(dev_net(dst->dev))); rt_del(hash, rt); ret = NULL; - } else if (rt->peer && - rt->peer->pmtu_expires && - time_after_eq(jiffies, rt->peer->pmtu_expires)) { - unsigned long orig = rt->peer->pmtu_expires; - - if (cmpxchg(&rt->peer->pmtu_expires, orig, 0) == orig) - dst_metric_set(dst, RTAX_MTU, - rt->peer->pmtu_orig); + } else if (rt->peer && peer_pmtu_expired(rt->peer)) { + dst_metric_set(dst, RTAX_MTU, rt->peer->pmtu_orig); } } return ret; @@ -1531,8 +1542,10 @@ unsigned short ip_rt_frag_needed(struct net *net, const struct iphdr *iph, static void check_peer_pmtu(struct dst_entry *dst, struct inet_peer *peer) { - unsigned long expires = peer->pmtu_expires; + unsigned long expires = ACCESS_ONCE(peer->pmtu_expires); + if (!expires) + return; if (time_before(jiffies, expires)) { u32 orig_dst_mtu = dst_mtu(dst); if (peer->pmtu_learned < orig_dst_mtu) { @@ -1555,10 +1568,11 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) rt_bind_peer(rt, rt->rt_dst, 1); peer = rt->peer; if (peer) { + unsigned long pmtu_expires = ACCESS_ONCE(peer->pmtu_expires); + if (mtu < ip_rt_min_pmtu) mtu = ip_rt_min_pmtu; - if (!peer->pmtu_expires || mtu < peer->pmtu_learned) { - unsigned long pmtu_expires; + if (!pmtu_expires || mtu < peer->pmtu_learned) { pmtu_expires = jiffies + ip_rt_mtu_expires; if (!pmtu_expires) @@ -1612,13 +1626,14 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) rt_bind_peer(rt, rt->rt_dst, 0); peer = rt->peer; - if (peer && peer->pmtu_expires) + if (peer) { check_peer_pmtu(dst, peer); - if (peer && peer->redirect_learned.a4 && - peer->redirect_learned.a4 != rt->rt_gateway) { - if (check_peer_redir(dst, peer)) - return NULL; + if (peer->redirect_learned.a4 && + peer->redirect_learned.a4 != rt->rt_gateway) { + if (check_peer_redir(dst, peer)) + return NULL; + } } rt->rt_peer_genid = rt_peer_genid(); @@ -1649,14 +1664,8 @@ static void ipv4_link_failure(struct sk_buff *skb) icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); rt = skb_rtable(skb); - if (rt && - rt->peer && - rt->peer->pmtu_expires) { - unsigned long orig = rt->peer->pmtu_expires; - - if (cmpxchg(&rt->peer->pmtu_expires, orig, 0) == orig) - dst_metric_set(&rt->dst, RTAX_MTU, rt->peer->pmtu_orig); - } + if (rt && rt->peer && peer_pmtu_cleaned(rt->peer)) + dst_metric_set(&rt->dst, RTAX_MTU, rt->peer->pmtu_orig); } static int ip_rt_bug(struct sk_buff *skb) @@ -1770,8 +1779,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, sizeof(u32) * RTAX_MAX); dst_init_metrics(&rt->dst, peer->metrics, false); - if (peer->pmtu_expires) - check_peer_pmtu(&rt->dst, peer); + check_peer_pmtu(&rt->dst, peer); if (peer->redirect_learned.a4 && peer->redirect_learned.a4 != rt->rt_gateway) { rt->rt_gateway = peer->redirect_learned.a4; @@ -2775,7 +2783,8 @@ static int rt_fill_info(struct net *net, struct rtable *rt = skb_rtable(skb); struct rtmsg *r; struct nlmsghdr *nlh; - long expires; + long expires = 0; + const struct inet_peer *peer = rt->peer; u32 id = 0, ts = 0, tsage = 0, error; nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags); @@ -2823,15 +2832,16 @@ static int rt_fill_info(struct net *net, NLA_PUT_BE32(skb, RTA_MARK, rt->rt_mark); error = rt->dst.error; - expires = (rt->peer && rt->peer->pmtu_expires) ? - rt->peer->pmtu_expires - jiffies : 0; - if (rt->peer) { + if (peer) { inet_peer_refcheck(rt->peer); - id = atomic_read(&rt->peer->ip_id_count) & 0xffff; - if (rt->peer->tcp_ts_stamp) { - ts = rt->peer->tcp_ts; - tsage = get_seconds() - rt->peer->tcp_ts_stamp; + id = atomic_read(&peer->ip_id_count) & 0xffff; + if (peer->tcp_ts_stamp) { + ts = peer->tcp_ts; + tsage = get_seconds() - peer->tcp_ts_stamp; } + expires = ACCESS_ONCE(peer->pmtu_expires); + if (expires) + expires -= jiffies; } if (rt_is_input_route(rt)) { From 0c1ad04aecb975f2a2014e1bc5a2fa23923ecbd9 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Thu, 9 Jun 2011 00:28:13 -0700 Subject: [PATCH 244/595] netpoll: prevent netpoll setup on slave devices In commit 8d8fc29d02a33e4bd5f4fa47823c1fd386346093 (netpoll: disable netpoll when enslave a device), we automatically disable netpoll when the underlying device is being enslaved, we also need to prevent people from setuping netpoll on devices that are already enslaved. Signed-off-by: WANG Cong Signed-off-by: David S. Miller --- net/core/netpoll.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 2d7d6d473781..42ea4b0e59f1 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -792,6 +792,12 @@ int netpoll_setup(struct netpoll *np) return -ENODEV; } + if (ndev->master) { + printk(KERN_ERR "%s: %s is a slave device, aborting.\n", + np->name, np->dev_name); + return -EBUSY; + } + if (!netif_running(ndev)) { unsigned long atmost, atleast; From 2809e80b8a73d556b2302e273966fb15db16c51e Mon Sep 17 00:00:00 2001 From: Guan Xuetao Date: Thu, 26 May 2011 16:43:27 +0800 Subject: [PATCH 245/595] unicore32: move rtc-puv3.c to drivers/rtc directory The patch moves rtc driver for PKUnity-v3 SoC from arch/unicore32/kernel/ to drivers/rtc/, with renaming it to rtc-puv3.c. Also, Kconfig, Makefile, and MAINTAINERS are modified correspondingly. Signed-off-by: Guan Xuetao Acked-by: Arnd Bergmann --- MAINTAINERS | 1 + arch/unicore32/Kconfig | 4 ---- arch/unicore32/configs/debug_defconfig | 6 +++--- arch/unicore32/kernel/Makefile | 1 - drivers/rtc/Kconfig | 9 +++++++++ drivers/rtc/Makefile | 1 + .../kernel/rtc.c => drivers/rtc/rtc-puv3.c | 14 +------------- 7 files changed, 15 insertions(+), 21 deletions(-) rename arch/unicore32/kernel/rtc.c => drivers/rtc/rtc-puv3.c (98%) diff --git a/MAINTAINERS b/MAINTAINERS index b5ea4d033730..bbe49d8c22af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4945,6 +4945,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.gi F: drivers/input/serio/i8042-unicore32io.h F: drivers/i2c/busses/i2c-puv3.c F: drivers/video/fb-puv3.c +F: drivers/rtc/rtc-puv3.c PMC SIERRA MaxRAID DRIVER M: Anil Ravindranath diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig index d3a303246c9f..e57dcce9bfda 100644 --- a/arch/unicore32/Kconfig +++ b/arch/unicore32/Kconfig @@ -231,10 +231,6 @@ config PUV3_PWM help Enable support for NB0916 PWM controllers -config PUV3_RTC - tristate "PKUnity v3 RTC Support" - depends on !ARCH_FPGA - if PUV3_NB0916 menu "PKUnity NetBook-0916 Features" diff --git a/arch/unicore32/configs/debug_defconfig b/arch/unicore32/configs/debug_defconfig index b5fbde9f1cb2..9b9c2519a38f 100644 --- a/arch/unicore32/configs/debug_defconfig +++ b/arch/unicore32/configs/debug_defconfig @@ -64,7 +64,6 @@ CONFIG_I2C_BATTERY_BQ27200=n CONFIG_I2C_EEPROM_AT24=n CONFIG_LCD_BACKLIGHT=n -CONFIG_PUV3_RTC=y CONFIG_PUV3_UMAL=y CONFIG_PUV3_MUSB=n CONFIG_PUV3_AC97=n @@ -167,8 +166,9 @@ CONFIG_LEDS_TRIGGER_IDE_DISK=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y # Real Time Clock -CONFIG_RTC_LIB=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PUV3=y ### File systems CONFIG_EXT2_FS=m diff --git a/arch/unicore32/kernel/Makefile b/arch/unicore32/kernel/Makefile index ec23a2fb2f50..aeb0f181568e 100644 --- a/arch/unicore32/kernel/Makefile +++ b/arch/unicore32/kernel/Makefile @@ -16,7 +16,6 @@ obj-$(CONFIG_UNICORE_FPU_F64) += fpu-ucf64.o obj-$(CONFIG_ARCH_PUV3) += clock.o irq.o time.o obj-$(CONFIG_PUV3_GPIO) += gpio.o -obj-$(CONFIG_PUV3_RTC) += rtc.o obj-$(CONFIG_PUV3_PWM) += pwm.o obj-$(CONFIG_PUV3_PM) += pm.o sleep.o obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate_asm.o diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index f822e13dc04b..ce2aabf5c550 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1051,4 +1051,13 @@ config RTC_DRV_TILE Enable support for the Linux driver side of the Tilera hypervisor's real-time clock interface. +config RTC_DRV_PUV3 + tristate "PKUnity v3 RTC support" + depends on ARCH_PUV3 + help + This enables support for the RTC in the PKUnity-v3 SoCs. + + This drive can also be built as a module. If so, the module + will be called rtc-puv3. + endif # RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 213d725f16d4..0ffefe877bfa 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o +obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o diff --git a/arch/unicore32/kernel/rtc.c b/drivers/rtc/rtc-puv3.c similarity index 98% rename from arch/unicore32/kernel/rtc.c rename to drivers/rtc/rtc-puv3.c index 8cad70b3302c..46f14b82f3ab 100644 --- a/arch/unicore32/kernel/rtc.c +++ b/drivers/rtc/rtc-puv3.c @@ -1,7 +1,5 @@ /* - * linux/arch/unicore32/kernel/rtc.c - * - * Code specific to PKUnity SoC and UniCore ISA + * RTC driver code specific to PKUnity SoC and UniCore ISA * * Maintained by GUAN Xue-tao * Copyright (C) 2001-2010 Guan Xuetao @@ -36,7 +34,6 @@ static int puv3_rtc_tickno = IRQ_RTC; static DEFINE_SPINLOCK(puv3_rtc_pie_lock); /* IRQ Handlers */ - static irqreturn_t puv3_rtc_alarmirq(int irq, void *id) { struct rtc_device *rdev = id; @@ -89,7 +86,6 @@ static int puv3_rtc_setpie(struct device *dev, int enabled) } /* Time read/write */ - static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) { rtc_time_to_tm(readl(RTC_RCNR), rtc_tm); @@ -196,7 +192,6 @@ static void puv3_rtc_release(struct device *dev) struct rtc_device *rtc_dev = platform_get_drvdata(pdev); /* do not clear AIE here, it may be needed for wake */ - puv3_rtc_setpie(dev, 0); free_irq(puv3_rtc_alarmno, rtc_dev); free_irq(puv3_rtc_tickno, rtc_dev); @@ -218,7 +213,6 @@ static void puv3_rtc_enable(struct platform_device *pdev, int en) writel(readl(RTC_RTSR) & ~RTC_RTSR_HZE, RTC_RTSR); } else { /* re-enable the device, and check it is ok */ - if ((readl(RTC_RTSR) & RTC_RTSR_HZE) == 0) { dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); writel(readl(RTC_RTSR) | RTC_RTSR_HZE, RTC_RTSR); @@ -251,7 +245,6 @@ static int puv3_rtc_probe(struct platform_device *pdev) pr_debug("%s: probe=%p\n", __func__, pdev); /* find the IRQs */ - puv3_rtc_tickno = platform_get_irq(pdev, 1); if (puv3_rtc_tickno < 0) { dev_err(&pdev->dev, "no irq for rtc tick\n"); @@ -268,7 +261,6 @@ static int puv3_rtc_probe(struct platform_device *pdev) puv3_rtc_tickno, puv3_rtc_alarmno); /* get the memory region */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(&pdev->dev, "failed to get memory region resource\n"); @@ -288,7 +280,6 @@ static int puv3_rtc_probe(struct platform_device *pdev) puv3_rtc_enable(pdev, 1); /* register RTC and exit */ - rtc = rtc_device_register("pkunity", &pdev->dev, &puv3_rtcops, THIS_MODULE); @@ -315,8 +306,6 @@ static int puv3_rtc_probe(struct platform_device *pdev) #ifdef CONFIG_PM -/* RTC Power management control */ - static int ticnt_save; static int puv3_rtc_suspend(struct platform_device *pdev, pm_message_t state) @@ -368,4 +357,3 @@ module_exit(puv3_rtc_exit); MODULE_DESCRIPTION("RTC Driver for the PKUnity v3 chip"); MODULE_AUTHOR("Hu Dongliang"); MODULE_LICENSE("GPL v2"); - From f4728fd21f6d81bb2100da7eb9c675f1a74ad30d Mon Sep 17 00:00:00 2001 From: Guan Xuetao Date: Wed, 20 Apr 2011 19:06:53 +0800 Subject: [PATCH 246/595] unicore32: change zImage physical address, though it's PIC codes U-boot will load the kernel image to 48M physical memory address. The patch changes it to the correct address, though it's PIC codes. Signed-off-by: Guan Xuetao Acked-by: Arnd Bergmann --- arch/unicore32/boot/compressed/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/unicore32/boot/compressed/Makefile b/arch/unicore32/boot/compressed/Makefile index 95373428cb3d..b0954a2d23cf 100644 --- a/arch/unicore32/boot/compressed/Makefile +++ b/arch/unicore32/boot/compressed/Makefile @@ -59,7 +59,7 @@ $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head.o $(obj)/piggy.o \ # We now have a PIC decompressor implementation. Decompressors running # from RAM should not define ZTEXTADDR. Decompressors running directly # from ROM or Flash must define ZTEXTADDR (preferably via the config) -ZTEXTADDR := 0 +ZTEXTADDR := 0x03000000 ZBSSADDR := ALIGN(4) SEDFLAGS_lds = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ From 978b42e6f6f48560b18661a5e187aec7329a094b Mon Sep 17 00:00:00 2001 From: Guan Xuetao Date: Mon, 16 May 2011 15:28:19 +0800 Subject: [PATCH 247/595] unicore32: add KBUILD_DEFCONFIG with unicore32_defconfig (old debug_defconfig) Rename debug_defconfig to unicore32_defconfig, which is a minimal config for PKUnity-v3 (130nm) SoC board. Also, add KBUILD_DEFCONFIG to use 'make defconfig'. Signed-off-by: Guan Xuetao Acked-by: Arnd Bergmann --- arch/unicore32/Makefile | 3 ++- .../unicore32/configs/{debug_defconfig => unicore32_defconfig} | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) rename arch/unicore32/configs/{debug_defconfig => unicore32_defconfig} (99%) diff --git a/arch/unicore32/Makefile b/arch/unicore32/Makefile index 76a8beec7d03..6555abbaeb87 100644 --- a/arch/unicore32/Makefile +++ b/arch/unicore32/Makefile @@ -75,7 +75,8 @@ endif boot := arch/unicore32/boot -# Default target when executing plain make +# Default defconfig and target when executing plain make +KBUILD_DEFCONFIG := $(ARCH)_defconfig KBUILD_IMAGE := zImage all: $(KBUILD_IMAGE) diff --git a/arch/unicore32/configs/debug_defconfig b/arch/unicore32/configs/unicore32_defconfig similarity index 99% rename from arch/unicore32/configs/debug_defconfig rename to arch/unicore32/configs/unicore32_defconfig index 9b9c2519a38f..c9dd3198b6f7 100644 --- a/arch/unicore32/configs/debug_defconfig +++ b/arch/unicore32/configs/unicore32_defconfig @@ -1,6 +1,6 @@ ### General setup CONFIG_EXPERIMENTAL=y -CONFIG_LOCALVERSION="-debug" +CONFIG_LOCALVERSION="-unicore32" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y From 42733b3c4861799b3c30c1e416099324bb577960 Mon Sep 17 00:00:00 2001 From: Guan Xuetao Date: Thu, 26 May 2011 17:19:20 +0800 Subject: [PATCH 248/595] unicore32: change PERCPU to PERCPU_SECTION The patch changes PERCPU to PERCPU_SECTION see commit from Tejun Heo <0415b00d175e0d8945e6785aad21b5f157976ce0> percpu: Always align percpu output section to PAGE_SIZE Signed-off-by: Guan Xuetao Acked-by: Tejun Heo --- arch/unicore32/kernel/vmlinux.lds.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/unicore32/kernel/vmlinux.lds.S b/arch/unicore32/kernel/vmlinux.lds.S index 9bf7f7af52c5..77e407e49a63 100644 --- a/arch/unicore32/kernel/vmlinux.lds.S +++ b/arch/unicore32/kernel/vmlinux.lds.S @@ -30,7 +30,7 @@ SECTIONS HEAD_TEXT_SECTION INIT_TEXT_SECTION(PAGE_SIZE) INIT_DATA_SECTION(16) - PERCPU(L1_CACHE_BYTES, PAGE_SIZE) + PERCPU_SECTION(L1_CACHE_BYTES) __init_end = .; _stext = .; From 62b62c5c29468412cadd39dfb1113d3f0a323cfe Mon Sep 17 00:00:00 2001 From: Guan Xuetao Date: Thu, 26 May 2011 18:17:43 +0800 Subject: [PATCH 249/595] unicore32: using generic-y format for one line asm-generic files The patch adds one-line asm-generic files in arch/unicore32/include/asm/Kbuild Also, remove the old implementation in arch/unicore32/Makefile see commit from Sam Ravnborg kbuild: asm-generic support Signed-off-by: Guan Xuetao Acked-by: Arnd Bergmann --- arch/unicore32/Makefile | 35 ------------------ arch/unicore32/include/asm/Kbuild | 59 +++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 35 deletions(-) diff --git a/arch/unicore32/Makefile b/arch/unicore32/Makefile index 6555abbaeb87..6af4bc415f2b 100644 --- a/arch/unicore32/Makefile +++ b/arch/unicore32/Makefile @@ -40,39 +40,6 @@ core-y += arch/unicore32/mm/ libs-y += arch/unicore32/lib/ -ASM_GENERATED_DIR := $(srctree)/arch/unicore32/include/generated -LINUXINCLUDE += -I$(ASM_GENERATED_DIR) - -ASM_GENERIC_HEADERS := atomic.h auxvec.h -ASM_GENERIC_HEADERS += bitsperlong.h bug.h bugs.h -ASM_GENERIC_HEADERS += cputime.h current.h -ASM_GENERIC_HEADERS += device.h div64.h -ASM_GENERIC_HEADERS += emergency-restart.h errno.h -ASM_GENERIC_HEADERS += fb.h fcntl.h ftrace.h futex.h -ASM_GENERIC_HEADERS += hardirq.h hw_irq.h -ASM_GENERIC_HEADERS += ioctl.h ioctls.h ipcbuf.h irq_regs.h -ASM_GENERIC_HEADERS += kdebug.h kmap_types.h -ASM_GENERIC_HEADERS += local.h -ASM_GENERIC_HEADERS += mman.h module.h msgbuf.h -ASM_GENERIC_HEADERS += param.h parport.h percpu.h poll.h posix_types.h -ASM_GENERIC_HEADERS += resource.h -ASM_GENERIC_HEADERS += scatterlist.h sections.h segment.h sembuf.h serial.h -ASM_GENERIC_HEADERS += setup.h shmbuf.h shmparam.h -ASM_GENERIC_HEADERS += siginfo.h signal.h sizes.h -ASM_GENERIC_HEADERS += socket.h sockios.h stat.h statfs.h swab.h syscalls.h -ASM_GENERIC_HEADERS += termbits.h termios.h topology.h types.h -ASM_GENERIC_HEADERS += ucontext.h unaligned.h user.h -ASM_GENERIC_HEADERS += vga.h -ASM_GENERIC_HEADERS += xor.h - -archprepare: -ifneq ($(ASM_GENERATED_DIR), $(wildcard $(ASM_GENERATED_DIR))) - $(Q)mkdir -p $(ASM_GENERATED_DIR)/asm - $(Q)$(foreach a, $(ASM_GENERIC_HEADERS), \ - echo '#include ' \ - > $(ASM_GENERATED_DIR)/asm/$a; ) -endif - boot := arch/unicore32/boot # Default defconfig and target when executing plain make @@ -84,8 +51,6 @@ all: $(KBUILD_IMAGE) zImage Image uImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ -MRPROPER_DIRS += $(ASM_GENERATED_DIR) - archclean: $(Q)$(MAKE) $(clean)=$(boot) diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild index b200fdaca44d..ca113d6999c5 100644 --- a/arch/unicore32/include/asm/Kbuild +++ b/arch/unicore32/include/asm/Kbuild @@ -1,2 +1,61 @@ include include/asm-generic/Kbuild.asm +generic-y += atomic.h +generic-y += auxvec.h +generic-y += bitsperlong.h +generic-y += bug.h +generic-y += bugs.h +generic-y += cputime.h +generic-y += current.h +generic-y += device.h +generic-y += div64.h +generic-y += emergency-restart.h +generic-y += errno.h +generic-y += fb.h +generic-y += fcntl.h +generic-y += ftrace.h +generic-y += futex.h +generic-y += hardirq.h +generic-y += hw_irq.h +generic-y += ioctl.h +generic-y += ioctls.h +generic-y += ipcbuf.h +generic-y += irq_regs.h +generic-y += kdebug.h +generic-y += kmap_types.h +generic-y += local.h +generic-y += mman.h +generic-y += module.h +generic-y += msgbuf.h +generic-y += param.h +generic-y += parport.h +generic-y += percpu.h +generic-y += poll.h +generic-y += posix_types.h +generic-y += resource.h +generic-y += scatterlist.h +generic-y += sections.h +generic-y += segment.h +generic-y += sembuf.h +generic-y += serial.h +generic-y += setup.h +generic-y += shmbuf.h +generic-y += shmparam.h +generic-y += siginfo.h +generic-y += signal.h +generic-y += sizes.h +generic-y += socket.h +generic-y += sockios.h +generic-y += stat.h +generic-y += statfs.h +generic-y += swab.h +generic-y += syscalls.h +generic-y += termbits.h +generic-y += termios.h +generic-y += topology.h +generic-y += types.h +generic-y += ucontext.h +generic-y += unaligned.h +generic-y += user.h +generic-y += vga.h +generic-y += xor.h From 07989b7ad63af424886ff922fd3bcca9e00ffa78 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 9 Jun 2011 10:10:27 +0100 Subject: [PATCH 250/595] Revert "ARM: 6943/1: mm: use TTBR1 instead of reserved context ID" This reverts commit 52af9c6cd863fe37d1103035ec7ee22ac1296458. Will Deacon reports that: In 52af9c6c ("ARM: 6943/1: mm: use TTBR1 instead of reserved context ID") I updated the ASID rollover code to use only the kernel page tables whilst updating the ASID. Unfortunately, the code to restore the user page tables was part of a later patch which isn't yet in mainline, so this leaves the code quite broken. We're also in the process of eliminating __ARCH_WANT_INTERRUPTS_ON_CTXSW from ARM, so lets revert these until we can properly sort out what we're doing with the ARM context switching. Signed-off-by: Russell King --- arch/arm/mm/context.c | 11 +++++------ arch/arm/mm/proc-v7.S | 10 ++++++---- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 8bfae964b133..b6c776ae4039 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -24,7 +24,9 @@ DEFINE_PER_CPU(struct mm_struct *, current_mm); /* * We fork()ed a process, and we need a new context for the child - * to run in. + * to run in. We reserve version 0 for initial tasks so we will + * always allocate an ASID. The ASID 0 is reserved for the TTBR + * register changing sequence. */ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) { @@ -34,11 +36,8 @@ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) static void flush_context(void) { - u32 ttb; - /* Copy TTBR1 into TTBR0 */ - asm volatile("mrc p15, 0, %0, c2, c0, 1\n" - "mcr p15, 0, %0, c2, c0, 0" - : "=r" (ttb)); + /* set the reserved ASID before flushing the TLB */ + asm("mcr p15, 0, %0, c13, c0, 1\n" : : "r" (0)); isb(); local_flush_tlb_all(); if (icache_is_vivt_asid_tagged()) { diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index b3b566ec83d3..3c3867850a30 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -108,16 +108,18 @@ ENTRY(cpu_v7_switch_mm) #ifdef CONFIG_ARM_ERRATA_430973 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB #endif - mrc p15, 0, r2, c2, c0, 1 @ load TTB 1 - mcr p15, 0, r2, c2, c0, 0 @ into TTB 0 +#ifdef CONFIG_ARM_ERRATA_754322 + dsb +#endif + mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID + isb +1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 isb #ifdef CONFIG_ARM_ERRATA_754322 dsb #endif mcr p15, 0, r1, c13, c0, 1 @ set context ID isb - mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 - isb #endif mov pc, lr ENDPROC(cpu_v7_switch_mm) From a0a54d37b4b1d1f55d1e81e8ffc223bb85472fa3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 9 Jun 2011 10:12:41 +0100 Subject: [PATCH 251/595] Revert "ARM: 6944/1: mm: allow ASID 0 to be allocated to tasks" This reverts commit 45b95235b0ac86cef2ad4480b0618b8778847479. Will Deacon reports that: In 52af9c6c ("ARM: 6943/1: mm: use TTBR1 instead of reserved context ID") I updated the ASID rollover code to use only the kernel page tables whilst updating the ASID. Unfortunately, the code to restore the user page tables was part of a later patch which isn't yet in mainline, so this leaves the code quite broken. We're also in the process of eliminating __ARCH_WANT_INTERRUPTS_ON_CTXSW from ARM, so lets revert these until we can properly sort out what we're doing with the context switching. Signed-off-by: Russell King --- arch/arm/mm/context.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index b6c776ae4039..b0ee9ba3cfab 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -93,7 +93,7 @@ static void reset_context(void *info) return; smp_rmb(); - asid = cpu_last_asid + cpu; + asid = cpu_last_asid + cpu + 1; flush_context(); set_mm_context(mm, asid); @@ -143,13 +143,13 @@ void __new_context(struct mm_struct *mm) * to start a new version and flush the TLB. */ if (unlikely((asid & ~ASID_MASK) == 0)) { - asid = cpu_last_asid + smp_processor_id(); + asid = cpu_last_asid + smp_processor_id() + 1; flush_context(); #ifdef CONFIG_SMP smp_wmb(); smp_call_function(reset_context, NULL, 1); #endif - cpu_last_asid += NR_CPUS - 1; + cpu_last_asid += NR_CPUS; } set_mm_context(mm, asid); From 6075e9df471e35f2ebf4c73c95c304d0473bd4b2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 7 Jun 2011 09:40:51 +0100 Subject: [PATCH 252/595] ARM: 6949/2: mach-u300: fix compilaton warning in IO accessors The IO accessors for U300 were using u32 rather than the nominal void __iomem * type, rectify this by properly defining the virtual base for statically mapped peripherals to be void __iomem *. Requires fixing a field in struct clk as well. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-u300/clock.h | 2 +- arch/arm/mach-u300/include/mach/u300-regs.h | 22 ++++++++++----------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-u300/clock.h b/arch/arm/mach-u300/clock.h index c34f3ea3017c..4f50ca8f901e 100644 --- a/arch/arm/mach-u300/clock.h +++ b/arch/arm/mach-u300/clock.h @@ -31,7 +31,7 @@ struct clk { bool reset; __u16 clk_val; __s8 usecount; - __u32 res_reg; + void __iomem * res_reg; __u16 res_mask; bool hw_ctrld; diff --git a/arch/arm/mach-u300/include/mach/u300-regs.h b/arch/arm/mach-u300/include/mach/u300-regs.h index 8b85df4c8d8f..035fdc9dbdb0 100644 --- a/arch/arm/mach-u300/include/mach/u300-regs.h +++ b/arch/arm/mach-u300/include/mach/u300-regs.h @@ -18,6 +18,12 @@ * the defines are used for setting up the I/O memory mapping. */ +#ifdef __ASSEMBLER__ +#define IOMEM(a) (a) +#else +#define IOMEM(a) (void __iomem *) a +#endif + /* NAND Flash CS0 */ #define U300_NAND_CS0_PHYS_BASE 0x80000000 @@ -47,13 +53,6 @@ #define U300_SEMI_CONFIG_BASE 0x30000000 #endif -/* - * All the following peripherals are specified at their PHYSICAL address, - * so if you need to access them (in the kernel), you MUST use the macros - * defined in to map to the IO_ADDRESS_AHB() IO_ADDRESS_FAST() - * etc. - */ - /* * AHB peripherals */ @@ -63,11 +62,11 @@ /* Vectored Interrupt Controller 0, servicing 32 interrupts */ #define U300_INTCON0_BASE (U300_AHB_PER_PHYS_BASE+0x1000) -#define U300_INTCON0_VBASE (U300_AHB_PER_VIRT_BASE+0x1000) +#define U300_INTCON0_VBASE IOMEM(U300_AHB_PER_VIRT_BASE+0x1000) /* Vectored Interrupt Controller 1, servicing 32 interrupts */ #define U300_INTCON1_BASE (U300_AHB_PER_PHYS_BASE+0x2000) -#define U300_INTCON1_VBASE (U300_AHB_PER_VIRT_BASE+0x2000) +#define U300_INTCON1_VBASE IOMEM(U300_AHB_PER_VIRT_BASE+0x2000) /* Memory Stick Pro (MSPRO) controller */ #define U300_MSPRO_BASE (U300_AHB_PER_PHYS_BASE+0x3000) @@ -115,7 +114,7 @@ /* SYSCON */ #define U300_SYSCON_BASE (U300_SLOW_PER_PHYS_BASE+0x1000) -#define U300_SYSCON_VBASE (U300_SLOW_PER_VIRT_BASE+0x1000) +#define U300_SYSCON_VBASE IOMEM(U300_SLOW_PER_VIRT_BASE+0x1000) /* Watchdog */ #define U300_WDOG_BASE (U300_SLOW_PER_PHYS_BASE+0x2000) @@ -125,7 +124,7 @@ /* APP side special timer */ #define U300_TIMER_APP_BASE (U300_SLOW_PER_PHYS_BASE+0x4000) -#define U300_TIMER_APP_VBASE (U300_SLOW_PER_VIRT_BASE+0x4000) +#define U300_TIMER_APP_VBASE IOMEM(U300_SLOW_PER_VIRT_BASE+0x4000) /* Keypad */ #define U300_KEYPAD_BASE (U300_SLOW_PER_PHYS_BASE+0x5000) @@ -181,5 +180,4 @@ * Virtual accessor macros for static devices */ - #endif From f506cd48a4236b7045d092c9b92709ae6b4bdaf0 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 9 Jun 2011 04:58:36 +0100 Subject: [PATCH 253/595] ARM: 6953/1: DT: don't try to access physical address zero If the DT physical address is zero, this is equivalent to no DT. Especially when the actual RAM physical address is not located at zero, the result of phys_to_virt() would point to la-la-land and crash the kernel, which crash is completely silent this early during boot. Signed-off-by: Nicolas Pitre Acked-by: Grant Likely Signed-off-by: Russell King --- arch/arm/kernel/devtree.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index a701e4226a6c..0cdd7b456cb2 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -76,6 +76,9 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) unsigned long dt_root; const char *model; + if (!dt_phys) + return NULL; + devtree = phys_to_virt(dt_phys); /* check device tree validity */ From 720c60e1943a06cfd9472ad5a9967dec304e4394 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 9 Jun 2011 05:05:27 +0100 Subject: [PATCH 254/595] ARM: 6954/1: zImage: fix Thumb2 breakage Commit af3e4fd37a "ARM: 6859/1: Add writethrough dcache support for ARM926EJS processor" broke Thumb2 compilation by omitting to maintain the wide encoding for the added branch instructions which made the ARM926EJ-S record smaller than expected, breaking the record walk code. Signed-off-by: Nicolas Pitre Cc: Mark A. Greer Signed-off-by: Russell King --- arch/arm/boot/compressed/head.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index f9da41921c52..942fad97e447 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -691,9 +691,9 @@ proc_types: .word 0x41069260 @ ARM926EJ-S (v5TEJ) .word 0xff0ffff0 - b __arm926ejs_mmu_cache_on - b __armv4_mmu_cache_off - b __armv5tej_mmu_cache_flush + W(b) __arm926ejs_mmu_cache_on + W(b) __armv4_mmu_cache_off + W(b) __armv5tej_mmu_cache_flush .word 0x00007000 @ ARM7 IDs .word 0x0000f000 From 373ce3020b03fb6199415ab866595c7d627bbc97 Mon Sep 17 00:00:00 2001 From: Po-Yu Chuang Date: Thu, 9 Jun 2011 08:42:17 +0100 Subject: [PATCH 255/595] ARM: 6955/1: cmpxchg syscall should data abort if page not write If the page to cmpxchg is user mode read only (not write), we should simulate a data abort first. Signed-off-by: Po-Yu Chuang Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index d52eec268b47..c5ead3c2c618 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -563,7 +563,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) if (!pmd_present(*pmd)) goto bad_access; pte = pte_offset_map_lock(mm, pmd, addr, &ptl); - if (!pte_present(*pte) || !pte_dirty(*pte)) { + if (!pte_present(*pte) || !pte_write(*pte) || !pte_dirty(*pte)) { pte_unmap_unlock(pte, ptl); goto bad_access; } From 181e976327cf33095837c579608ebed42d2ad992 Mon Sep 17 00:00:00 2001 From: Peter Foley Date: Wed, 8 Jun 2011 20:58:32 -0400 Subject: [PATCH 256/595] kbuild: silence Nothing to be done for 'all' message This patch silences a Makefile.asm-generic message by defining a dummy rule for all. make -f /usr/src/git/scripts/Makefile.asm-generic \ obj=arch/x86/include/generated/asm make[1]: Nothing to be done for `all'. Signed-off-by: Peter Foley Signed-off-by: Michal Marek --- scripts/Makefile.asm-generic | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/Makefile.asm-generic b/scripts/Makefile.asm-generic index 490122c3e2aa..40caf3c26cd5 100644 --- a/scripts/Makefile.asm-generic +++ b/scripts/Makefile.asm-generic @@ -17,6 +17,7 @@ quiet_cmd_wrap = WRAP $@ cmd_wrap = echo "\#include " >$@ all: $(patsubst %, $(obj)/%, $(generic-y)) + @: $(obj)/%.h: $(call cmd,wrap) From 3115ae174620eeab4b16f52c8d0a9a35d2717e3c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 8 Jun 2011 18:07:49 +0100 Subject: [PATCH 257/595] ASoC: WM8804 does not support sample rates below 32kHz Reported-by: Kieran O'Leary Signed-off-by: Mark Brown Acked-by: Liam Girdwood Cc: stable@kernel.org --- sound/soc/codecs/wm8804.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 6785688f8806..9a5e67c5a6bd 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -680,20 +680,25 @@ static struct snd_soc_dai_ops wm8804_dai_ops = { #define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE) +#define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \ + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) + static struct snd_soc_dai_driver wm8804_dai = { .name = "wm8804-spdif", .playback = { .stream_name = "Playback", .channels_min = 2, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = WM8804_RATES, .formats = WM8804_FORMATS, }, .capture = { .stream_name = "Capture", .channels_min = 2, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = WM8804_RATES, .formats = WM8804_FORMATS, }, .ops = &wm8804_dai_ops, From 0cd114fff9ace7014c0d3ef8ab385fc5d3cf2d2f Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Wed, 8 Jun 2011 15:02:56 -0500 Subject: [PATCH 258/595] ASoC: fsl: fix initialization of DMA buffers The DMA (PCM) driver used by some Freescale PowerPC supports separate DAIs for playback and capture, so DMA buffers should be allocated only for the initialized streams. Instead of checking for the number of active channels, which apparently is not reliable, check to see if the actual stream object exists. Also provide a better name for the DMA interrupt. Signed-off-by: Timur Tabi Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_dma.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 15dac0f20cd8..6680c0b4d203 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -310,7 +310,7 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, * should allocate a DMA buffer only for the streams that are valid. */ - if (dai->driver->playback.channels_min) { + if (pcm->streams[0].substream) { ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, fsl_dma_hardware.buffer_bytes_max, &pcm->streams[0].substream->dma_buffer); @@ -320,13 +320,13 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, } } - if (dai->driver->capture.channels_min) { + if (pcm->streams[1].substream) { ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, fsl_dma_hardware.buffer_bytes_max, &pcm->streams[1].substream->dma_buffer); if (ret) { - snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); dev_err(card->dev, "can't alloc capture dma buffer\n"); + snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); return ret; } } @@ -449,7 +449,8 @@ static int fsl_dma_open(struct snd_pcm_substream *substream) dma_private->ld_buf_phys = ld_buf_phys; dma_private->dma_buf_phys = substream->dma_buffer.addr; - ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "DMA", dma_private); + ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "fsldma-audio", + dma_private); if (ret) { dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n", dma_private->irq, ret); From db5e7ecc4abc91b9f26f0c0d79ef88a51e987d90 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 9 Jun 2011 08:40:59 -0400 Subject: [PATCH 259/595] tracing: Fix regression in printk_formats file The fix to fix the printk_formats of modules broke the printk_formats of trace_printks in the kernel. The update of what to show via the seq_file was only updated if the passed in fmt was NULL, which happens only on the first iteration. The result was showing the first format every time instead of iterating through the available formats. Signed-off-by: Steven Rostedt --- kernel/trace/trace_printk.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index dff763b7baf1..1f06468a10d7 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c @@ -240,13 +240,10 @@ static const char **find_next(void *v, loff_t *pos) const char **fmt = v; int start_index; - if (!fmt) - fmt = __start___trace_bprintk_fmt + *pos; - start_index = __stop___trace_bprintk_fmt - __start___trace_bprintk_fmt; if (*pos < start_index) - return fmt; + return __start___trace_bprintk_fmt + *pos; return find_next_mod_format(start_index, v, fmt, pos); } From 7f20caff0ef6ce87dbb044389d43bfa1093cd3af Mon Sep 17 00:00:00 2001 From: Connor Hansen Date: Sun, 5 Jun 2011 03:35:09 -0700 Subject: [PATCH 260/595] iscsi_ibft: iscsi_ibft_find unused variable i int i is only needed if CONFIG_ACPI is set so move it within a new ifdef so kernels without ACPI don't allocate space for nothing. Fixes warning too. Signed-off-by: Connor Hansen Signed-off-by: Peter Jones [v2: Fixed warning when CONFIG_ACPI was defined] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/firmware/iscsi_ibft_find.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c index f032e446fc11..bfe723266fd8 100644 --- a/drivers/firmware/iscsi_ibft_find.c +++ b/drivers/firmware/iscsi_ibft_find.c @@ -108,7 +108,9 @@ static int __init find_ibft_in_mem(void) */ unsigned long __init find_ibft_region(unsigned long *sizep) { +#ifdef CONFIG_ACPI int i; +#endif ibft_addr = NULL; #ifdef CONFIG_ACPI From a91d92875ee94e4703fd017ccaadb48cfb344994 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Fri, 3 Jun 2011 09:51:34 +0000 Subject: [PATCH 261/595] xen: partially revert "xen: set max_pfn_mapped to the last pfn mapped" We only need to set max_pfn_mapped to the last pfn mapped on x86_64 to make sure that cleanup_highmap doesn't remove important mappings at _end. We don't need to do this on x86_32 because cleanup_highmap is not called on x86_32. Besides lowering max_pfn_mapped on x86_32 has the unwanted side effect of limiting the amount of memory available for the 1:1 kernel pagetable allocation. This patch reverts the x86_32 part of the original patch. CC: stable@kernel.org Signed-off-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/mmu.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index dc708dcc62f1..afe1d54f980c 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1599,6 +1599,11 @@ static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) { pte_t pte; +#ifdef CONFIG_X86_32 + if (pfn > max_pfn_mapped) + max_pfn_mapped = pfn; +#endif + if (!pte_none(pte_page[pteidx])) continue; @@ -1766,7 +1771,9 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, initial_kernel_pmd = extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE); - max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list)); + max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) + + xen_start_info->nr_pt_frames * PAGE_SIZE + + 512*1024); kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd); memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD); From 977cb76d52e7aa040e18a84b29fe6fd80d79319b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 6 Jun 2011 10:15:49 +0200 Subject: [PATCH 262/595] x86: devicetree: Add missing early_init_dt_setup_initrd_arch stub This patch fixes the following build failure: drivers/built-in.o: In function `early_init_dt_check_for_initrd': /home/florian/dev/kernel/x86/linux-2.6-x86/drivers/of/fdt.c:571: undefined reference to `early_init_dt_setup_initrd_arch' make: *** [.tmp_vmlinux1] Error 1 which happens as soon as we enable initrd support on a x86 devicetree platform such as Intel CE4100. Signed-off-by: Florian Fainelli Acked-by: Grant Likely Cc: Maxime Bizon Acked-by: Sebastian Andrzej Siewior Cc: stable@kernel.org # 2.6.39 Link: http://lkml.kernel.org/r/201106061015.50039.ffainelli@freebox.fr Signed-off-by: Thomas Gleixner --- arch/x86/kernel/devicetree.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 690bc8461835..9aeb78a23de4 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -98,6 +99,16 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS)); } +#ifdef CONFIG_BLK_DEV_INITRD +void __init early_init_dt_setup_initrd_arch(unsigned long start, + unsigned long end) +{ + initrd_start = (unsigned long)__va(start); + initrd_end = (unsigned long)__va(end); + initrd_below_start_ok = 1; +} +#endif + void __init add_dtb(u64 data) { initial_dtb = data + offsetof(struct setup_data, data); From 4b80b8c2eee5282dab57f094fd3893c0c09f750c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 9 Jun 2011 13:22:36 +0200 Subject: [PATCH 263/595] ASoC: snd_soc_new_{mixer,mux,pga} make sure to use right DAPM context Currently it is possible that snd_soc_new_{mixer,mux,pga} is called with a DAPM context not matching the widgets context. This can lead to a wrong prefix_len calculation, which will result in undefined behaviour. To avoid this always use the DAPM context from the widget itself. Signed-off-by: Lars-Peter Clausen Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/soc-dapm.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 776e6f418306..32ab7fc4579a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -350,9 +350,9 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm, } /* create new dapm mixer control */ -static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, - struct snd_soc_dapm_widget *w) +static int dapm_new_mixer(struct snd_soc_dapm_widget *w) { + struct snd_soc_dapm_context *dapm = w->dapm; int i, ret = 0; size_t name_len, prefix_len; struct snd_soc_dapm_path *path; @@ -450,9 +450,9 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, } /* create new dapm mux control */ -static int dapm_new_mux(struct snd_soc_dapm_context *dapm, - struct snd_soc_dapm_widget *w) +static int dapm_new_mux(struct snd_soc_dapm_widget *w) { + struct snd_soc_dapm_context *dapm = w->dapm; struct snd_soc_dapm_path *path = NULL; struct snd_kcontrol *kcontrol; struct snd_card *card = dapm->card->snd_card; @@ -535,8 +535,7 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm, } /* create new dapm volume control */ -static int dapm_new_pga(struct snd_soc_dapm_context *dapm, - struct snd_soc_dapm_widget *w) +static int dapm_new_pga(struct snd_soc_dapm_widget *w) { if (w->num_kcontrols) dev_err(w->dapm->dev, @@ -1826,13 +1825,13 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) case snd_soc_dapm_mixer: case snd_soc_dapm_mixer_named_ctl: w->power_check = dapm_generic_check_power; - dapm_new_mixer(dapm, w); + dapm_new_mixer(w); break; case snd_soc_dapm_mux: case snd_soc_dapm_virt_mux: case snd_soc_dapm_value_mux: w->power_check = dapm_generic_check_power; - dapm_new_mux(dapm, w); + dapm_new_mux(w); break; case snd_soc_dapm_adc: case snd_soc_dapm_aif_out: @@ -1845,7 +1844,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) case snd_soc_dapm_pga: case snd_soc_dapm_out_drv: w->power_check = dapm_generic_check_power; - dapm_new_pga(dapm, w); + dapm_new_pga(w); break; case snd_soc_dapm_input: case snd_soc_dapm_output: From 25b8b936ed44814a5ce6fc3b2a21401f33cd56f6 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 8 Jun 2011 14:36:54 -0400 Subject: [PATCH 264/595] Btrfs: don't map extent buffer if path->skip_locking is set Arne's scrub stuff exposed a problem with mapping the extent buffer in reada_for_search. He searches the commit root with multiple threads and with skip_locking set, so we can race and overwrite node->map_token since node isn't locked. So fix this so that we only map the extent buffer if we don't already have a map_token and skip_locking isn't set. Without this patch scrub would panic almost immediately, with the patch it doesn't panic anymore. Thanks, Reported-by: Arne Jansen Signed-off-by: Josef Bacik --- fs/btrfs/ctree.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index d84089349c82..2e667868e0d2 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -1228,6 +1228,7 @@ static void reada_for_search(struct btrfs_root *root, u32 nr; u32 blocksize; u32 nscan = 0; + bool map = true; if (level != 1) return; @@ -1249,8 +1250,11 @@ static void reada_for_search(struct btrfs_root *root, nritems = btrfs_header_nritems(node); nr = slot; + if (node->map_token || path->skip_locking) + map = false; + while (1) { - if (!node->map_token) { + if (map && !node->map_token) { unsigned long offset = btrfs_node_key_ptr_offset(nr); map_private_extent_buffer(node, offset, sizeof(struct btrfs_key_ptr), @@ -1277,7 +1281,7 @@ static void reada_for_search(struct btrfs_root *root, if ((search <= target && target - search <= 65536) || (search > target && search - target <= 65536)) { gen = btrfs_node_ptr_generation(node, nr); - if (node->map_token) { + if (map && node->map_token) { unmap_extent_buffer(node, node->map_token, KM_USER1); node->map_token = NULL; @@ -1289,7 +1293,7 @@ static void reada_for_search(struct btrfs_root *root, if ((nread > 65536 || nscan > 32)) break; } - if (node->map_token) { + if (map && node->map_token) { unmap_extent_buffer(node, node->map_token, KM_USER1); node->map_token = NULL; } From 3473f3c06a36865ae05993041fff35ee928342a7 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 9 Jun 2011 10:15:17 -0400 Subject: [PATCH 265/595] Btrfs: unlock the trans lock properly In btrfs_wait_for_commit if we came upon a transaction that had committed we just exited, but that's bad since we are holding the trans_lock. So break instead so that the lock is dropped. Thanks, Reported-by: David Sterba Signed-off-by: Josef Bacik --- fs/btrfs/transaction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index dd719662340e..6b2e4786d189 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -349,7 +349,7 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid) list) { if (t->in_commit) { if (t->commit_done) - goto out; + break; cur_trans = t; atomic_inc(&cur_trans->use_count); break; From 8eb73c6c2675f708283822bd058ad1e416836ba2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 9 Jun 2011 10:18:23 +0300 Subject: [PATCH 266/595] Staging: mei: fix debug code ! has higher precedence than !=. H_RDY is 8 and since neither 0 nor 1 are equal to 8 the original condition was always true. Signed-off-by: Dan Carpenter Acked-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mei/init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/mei/init.c b/drivers/staging/mei/init.c index 2818851c0761..d1ffa32cd141 100644 --- a/drivers/staging/mei/init.c +++ b/drivers/staging/mei/init.c @@ -205,10 +205,10 @@ int mei_hw_init(struct mei_device *dev) "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", dev->host_hw_state, dev->me_hw_state); - if (!(dev->host_hw_state & H_RDY) != H_RDY) + if (!(dev->host_hw_state & H_RDY)) dev_dbg(&dev->pdev->dev, "host turn off H_RDY.\n"); - if (!(dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA) + if (!(dev->me_hw_state & ME_RDY_HRA)) dev_dbg(&dev->pdev->dev, "ME turn off ME_RDY.\n"); printk(KERN_ERR "mei: link layer initialization failed.\n"); From 8aa460e9e9f6eb6c23c8b244516bedddee901ceb Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 9 Jun 2011 16:21:00 +0200 Subject: [PATCH 267/595] staging: iio: max517: Fix iio_info changes struct iio_info introduced a bug where the second channel of a MAX518 can't be used. This commit fixes the typo (using max518 instead of the max517 struct). Signed-off-by: Roland Stigge Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/max517.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/dac/max517.c b/drivers/staging/iio/dac/max517.c index 881768df47a6..2fe34d21b6aa 100644 --- a/drivers/staging/iio/dac/max517.c +++ b/drivers/staging/iio/dac/max517.c @@ -195,7 +195,7 @@ static const struct iio_info max517_info = { }; static const struct iio_info max518_info = { - .attrs = &max517_attribute_group, + .attrs = &max518_attribute_group, .driver_module = THIS_MODULE, }; From 8d03e971cf403305217b8e62db3a2e5ad2d6263f Mon Sep 17 00:00:00 2001 From: Filip Palian Date: Thu, 12 May 2011 19:32:46 +0200 Subject: [PATCH 268/595] Bluetooth: l2cap and rfcomm: fix 1 byte infoleak to userspace. Structures "l2cap_conninfo" and "rfcomm_conninfo" have one padding byte each. This byte in "cinfo" is copied to userspace uninitialized. Signed-off-by: Filip Palian Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 1 + net/bluetooth/rfcomm/sock.c | 1 + 2 files changed, 2 insertions(+) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 18dc9888d8c2..8248303f44e8 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -413,6 +413,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us break; } + memset(&cinfo, 0, sizeof(cinfo)); cinfo.hci_handle = chan->conn->hcon->handle; memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 386cfaffd4b7..1b10727ce523 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -788,6 +788,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk; + memset(&cinfo, 0, sizeof(cinfo)); cinfo.hci_handle = conn->hcon->handle; memcpy(cinfo.dev_class, conn->hcon->dev_class, 3); From dac853ae89043f1b7752875300faf614de43c74b Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Thu, 9 Jun 2011 20:05:18 +0200 Subject: [PATCH 269/595] exec: delay address limit change until point of no return Unconditionally changing the address limit to USER_DS and not restoring it to its old value in the error path is wrong because it prevents us using kernel memory on repeated calls to this function. This, in fact, breaks the fallback of hard coded paths to the init program from being ever successful if the first candidate fails to load. With this patch applied switching to USER_DS is delayed until the point of no return is reached which makes it possible to have a multi-arch rootfs with one arch specific init binary for each of the (hard coded) probed paths. Since the address limit is already set to USER_DS when start_thread() will be invoked, this redundancy can be safely removed. Signed-off-by: Mathias Krause Cc: Al Viro Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- arch/x86/kernel/process_32.c | 1 - arch/x86/kernel/process_64.c | 1 - fs/exec.c | 5 +---- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 8d128783af47..a3d0dc59067b 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -245,7 +245,6 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) { set_user_gs(regs, 0); regs->fs = 0; - set_fs(USER_DS); regs->ds = __USER_DS; regs->es = __USER_DS; regs->ss = __USER_DS; diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 6c9dd922ac0d..ca6f7ab8df33 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -338,7 +338,6 @@ start_thread_common(struct pt_regs *regs, unsigned long new_ip, regs->cs = _cs; regs->ss = _ss; regs->flags = X86_EFLAGS_IF; - set_fs(USER_DS); /* * Free the old FP and other extended state */ diff --git a/fs/exec.c b/fs/exec.c index ea5f748906a8..97e0d52d72fd 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1093,6 +1093,7 @@ int flush_old_exec(struct linux_binprm * bprm) bprm->mm = NULL; /* We're using it now */ + set_fs(USER_DS); current->flags &= ~(PF_RANDOMIZE | PF_KTHREAD); flush_thread(); current->personality &= ~bprm->per_clear; @@ -1357,10 +1358,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) if (retval) return retval; - /* kernel module loader fixup */ - /* so we don't try to load run modprobe in kernel space. */ - set_fs(USER_DS); - retval = audit_bprm(bprm); if (retval) return retval; From 29cf519ee086686e5f0fc91cbb2d601dd1190f9c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 9 Jun 2011 11:23:37 -0700 Subject: [PATCH 270/595] vsprintf: Update %pI6c to not compress a single 0 RFC 5952 (http://tools.ietf.org/html/rfc5952) mandates that 2 or more consecutive 0's are required before using :: compression. Update ip6_compressed_string to match the RFC and update the http reference as well. Signed-off-by: Joe Perches Signed-off-by: Linus Torvalds --- lib/vsprintf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index c11205688fb4..4365df31a1d5 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -666,6 +666,8 @@ char *ip6_compressed_string(char *p, const char *addr) colonpos = i; } } + if (longest == 1) /* don't compress a single 0 */ + colonpos = -1; /* emit address */ for (i = 0; i < range; i++) { @@ -826,7 +828,7 @@ int kptr_restrict __read_mostly; * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order * - 'I6c' for IPv6 addresses printed as specified by - * http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00 + * http://tools.ietf.org/html/rfc5952 * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" * Options for %pU are: From 33d78647dc409784c18aa71995346e6955802fe0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Jun 2011 11:08:47 +0200 Subject: [PATCH 271/595] gpio/nomadik: fix sleepmode for elder Nomadik The mach-nomadik machine did not compile properly due to bad ux500-specific functions being called. Introduce new state variables to fix this up. Reported-by: Axel Lin Cc: Alessandro Rubini Cc: Prafulla Wadaskar Signed-off-by: Linus Walleij Signed-off-by: Grant Likely --- arch/arm/mach-ux500/cpu-db8500.c | 3 ++ arch/arm/plat-nomadik/include/plat/gpio.h | 1 + drivers/gpio/gpio-nomadik.c | 40 ++++++++++++++++------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index c3c417656bd9..4598b06c8c55 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -159,6 +159,9 @@ static void __init db8500_add_gpios(void) /* No custom data yet */ }; + if (cpu_is_u8500v2()) + pdata.supports_sleepmode = true; + dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base), IRQ_DB8500_GPIO0, &pdata); } diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index ea19a5b2f227..d5d7e651269c 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -90,6 +90,7 @@ struct nmk_gpio_platform_data { int num_gpio; u32 (*get_secondary_status)(unsigned int bank); void (*set_ioforce)(bool enable); + bool supports_sleepmode; }; #endif /* __ASM_PLAT_GPIO_H */ diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c index 4961ef9bc153..2c212c732d76 100644 --- a/drivers/gpio/gpio-nomadik.c +++ b/drivers/gpio/gpio-nomadik.c @@ -4,6 +4,7 @@ * Copyright (C) 2008,2009 STMicroelectronics * Copyright (C) 2009 Alessandro Rubini * Rewritten based on work by Prafulla WADASKAR + * Copyright (C) 2011 Linus Walleij * * 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 @@ -49,6 +50,7 @@ struct nmk_gpio_chip { u32 (*get_secondary_status)(unsigned int bank); void (*set_ioforce)(bool enable); spinlock_t lock; + bool sleepmode; /* Keep track of configured edges */ u32 edge_rising; u32 edge_falling; @@ -393,14 +395,25 @@ EXPORT_SYMBOL(nmk_config_pins_sleep); * @gpio: pin number * @mode: NMK_GPIO_SLPM_INPUT or NMK_GPIO_SLPM_NOCHANGE, * - * Sets the sleep mode of a pin. If @mode is NMK_GPIO_SLPM_INPUT, the pin is - * changed to an input (with pullup/down enabled) in sleep and deep sleep. If - * @mode is NMK_GPIO_SLPM_NOCHANGE, the pin remains in the state it was - * configured even when in sleep and deep sleep. + * This register is actually in the pinmux layer, not the GPIO block itself. + * The GPIO1B_SLPM register defines the GPIO mode when SLEEP/DEEP-SLEEP + * mode is entered (i.e. when signal IOFORCE is HIGH by the platform code). + * Each GPIO can be configured to be forced into GPIO mode when IOFORCE is + * HIGH, overriding the normal setting defined by GPIO_AFSELx registers. + * When IOFORCE returns LOW (by software, after SLEEP/DEEP-SLEEP exit), + * the GPIOs return to the normal setting defined by GPIO_AFSELx registers. * - * On DB8500v2 onwards, this setting loses the previous meaning and instead - * indicates if wakeup detection is enabled on the pin. Note that - * enable_irq_wake() will automatically enable wakeup detection. + * If @mode is NMK_GPIO_SLPM_INPUT, the corresponding GPIO is switched to GPIO + * mode when signal IOFORCE is HIGH (i.e. when SLEEP/DEEP-SLEEP mode is + * entered) regardless of the altfunction selected. Also wake-up detection is + * ENABLED. + * + * If @mode is NMK_GPIO_SLPM_NOCHANGE, the corresponding GPIO remains + * controlled by NMK_GPIO_DATC, NMK_GPIO_DATS, NMK_GPIO_DIR, NMK_GPIO_PDIS + * (for altfunction GPIO) or respective on-chip peripherals (for other + * altfuncs) when IOFORCE is HIGH. Also wake-up detection DISABLED. + * + * Note that enable_irq_wake() will automatically enable wakeup detection. */ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) { @@ -551,6 +564,12 @@ static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip, int gpio, bool on) { + if (nmk_chip->sleepmode) { + __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, + on ? NMK_GPIO_SLPM_WAKEUP_ENABLE + : NMK_GPIO_SLPM_WAKEUP_DISABLE); + } + __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on); } @@ -901,7 +920,7 @@ void nmk_gpio_wakeups_suspend(void) writel(chip->fwimsc & chip->real_wake, chip->addr + NMK_GPIO_FWIMSC); - if (cpu_is_u8500v2()) { + if (chip->sleepmode) { chip->slpm = readl(chip->addr + NMK_GPIO_SLPC); /* 0 -> wakeup enable */ @@ -923,7 +942,7 @@ void nmk_gpio_wakeups_resume(void) writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC); writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC); - if (cpu_is_u8500v2()) + if (chip->sleepmode) writel(chip->slpm, chip->addr + NMK_GPIO_SLPC); } } @@ -1010,6 +1029,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) nmk_chip->secondary_parent_irq = secondary_irq; nmk_chip->get_secondary_status = pdata->get_secondary_status; nmk_chip->set_ioforce = pdata->set_ioforce; + nmk_chip->sleepmode = pdata->supports_sleepmode; spin_lock_init(&nmk_chip->lock); chip = &nmk_chip->chip; @@ -1065,5 +1085,3 @@ core_initcall(nmk_gpio_init); MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); MODULE_DESCRIPTION("Nomadik GPIO Driver"); MODULE_LICENSE("GPL"); - - From cacd54ef49b75cb31d78bb7b8dd900690aac7bdf Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Mon, 30 May 2011 13:36:07 +0200 Subject: [PATCH 272/595] kbuild: Fix KERNELVERSION for empty SUBLEVEL or PATCHLEVEL Omit the second dot for releases without SUBLEVEL. If PATCHLEVEL is also empty, only display VERSION. Signed-off-by: Michal Marek --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index afb8e0d26f2c..4fe907510d79 100644 --- a/Makefile +++ b/Makefile @@ -378,7 +378,7 @@ KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds # Read KERNELRELEASE from include/config/kernel.release (if it exists) KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) -KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) +KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION) export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC From 78d3bb4483ba1b206dbaaf209219ed517b01f7da Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Mon, 30 May 2011 13:37:20 +0200 Subject: [PATCH 273/595] kbuild: Fix for empty SUBLEVEL or PATCHLEVEL expr treats all numbers as decimals, so prepending a zero is safe. Note that the KERNEL_VERSION() macro still takes three arguments, 3.0 has to be written as KERNEL_VERSION(3,0,0). Signed-off-by: Michal Marek --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4fe907510d79..60d4a6762689 100644 --- a/Makefile +++ b/Makefile @@ -1005,7 +1005,7 @@ endef define filechk_version.h (echo \#define LINUX_VERSION_CODE $(shell \ - expr $(VERSION) \* 65536 + $(PATCHLEVEL) \* 256 + $(SUBLEVEL)); \ + expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \ echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';) endef From fc4da9a3e68b1f64237fafda084f61067f568a99 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Thu, 9 Jun 2011 15:35:22 +0200 Subject: [PATCH 274/595] kbuild: Move depmod call to a separate script Do not bloat the Makefile with multiline shell statements. No user-visible change intended. Signed-off-by: Michal Marek --- Makefile | 12 +----------- scripts/depmod.sh | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 11 deletions(-) create mode 100755 scripts/depmod.sh diff --git a/Makefile b/Makefile index 60d4a6762689..43509373f37a 100644 --- a/Makefile +++ b/Makefile @@ -1110,11 +1110,6 @@ modules_install: _modinst_ _modinst_post PHONY += _modinst_ _modinst_: - @if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \ - echo "Warning: you may need to install module-init-tools"; \ - echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\ - sleep 1; \ - fi @rm -rf $(MODLIB)/kernel @rm -f $(MODLIB)/source @mkdir -p $(MODLIB)/kernel @@ -1531,12 +1526,7 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files)) # Run depmod only if we have System.map and depmod is executable quiet_cmd_depmod = DEPMOD $(KERNELRELEASE) - cmd_depmod = \ - if [ -r System.map -a -x $(DEPMOD) ]; then \ - $(DEPMOD) -ae -F System.map \ - $(if $(strip $(INSTALL_MOD_PATH)), -b $(INSTALL_MOD_PATH) ) \ - $(KERNELRELEASE); \ - fi + cmd_depmod = $(srctree)/scripts/depmod.sh $(DEPMOD) $(KERNELRELEASE) # Create temporary dir for module support files # clean it up only when building all modules diff --git a/scripts/depmod.sh b/scripts/depmod.sh new file mode 100755 index 000000000000..9f205dafed36 --- /dev/null +++ b/scripts/depmod.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# A depmod wrapper used by the toplevel Makefile + +if test $# -ne 2; then + echo "Usage: $0 /sbin/depmod " >&2 + exit 1 +fi +DEPMOD=$1 +KERNELRELEASE=$2 + +if ! "$DEPMOD" -V 2>/dev/null | grep -q module-init-tools; then + echo "Warning: you may need to install module-init-tools" >&2 + echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt" >&2 + sleep 1 +fi + +if ! test -r System.map -a -x "$DEPMOD"; then + exit 0 +fi +set -- -ae -F System.map +if test -n "$INSTALL_MOD_PATH"; then + set -- "$@" -b "$INSTALL_MOD_PATH" +fi +exec "$DEPMOD" "$@" "$KERNELRELEASE" From bfe5424a8b31624e7a476f959d552999f931e7c7 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Thu, 9 Jun 2011 16:35:41 +0200 Subject: [PATCH 275/595] kbuild: Hack for depmod not handling X.Y versions depmod from module-init-tools < 3.13 and the busybox depmod check if the kernel release starts with ... To support these versions, we create a symlink with two numbers prepended. Signed-off-by: Michal Marek --- scripts/depmod.sh | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/scripts/depmod.sh b/scripts/depmod.sh index 9f205dafed36..3b029cba2baf 100755 --- a/scripts/depmod.sh +++ b/scripts/depmod.sh @@ -18,8 +18,31 @@ fi if ! test -r System.map -a -x "$DEPMOD"; then exit 0 fi +# older versions of depmod require the version string to start with three +# numbers, so we cheat with a symlink here +depmod_hack_needed=true +mkdir -p .tmp_depmod/lib/modules/$KERNELRELEASE +if "$DEPMOD" -b .tmp_depmod $KERNELRELEASE 2>/dev/null; then + if test -e .tmp_depmod/lib/modules/$KERNELRELEASE/modules.dep -o \ + -e .tmp_depmod/lib/modules/$KERNELRELEASE/modules.dep.bin; then + depmod_hack_needed=false + fi +fi +if $depmod_hack_needed; then + symlink="$INSTALL_MOD_PATH/lib/modules/99.98.$KERNELRELEASE" + ln -s "$KERNELRELEASE" "$symlink" + KERNELRELEASE=99.98.$KERNELRELEASE +fi + set -- -ae -F System.map if test -n "$INSTALL_MOD_PATH"; then set -- "$@" -b "$INSTALL_MOD_PATH" fi -exec "$DEPMOD" "$@" "$KERNELRELEASE" +"$DEPMOD" "$@" "$KERNELRELEASE" +ret=$? + +if $depmod_hack_needed; then + rm -f "$symlink" +fi + +exit $ret From 5d61b9fd19d9f3cf653dbba615876e7792eea5ea Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Mon, 30 May 2011 14:12:09 +0200 Subject: [PATCH 276/595] perf: Use make kernelversion instead of parsing the Makefile Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Signed-off-by: Michal Marek --- tools/perf/util/PERF-VERSION-GEN | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN index 26d4d3fd6deb..9c5fb4d93824 100755 --- a/tools/perf/util/PERF-VERSION-GEN +++ b/tools/perf/util/PERF-VERSION-GEN @@ -23,12 +23,7 @@ if test -d ../../.git -o -f ../../.git && then VN=$(echo "$VN" | sed -e 's/-/./g'); else - eval $(grep '^VERSION[[:space:]]*=' ../../Makefile|tr -d ' ') - eval $(grep '^PATCHLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ') - eval $(grep '^SUBLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ') - eval $(grep '^EXTRAVERSION[[:space:]]*=' ../../Makefile|tr -d ' ') - - VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}" + VN=$(make -sC ../.. kernelversion) fi VN=$(expr "$VN" : v*'\(.*\)') From 96d7303e9cfb6a9bc664174a4dfdb6fa689284fe Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Sun, 5 Jun 2011 20:48:47 +0000 Subject: [PATCH 277/595] ipv4: Fix packet size calculation for raw IPsec packets in __ip_append_data We assume that transhdrlen is positive on the first fragment which is wrong for raw packets. So we don't add exthdrlen to the packet size for raw packets. This leads to a reallocation on IPsec because we have not enough headroom on the skb to place the IPsec headers. This patch fixes this by adding exthdrlen to the packet size whenever the send queue of the socket is empty. This issue was introduced with git commit 1470ddf7 (inet: Remove explicit write references to sk/inet in ip_append_data) Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 98af3697c718..a8024eaa0e87 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -799,7 +799,9 @@ static int __ip_append_data(struct sock *sk, int csummode = CHECKSUM_NONE; struct rtable *rt = (struct rtable *)cork->dst; - exthdrlen = transhdrlen ? rt->dst.header_len : 0; + skb = skb_peek_tail(queue); + + exthdrlen = !skb ? rt->dst.header_len : 0; length += exthdrlen; transhdrlen += exthdrlen; mtu = cork->fragsize; @@ -825,8 +827,6 @@ static int __ip_append_data(struct sock *sk, !exthdrlen) csummode = CHECKSUM_PARTIAL; - skb = skb_peek_tail(queue); - cork->length += length; if (((length > mtu) || (skb && skb_is_gso(skb))) && (sk->sk_protocol == IPPROTO_UDP) && From 5587912fcff1da2ff8494fa33cf9d92dc6982c11 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 9 Jun 2011 15:00:21 -0700 Subject: [PATCH 278/595] ep93xx_eth: Update MAINTAINERS Lennert stated that he has been short on time lately. Since I'm maintaining the ep93xx core stuff, I'm willing to also take over maintaining the Ethernet driver. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Acked-by: Lennert Buytenhek Signed-off-by: David S. Miller --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 29801f760b6f..6a1c430d2821 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1739,7 +1739,7 @@ S: Supported F: drivers/net/enic/ CIRRUS LOGIC EP93XX ETHERNET DRIVER -M: Lennert Buytenhek +M: Hartley Sweeten L: netdev@vger.kernel.org S: Maintained F: drivers/net/arm/ep93xx_eth.c From b4c8cc88c18213688268d1d53a51d97ce2f19a64 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Thu, 9 Jun 2011 15:05:48 -0700 Subject: [PATCH 279/595] ethtool.h: fix typos Signed-off-by: Yegor Yefremov Signed-off-by: David S. Miller --- include/linux/ethtool.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index c6a850ab2ec5..439b173c5882 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -268,7 +268,7 @@ struct ethtool_pauseparam { __u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ /* If the link is being auto-negotiated (via ethtool_cmd.autoneg - * being true) the user may set 'autonet' here non-zero to have the + * being true) the user may set 'autoneg' here non-zero to have the * pause parameters be auto-negotiated too. In such a case, the * {rx,tx}_pause values below determine what capabilities are * advertised. @@ -811,7 +811,7 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * @get_tx_csum: Deprecated as redundant. Report whether transmit checksums * are turned on or off. * @set_tx_csum: Deprecated in favour of generic netdev features. Turn - * transmit checksums on or off. Returns a egative error code or zero. + * transmit checksums on or off. Returns a negative error code or zero. * @get_sg: Deprecated as redundant. Report whether scatter-gather is * enabled. * @set_sg: Deprecated in favour of generic netdev features. Turn @@ -1087,7 +1087,7 @@ struct ethtool_ops { /* The following are all involved in forcing a particular link * mode for the device for setting things. When getting the * devices settings, these indicate the current mode and whether - * it was foced up into this mode or autonegotiated. + * it was forced up into this mode or autonegotiated. */ /* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */ From a9011580a99cd4f21546381782582bfaf9e40675 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 9 Jun 2011 23:21:11 +0100 Subject: [PATCH 280/595] ARM: extend Code: line by one 16-bit quantity for Thumb instructions Dump out the following 16-bit instruction to the faulting instruction in the Code: line. This allows Thumb-2 instructions to be properly encoded. Tested-by: Kevin Hilman Signed-off-by: Russell King --- arch/arm/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index c5ead3c2c618..6807cb1e76dd 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -139,7 +139,7 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) fs = get_fs(); set_fs(KERNEL_DS); - for (i = -4; i < 1; i++) { + for (i = -4; i < 1 + !!thumb; i++) { unsigned int val, bad; if (thumb) From a7d82a0a3cd547494294baee7f9764ea44bead73 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Thu, 9 Jun 2011 02:54:08 +0000 Subject: [PATCH 281/595] sparc32, sun4m: bugfix in SMP IPI traphandler Three new IPIs were introduced by commit ecbc42b70acbc6327adefe9635db93fcf62bf59d ("sparc32, sun4m: Implemented SMP IPIs support for SUN4M machines"), the old handler was already prepared for IPIs but handled only IRQ14 and IRQ13, this patch adds support for the new IPI at IRQ12. The IPI trap handler looks at the mask rather than the pending IRQ/IPI, this bug may have masked the problem above, introduced by the same commit. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- arch/sparc/kernel/entry.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index c4e616711348..9fe08a1ea6c6 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -229,7 +229,7 @@ real_irq_entry: #ifdef CONFIG_SMP .globl patchme_maybe_smp_msg - cmp %l7, 12 + cmp %l7, 11 patchme_maybe_smp_msg: bgu maybe_smp4m_msg nop @@ -293,7 +293,7 @@ maybe_smp4m_msg: WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE - sll %o2, 28, %o2 ! shift for simpler checks below + sll %o3, 28, %o2 ! shift for simpler checks below maybe_smp4m_msg_check_single: andcc %o2, 0x1, %g0 beq,a maybe_smp4m_msg_check_mask From 10f0d07c51516bd24b040016c6d4304eef05f115 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Thu, 9 Jun 2011 02:54:09 +0000 Subject: [PATCH 282/595] sparc32, leon: bugfix in LEON SMP interrupt init During converting per-cpu ticker to genirq layer some IRQ initialization code was removed by commit 2cf9530420e446bb61f665d02afeb81070106900 ("sparc32,leon: per-cpu ticker use genirq per-cpu handler"). This patch reintroduces the code at the same place it was removed from. IRQ12 - IRQ14 will crash on LEON SMP without this patch because it will run the SUN4M IRQ trap handler. Reported-by: Jan Andersson Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- arch/sparc/kernel/leon_kernel.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index c23d61e9e52c..d17255a2bbac 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -376,6 +376,22 @@ void __init leon_init_timers(irq_handler_t counter_fn) prom_halt(); } +#ifdef CONFIG_SMP + { + unsigned long flags; + + /* + * In SMP, sun4m adds a IPI handler to IRQ trap handler that + * LEON never must take, sun4d and LEON overwrites the branch + * with a NOP. + */ + local_irq_save(flags); + patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ + local_flush_cache_all(); + local_irq_restore(flags); + } +#endif + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, LEON3_GPTIMER_EN | LEON3_GPTIMER_RL | From 13863a66c9c8a663665445cf05d68de96ff31830 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 9 Jun 2011 23:14:58 +0200 Subject: [PATCH 283/595] genirq: Prevent potential NULL dereference in irq_set_irq_wake() In kernel/irq/manage.c::irq_set_irq_wake() we call irq_get_desc_buslock() which may return NULL, but the code dereferences the result unconditionally. irq_set_irq_wake() has lots of callers - I checked a few and I couldn't find anything that guarantees that they won't call it with some input that will cause irq_get_desc_buslock() to return NULL, so I think it's a good thing to test and -EINVAL was the most sane error code in this situation that I could think of. Not all callers test the return value of irq_set_irq_wake(), but those that do take != 0 to mean error as far as I can see, so they should be fine. I guess those that don't test actually should, but that's a different issue. Signed-off-by: Jesper Juhl Link: http://lkml.kernel.org/r/alpine.LNX.2.00.1106092300360.17868@swampdragon.chaosbits.net Signed-off-by: Thomas Gleixner --- kernel/irq/manage.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index d64bafb1afd0..0a7840aeb0fb 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -491,6 +491,9 @@ int irq_set_irq_wake(unsigned int irq, unsigned int on) struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); int ret = 0; + if (!desc) + return -EINVAL; + /* wakeup-capable irqs can be shared between drivers that * don't need to have the same sleep mode behaviors. */ From 33195500edf260e8c8809ab9dfc67f50e0ce031f Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Fri, 10 Jun 2011 10:36:54 +0900 Subject: [PATCH 284/595] ASoC: SAMSUNG: Fix the incorrect referencing of I2SCON register If DMA active status should be checked, I2SCON register should be referenced. In this patch, Fix the incorrect referencing of I2SCON register. Reported-by : Lakkyung Jung Signed-off-by: Sangbeom Kim Acked-by: Jassi Brar Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/samsung/i2s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index ffa09b3b2caa..992a732b5211 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -191,7 +191,7 @@ static inline bool tx_active(struct i2s_dai *i2s) if (!i2s) return false; - active = readl(i2s->addr + I2SMOD); + active = readl(i2s->addr + I2SCON); if (is_secondary(i2s)) active &= CON_TXSDMA_ACTIVE; @@ -223,7 +223,7 @@ static inline bool rx_active(struct i2s_dai *i2s) if (!i2s) return false; - active = readl(i2s->addr + I2SMOD) & CON_RXDMA_ACTIVE; + active = readl(i2s->addr + I2SCON) & CON_RXDMA_ACTIVE; return active ? true : false; } From ad3e34bba4b64ab8e1f5ea1a17768e1a0d9648ea Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 8 Jun 2011 14:45:50 -0400 Subject: [PATCH 285/595] Btrfs: don't map extent buffer if path->skip_locking is set Arne's scrub stuff exposed a problem with mapping the extent buffer in reada_for_search. He searches the commit root with multiple threads and with skip_locking set, so we can race and overwrite node->map_token since node isn't locked. So fix this so that we only map the extent buffer if we don't already have a map_token and skip_locking isn't set. Without this patch scrub would panic almost immediately, with the patch it doesn't panic anymore. Thanks, Reported-by: Arne Jansen Signed-off-by: Josef Bacik --- fs/btrfs/ctree.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index d84089349c82..2e667868e0d2 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -1228,6 +1228,7 @@ static void reada_for_search(struct btrfs_root *root, u32 nr; u32 blocksize; u32 nscan = 0; + bool map = true; if (level != 1) return; @@ -1249,8 +1250,11 @@ static void reada_for_search(struct btrfs_root *root, nritems = btrfs_header_nritems(node); nr = slot; + if (node->map_token || path->skip_locking) + map = false; + while (1) { - if (!node->map_token) { + if (map && !node->map_token) { unsigned long offset = btrfs_node_key_ptr_offset(nr); map_private_extent_buffer(node, offset, sizeof(struct btrfs_key_ptr), @@ -1277,7 +1281,7 @@ static void reada_for_search(struct btrfs_root *root, if ((search <= target && target - search <= 65536) || (search > target && search - target <= 65536)) { gen = btrfs_node_ptr_generation(node, nr); - if (node->map_token) { + if (map && node->map_token) { unmap_extent_buffer(node, node->map_token, KM_USER1); node->map_token = NULL; @@ -1289,7 +1293,7 @@ static void reada_for_search(struct btrfs_root *root, if ((nread > 65536 || nscan > 32)) break; } - if (node->map_token) { + if (map && node->map_token) { unmap_extent_buffer(node, node->map_token, KM_USER1); node->map_token = NULL; } From 8c51032f978bac5bec5dae0c5de4f85db97c1cc9 Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Fri, 3 Jun 2011 10:09:26 +0200 Subject: [PATCH 286/595] btrfs: scrub: errors in tree enumeration due to the semantics of btrfs_search_slot the path can point to an invalid slot when ret > 0. This condition went unnoticed, which in turn could have led to an incomplete scrubbing. Signed-off-by: Arne Jansen --- fs/btrfs/scrub.c | 57 +++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index df50fd1eca8f..d5a4108cedaf 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -804,18 +804,12 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev, ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) - goto out; - - l = path->nodes[0]; - slot = path->slots[0]; - btrfs_item_key_to_cpu(l, &key, slot); - if (key.objectid != logical) { - ret = btrfs_previous_item(root, path, 0, - BTRFS_EXTENT_ITEM_KEY); - if (ret < 0) - goto out; - } + goto out_noplug; + /* + * we might miss half an extent here, but that doesn't matter, + * as it's only the prefetch + */ while (1) { l = path->nodes[0]; slot = path->slots[0]; @@ -824,7 +818,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev, if (ret == 0) continue; if (ret < 0) - goto out; + goto out_noplug; break; } @@ -906,15 +900,20 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev, ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) goto out; - - l = path->nodes[0]; - slot = path->slots[0]; - btrfs_item_key_to_cpu(l, &key, slot); - if (key.objectid != logical) { + if (ret > 0) { ret = btrfs_previous_item(root, path, 0, BTRFS_EXTENT_ITEM_KEY); if (ret < 0) goto out; + if (ret > 0) { + /* there's no smaller item, so stick with the + * larger one */ + btrfs_release_path(path); + ret = btrfs_search_slot(NULL, root, &key, + path, 0, 0); + if (ret < 0) + goto out; + } } while (1) { @@ -989,6 +988,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev, out: blk_finish_plug(&plug); +out_noplug: btrfs_free_path(path); return ret < 0 ? ret : 0; } @@ -1064,8 +1064,15 @@ int scrub_enumerate_chunks(struct scrub_dev *sdev, u64 start, u64 end) while (1) { ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) - goto out; - ret = 0; + break; + if (ret > 0) { + if (path->slots[0] >= + btrfs_header_nritems(path->nodes[0])) { + ret = btrfs_next_leaf(root, path); + if (ret) + break; + } + } l = path->nodes[0]; slot = path->slots[0]; @@ -1075,7 +1082,7 @@ int scrub_enumerate_chunks(struct scrub_dev *sdev, u64 start, u64 end) if (found_key.objectid != sdev->dev->devid) break; - if (btrfs_key_type(&key) != BTRFS_DEV_EXTENT_KEY) + if (btrfs_key_type(&found_key) != BTRFS_DEV_EXTENT_KEY) break; if (found_key.offset >= end) @@ -1104,7 +1111,7 @@ int scrub_enumerate_chunks(struct scrub_dev *sdev, u64 start, u64 end) cache = btrfs_lookup_block_group(fs_info, chunk_offset); if (!cache) { ret = -ENOENT; - goto out; + break; } ret = scrub_chunk(sdev, chunk_tree, chunk_objectid, chunk_offset, length); @@ -1116,9 +1123,13 @@ int scrub_enumerate_chunks(struct scrub_dev *sdev, u64 start, u64 end) btrfs_release_path(path); } -out: btrfs_free_path(path); - return ret; + + /* + * ret can still be 1 from search_slot or next_leaf, + * that's not an error + */ + return ret < 0 ? ret : 0; } static noinline_for_stack int scrub_supers(struct scrub_dev *sdev) From 632dd772fcbde2ba37c0e8983bd38ef4a1eac906 Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Fri, 10 Jun 2011 12:07:07 +0200 Subject: [PATCH 287/595] btrfs: reinitialize scrub workers Scrub starts the workers each time a scrub starts and stops them after it finished. This patch adds an initialization for the workers before each start, otherwise the workers behave strangely. Signed-off-by: Arne Jansen --- fs/btrfs/disk-io.c | 2 -- fs/btrfs/scrub.c | 6 +++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a203d363184d..7bbbfebe47e4 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1668,8 +1668,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, init_waitqueue_head(&fs_info->scrub_pause_wait); init_rwsem(&fs_info->scrub_super_lock); fs_info->scrub_workers_refcnt = 0; - btrfs_init_workers(&fs_info->scrub_workers, "scrub", - fs_info->thread_pool_size, &fs_info->generic_worker); sb->s_blocksize = 4096; sb->s_blocksize_bits = blksize_bits(4096); diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index d5a4108cedaf..92cac19388ed 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -1166,8 +1166,12 @@ static noinline_for_stack int scrub_workers_get(struct btrfs_root *root) struct btrfs_fs_info *fs_info = root->fs_info; mutex_lock(&fs_info->scrub_lock); - if (fs_info->scrub_workers_refcnt == 0) + if (fs_info->scrub_workers_refcnt == 0) { + btrfs_init_workers(&fs_info->scrub_workers, "scrub", + fs_info->thread_pool_size, &fs_info->generic_worker); + fs_info->scrub_workers.idle_thresh = 4; btrfs_start_workers(&fs_info->scrub_workers, 1); + } ++fs_info->scrub_workers_refcnt; mutex_unlock(&fs_info->scrub_lock); From 6eef3125886df260ca0e8758d141308152226f6a Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Fri, 10 Jun 2011 13:04:58 +0200 Subject: [PATCH 288/595] btrfs: remove unneeded includes from scrub.c Signed-off-by: Arne Jansen --- fs/btrfs/scrub.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 92cac19388ed..a8d03d5efb5d 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -16,13 +16,7 @@ * Boston, MA 021110-1307, USA. */ -#include -#include -#include #include -#include -#include -#include #include "ctree.h" #include "volumes.h" #include "disk-io.h" From 20f5e0b36d968326fab3b720035f226113e34ae9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 10 Jun 2011 09:31:54 +0200 Subject: [PATCH 289/595] ALSA: hda - Fix invalid unsol tag for some alc262 model quirks The tag number was forgotten to be fixed after cleaning up the model quirks for ALC262 fujitsu and lenovo-3000 models. Tested-by: Michal Hocko Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d7007896772b..ca211c1cba03 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -11924,7 +11924,7 @@ static const struct hda_verb alc262_nec_verbs[] = { * 0x1b = port replicator headphone out */ -#define ALC_HP_EVENT 0x37 +#define ALC_HP_EVENT ALC880_HP_EVENT static const struct hda_verb alc262_fujitsu_unsol_verbs[] = { {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, From c0a20263dbe1fc5f394913d71063c9cd8282c5db Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 10 Jun 2011 15:28:15 +0200 Subject: [PATCH 290/595] ALSA: hda - Fix initialization of hp pins with master_mute in Realtek Some Reatlek model quirks use master_mute bool switch for controlling the master-mute of outputs. For these cases, the initialization of HP pins/amps were forgotten during the transition to the common automute helper function in 3.0 development time, and resulted in the muted HP output as default. This patch fixes the issue by adjusting the HP output explicitly with master_mute switch. Tested-by: Michal Hocko Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ca211c1cba03..43fcfbd32847 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1141,6 +1141,13 @@ static void update_speakers(struct hda_codec *codec) struct alc_spec *spec = codec->spec; int on; + /* Control HP pins/amps depending on master_mute state; + * in general, HP pins/amps control should be enabled in all cases, + * but currently set only for master_mute, just to be safe + */ + do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins), + spec->autocfg.hp_pins, spec->master_mute, true); + if (!spec->automute) on = 0; else @@ -6201,11 +6208,6 @@ static const struct snd_kcontrol_new alc260_input_mixer[] = { /* update HP, line and mono out pins according to the master switch */ static void alc260_hp_master_update(struct hda_codec *codec) { - struct alc_spec *spec = codec->spec; - - /* change HP pins */ - do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins), - spec->autocfg.hp_pins, spec->master_mute, true); update_speakers(codec); } From 890ee02ac12c02c4712b6d7dd062ff4d6d37691c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 10 Jun 2011 15:32:31 +0200 Subject: [PATCH 291/595] ALSA: Use %pV for snd_printk() Clean up snd_printk() helper using the %pV prefix for recursive printks. This also automagically fixes an Oops with RO/NX-enabled modules. Tested-by: Maarten Lankhorst Signed-off-by: Takashi Iwai --- sound/core/misc.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/sound/core/misc.c b/sound/core/misc.c index 2c41825c836e..eb9fe2e1d291 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -58,26 +58,6 @@ static const char *sanity_file_name(const char *path) else return path; } - -/* print file and line with a certain printk prefix */ -static int print_snd_pfx(unsigned int level, const char *path, int line, - const char *format) -{ - const char *file = sanity_file_name(path); - char tmp[] = "<0>"; - const char *pfx = level ? KERN_DEBUG : KERN_DEFAULT; - int ret = 0; - - if (format[0] == '<' && format[2] == '>') { - tmp[1] = format[1]; - pfx = tmp; - ret = 1; - } - printk("%sALSA %s:%d: ", pfx, file, line); - return ret; -} -#else -#define print_snd_pfx(level, path, line, format) 0 #endif #if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK) @@ -85,15 +65,29 @@ void __snd_printk(unsigned int level, const char *path, int line, const char *format, ...) { va_list args; - +#ifdef CONFIG_SND_VERBOSE_PRINTK + struct va_format vaf; + char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV"; +#endif + #ifdef CONFIG_SND_DEBUG if (debug < level) return; #endif + va_start(args, format); - if (print_snd_pfx(level, path, line, format)) - format += 3; /* skip the printk level-prefix */ +#ifdef CONFIG_SND_VERBOSE_PRINTK + vaf.fmt = format; + vaf.va = &args; + if (format[0] == '<' && format[2] == '>') { + memcpy(verbose_fmt, format, 3); + vaf.fmt = format + 3; + } else if (level) + memcpy(verbose_fmt, KERN_DEBUG, 3); + printk(verbose_fmt, sanity_file_name(path), line, &vaf); +#else vprintk(format, args); +#endif va_end(args); } EXPORT_SYMBOL_GPL(__snd_printk); From 7ab1fc0af3464d231e17eb729a03495d93d0cc5c Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Fri, 10 Jun 2011 10:14:01 -0400 Subject: [PATCH 292/595] ALSA: hda: Fix inaudible internal speakers on CyberpowerPC Gamer Xplorer N57001 laptop BugLink: https://launchpad.net/bugs/761171 The original reporter needs the model=auto quirk for his internal speakers to be audible in the latest daily snapshot, so add an entry in the quirk table for his PCI SSID. A trivially different version of this patch using the model=asus quirk should be applied to the 2.6.38 and 2.6.39 stable kernels. We don't use the asus quirk in 3.0-rc2, because 3.0-rc2's autoparser is much improved. Reported-and-tested-by: tomdeering7 Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 3e6b9a8539c2..694b9daf691f 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3102,6 +3102,7 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO), SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */ + SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO), {} }; From e5ea3f12d41d96edf4ad9374db2b1725e457acec Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Fri, 10 Jun 2011 13:44:49 +0100 Subject: [PATCH 293/595] gpio/basic_mmio: add missing include of spinlock_types.h include/linux/basic_mmio_gpio.h uses a spinlock_t without including any of the spinlock headers resulting in this compiler warning. include/linux/basic_mmio_gpio.h:51:2: error: expected specifier-qualifier-list before 'spinlock_t' Explicitly include linux/spinlock_types.h to fix it. Signed-off-by: Jamie Iles Signed-off-by: Grant Likely --- include/linux/basic_mmio_gpio.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/basic_mmio_gpio.h b/include/linux/basic_mmio_gpio.h index 1ae12710d732..98999cf107ce 100644 --- a/include/linux/basic_mmio_gpio.h +++ b/include/linux/basic_mmio_gpio.h @@ -16,6 +16,7 @@ #include #include #include +#include struct bgpio_pdata { int base; From 0da67bed835fdde68ca0e924d2a2d6ac82c70833 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 12 May 2011 11:13:15 +0300 Subject: [PATCH 294/595] Bluetooth: fix shutdown on SCO sockets shutdown should wait for SCO link to be properly disconnected before detroying the socket, otherwise an application using the socket may assume link is properly disconnected before it really happens which can be a problem when e.g synchronizing profile switch. Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Gustavo F. Padovan --- net/bluetooth/sco.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 42fdffd1d76c..cb4fb7837e5c 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -369,6 +369,15 @@ static void __sco_sock_close(struct sock *sk) case BT_CONNECTED: case BT_CONFIG: + if (sco_pi(sk)->conn) { + sk->sk_state = BT_DISCONN; + sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT); + hci_conn_put(sco_pi(sk)->conn->hcon); + sco_pi(sk)->conn->hcon = NULL; + } else + sco_chan_del(sk, ECONNRESET); + break; + case BT_CONNECT: case BT_DISCONN: sco_chan_del(sk, ECONNRESET); @@ -819,7 +828,9 @@ static void sco_chan_del(struct sock *sk, int err) conn->sk = NULL; sco_pi(sk)->conn = NULL; sco_conn_unlock(conn); - hci_conn_put(conn->hcon); + + if (conn->hcon) + hci_conn_put(conn->hcon); } sk->sk_state = BT_CLOSED; From 26e7acf315ba5fc5ac4e7cbdb422a345e59898bd Mon Sep 17 00:00:00 2001 From: David Miller Date: Thu, 19 May 2011 17:37:45 -0400 Subject: [PATCH 295/595] Bluetooth: Do not ignore errors returned from strict_strtol() Signed-off-by: David S. Miller Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/btmrvl_debugfs.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c index fd6305bf953e..8ecf4c6c2874 100644 --- a/drivers/bluetooth/btmrvl_debugfs.c +++ b/drivers/bluetooth/btmrvl_debugfs.c @@ -64,6 +64,8 @@ static ssize_t btmrvl_hscfgcmd_write(struct file *file, return -EFAULT; ret = strict_strtol(buf, 10, &result); + if (ret) + return ret; priv->btmrvl_dev.hscfgcmd = result; @@ -108,6 +110,8 @@ static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf, return -EFAULT; ret = strict_strtol(buf, 10, &result); + if (ret) + return ret; priv->btmrvl_dev.psmode = result; @@ -147,6 +151,8 @@ static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf, return -EFAULT; ret = strict_strtol(buf, 10, &result); + if (ret) + return ret; priv->btmrvl_dev.pscmd = result; @@ -191,6 +197,8 @@ static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf, return -EFAULT; ret = strict_strtol(buf, 16, &result); + if (ret) + return ret; priv->btmrvl_dev.gpio_gap = result; @@ -230,6 +238,8 @@ static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf, return -EFAULT; ret = strict_strtol(buf, 10, &result); + if (ret) + return ret; priv->btmrvl_dev.hscmd = result; if (priv->btmrvl_dev.hscmd) { @@ -272,6 +282,8 @@ static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf, return -EFAULT; ret = strict_strtol(buf, 10, &result); + if (ret) + return ret; priv->btmrvl_dev.hsmode = result; From 7f4f0572df6c8eaa6a587bc212b0806ff37380dd Mon Sep 17 00:00:00 2001 From: Ville Tervo Date: Fri, 27 May 2011 11:16:21 +0300 Subject: [PATCH 296/595] Bluetooth: Do not send SET_EVENT_MASK for 1.1 and earlier devices Some old hci controllers do not accept any mask so leave the default mask on for these devices. < HCI Command: Set Event Mask (0x03|0x0001) plen 8 Mask: 0xfffffbff00000000 > HCI Event: Command Complete (0x0e) plen 4 Set Event Mask (0x03|0x0001) ncmd 1 status 0x12 Error: Invalid HCI Command Parameters Signed-off-by: Ville Tervo Tested-by: Corey Boyle Tested-by: Ed Tomlinson Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index f13ddbf858ba..77930aa522e3 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -477,14 +477,16 @@ static void hci_setup_event_mask(struct hci_dev *hdev) * command otherwise */ u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; - /* Events for 1.2 and newer controllers */ - if (hdev->lmp_ver > 1) { - events[4] |= 0x01; /* Flow Specification Complete */ - events[4] |= 0x02; /* Inquiry Result with RSSI */ - events[4] |= 0x04; /* Read Remote Extended Features Complete */ - events[5] |= 0x08; /* Synchronous Connection Complete */ - events[5] |= 0x10; /* Synchronous Connection Changed */ - } + /* CSR 1.1 dongles does not accept any bitfield so don't try to set + * any event mask for pre 1.2 devices */ + if (hdev->lmp_ver <= 1) + return; + + events[4] |= 0x01; /* Flow Specification Complete */ + events[4] |= 0x02; /* Inquiry Result with RSSI */ + events[4] |= 0x04; /* Read Remote Extended Features Complete */ + events[5] |= 0x08; /* Synchronous Connection Complete */ + events[5] |= 0x10; /* Synchronous Connection Changed */ if (hdev->features[3] & LMP_RSSI_INQ) events[4] |= 0x04; /* Inquiry Result with RSSI */ From 38e87880666091fe9c572a7a2ed2e771d97ca5aa Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 10 Jun 2011 16:36:57 -0400 Subject: [PATCH 297/595] Btrfs: make sure to recheck for bitmaps in clusters Josef recently changed the free extent cache to look in the block group cluster for any bitmaps before trying to add a new bitmap for the same offset. This avoids BUG_ON()s due covering duplicate ranges. But it didn't go quite far enough. A given free range might span between one or more bitmaps or free space entries. The code has looping to cover this, but it doesn't check for clustered bitmaps every time. This shuffles our gotos to check for a bitmap in the cluster for every new bitmap entry we try to add. Signed-off-by: Chris Mason --- fs/btrfs/free-space-cache.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 38f3fd923043..9f985a429877 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1492,7 +1492,7 @@ static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl, if (ctl->op == &free_space_op) block_group = ctl->private; - +again: /* * Since we link bitmaps right into the cluster we need to see if we * have a cluster here, and if so and it has our bitmap we need to add @@ -1510,13 +1510,13 @@ static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl, node = rb_first(&cluster->root); if (!node) { spin_unlock(&cluster->lock); - goto again; + goto no_cluster_bitmap; } entry = rb_entry(node, struct btrfs_free_space, offset_index); if (!entry->bitmap) { spin_unlock(&cluster->lock); - goto again; + goto no_cluster_bitmap; } if (entry->offset == offset_to_bitmap(ctl, offset)) { @@ -1531,7 +1531,8 @@ static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl, goto out; } } -again: + +no_cluster_bitmap: bitmap_info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 1, 0); if (!bitmap_info) { From 38e880540f983045da7a00fbc50daad238207fc5 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 10 Jun 2011 18:43:13 +0000 Subject: [PATCH 298/595] Btrfs: clear current->journal_info on async transaction commit Normally current->jouranl_info is cleared by commit_transaction. For an async snap or subvol creation, though, it runs in a work queue. Clear it in btrfs_commit_transaction_async() to avoid leaking a non-NULL journal_info when we return to userspace. When the actual commit runs in the other thread it won't care that it's current->journal_info is already NULL. Signed-off-by: Sage Weil Tested-by: Jim Schutt Signed-off-by: Chris Mason --- fs/btrfs/transaction.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 6b2e4786d189..2b3590b9fe98 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1118,8 +1118,11 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans, wait_current_trans_commit_start_and_unblock(root, cur_trans); else wait_current_trans_commit_start(root, cur_trans); - put_transaction(cur_trans); + if (current->journal_info == trans) + current->journal_info = NULL; + + put_transaction(cur_trans); return 0; } From 9eb9104c665aae2401a1723c044669eb10240072 Mon Sep 17 00:00:00 2001 From: richard kennedy Date: Tue, 7 Jun 2011 10:46:32 +0000 Subject: [PATCH 299/595] btrfs: remove 64bit alignment padding to allow extent_buffer to fit into one fewer cacheline Reorder extent_buffer to remove 8 bytes of alignment padding on 64 bit builds. This shrinks its size to 128 bytes allowing it to fit into one fewer cache lines and allows more objects per slab in its kmem_cache. slabinfo extent_buffer reports :- before:- Sizes (bytes) Slabs ---------------------------------- Object : 136 Total : 123 SlabObj: 136 Full : 121 SlabSiz: 4096 Partial: 0 Loss : 0 CpuSlab: 2 Align : 8 Objects: 30 after :- Object : 128 Total : 4 SlabObj: 128 Full : 2 SlabSiz: 4096 Partial: 0 Loss : 0 CpuSlab: 2 Align : 8 Objects: 32 Signed-off-by: Richard Kennedy Signed-off-by: Chris Mason --- fs/btrfs/extent_io.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 4e8445a4757c..a11a92ee2d30 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -126,9 +126,9 @@ struct extent_buffer { unsigned long map_len; struct page *first_page; unsigned long bflags; - atomic_t refs; struct list_head leak_list; struct rcu_head rcu_head; + atomic_t refs; /* the spinlock is used to protect most operations */ spinlock_t lock; From 027ed2f0044e95a97ed34db2d55a9ca95ba84385 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 8 Jun 2011 08:27:56 +0000 Subject: [PATCH 300/595] Btrfs: avoid stack bloat in btrfs_ioctl_fs_info() The size of struct btrfs_ioctl_fs_info_args is as big as 1KB, so don't declare the variable on stack. Signed-off-by: Li Zefan Reviewed-by: Josef Bacik Signed-off-by: Chris Mason --- fs/btrfs/ioctl.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index ac37040e426a..b793d112d1f6 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2054,29 +2054,34 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) static long btrfs_ioctl_fs_info(struct btrfs_root *root, void __user *arg) { - struct btrfs_ioctl_fs_info_args fi_args; + struct btrfs_ioctl_fs_info_args *fi_args; struct btrfs_device *device; struct btrfs_device *next; struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; + int ret = 0; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - fi_args.num_devices = fs_devices->num_devices; - fi_args.max_id = 0; - memcpy(&fi_args.fsid, root->fs_info->fsid, sizeof(fi_args.fsid)); + fi_args = kzalloc(sizeof(*fi_args), GFP_KERNEL); + if (!fi_args) + return -ENOMEM; + + fi_args->num_devices = fs_devices->num_devices; + memcpy(&fi_args->fsid, root->fs_info->fsid, sizeof(fi_args->fsid)); mutex_lock(&fs_devices->device_list_mutex); list_for_each_entry_safe(device, next, &fs_devices->devices, dev_list) { - if (device->devid > fi_args.max_id) - fi_args.max_id = device->devid; + if (device->devid > fi_args->max_id) + fi_args->max_id = device->devid; } mutex_unlock(&fs_devices->device_list_mutex); - if (copy_to_user(arg, &fi_args, sizeof(fi_args))) - return -EFAULT; + if (copy_to_user(arg, fi_args, sizeof(*fi_args))) + ret = -EFAULT; - return 0; + kfree(fi_args); + return ret; } static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg) From 5be76758f35ec6578e5b9b150aa513ac26bd9c54 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Thu, 9 Jun 2011 10:02:51 +0000 Subject: [PATCH 301/595] btrfs: fix unlocked access of delalloc_inodes list_splice_init will make delalloc_inodes empty, but without a spinlock around, this may produce corrupted list head, accessed in many placess, The race window is very tight and nobody seems to have hit it so far. Signed-off-by: David Sterba Signed-off-by: Chris Mason --- fs/btrfs/disk-io.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a203d363184d..33b744a5ac03 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2911,9 +2911,8 @@ static int btrfs_destroy_delalloc_inodes(struct btrfs_root *root) INIT_LIST_HEAD(&splice); - list_splice_init(&root->fs_info->delalloc_inodes, &splice); - spin_lock(&root->fs_info->delalloc_lock); + list_splice_init(&root->fs_info->delalloc_inodes, &splice); while (!list_empty(&splice)) { btrfs_inode = list_entry(splice.next, struct btrfs_inode, From 08d2f347e877e489ca098c87a6fd2e872fef9767 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Wed, 4 May 2011 16:18:50 +0200 Subject: [PATCH 302/595] Btrfs: fix extent state leak on failed nodatasum reads When encountering an EIO while reading from a nodatasum extent, we insert an error record into the inode's failure tree. btrfs_readpage_end_io_hook returns early for nodatasum inodes. We'd better clear the failure tree in that case, otherwise the kernel complains about BUG extent_state: Objects remaining on kmem_cache_close() on rmmod. Signed-off-by: Jan Schmidt Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 02ff4a1b968b..113913ae36e0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1986,7 +1986,7 @@ static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end, } if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) - return 0; + goto good; if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID && test_range_bit(io_tree, start, end, EXTENT_NODATASUM, 1, NULL)) { From 22b63a2971c5657dfc1bf4514f9410fc90c8b2c2 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Wed, 9 Feb 2011 16:05:31 +0200 Subject: [PATCH 303/595] Btrfs - use %pU to print fsid Get rid of FIXME comment. Uuids from dmesg are now the same as uuids given by btrfs-progs. Signed-off-by: Ilya Dryomov Signed-off-by: Chris Mason --- fs/btrfs/volumes.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index da541dfca2e3..1efa56e18f9b 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -689,12 +689,8 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, transid = btrfs_super_generation(disk_super); if (disk_super->label[0]) printk(KERN_INFO "device label %s ", disk_super->label); - else { - /* FIXME, make a readl uuid parser */ - printk(KERN_INFO "device fsid %llx-%llx ", - *(unsigned long long *)disk_super->fsid, - *(unsigned long long *)(disk_super->fsid + 8)); - } + else + printk(KERN_INFO "device fsid %pU ", disk_super->fsid); printk(KERN_CONT "devid %llu transid %llu %s\n", (unsigned long long)devid, (unsigned long long)transid, path); ret = device_list_add(path, disk_super, devid, fs_devices_ret); From 8f4b8c7613928d5c6da43715fedc00a7b1ee53be Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 11 Jun 2011 00:43:21 +0100 Subject: [PATCH 304/595] ARM: initrd: disable initrds outside of memory We can't cope with initrds outside of memory, so check that the initrd is within some declared memory to the kernel before using it. Otherwise we're likely to OOPS during boot. Signed-off-by: Russell King --- arch/arm/mm/init.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index b2cf9460ea60..c19571c40a21 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -330,6 +330,12 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) memblock_reserve(__pa(_stext), _end - _stext); #endif #ifdef CONFIG_BLK_DEV_INITRD + if (phys_initrd_size && + !memblock_is_region_memory(phys_initrd_start, phys_initrd_size)) { + pr_err("INITRD: 0x%08lx+0x%08lx is not a memory region - disabling initrd\n", + phys_initrd_start, phys_initrd_size); + phys_initrd_start = phys_initrd_size = 0; + } if (phys_initrd_size && memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) { pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region - disabling initrd\n", From e172dedd89a342b30fddfafd820d2ef40c039cea Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 11 Jun 2011 00:44:35 +0100 Subject: [PATCH 305/595] ARM: footbridge: fix debug macros More of the same of 5f2c1b30 (ARM: footbridge: fix debug macros), this time for the DC21285-based debugging code rather than the 8250- based debugging code. Signed-off-by: Russell King --- arch/arm/mach-footbridge/include/mach/debug-macro.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-footbridge/include/mach/debug-macro.S b/arch/arm/mach-footbridge/include/mach/debug-macro.S index 30b971d65815..1be2eeb7a0a0 100644 --- a/arch/arm/mach-footbridge/include/mach/debug-macro.S +++ b/arch/arm/mach-footbridge/include/mach/debug-macro.S @@ -26,6 +26,7 @@ #include #else +#include /* For EBSA285 debugging */ .equ dc21285_high, ARMCSR_BASE & 0xff000000 .equ dc21285_low, ARMCSR_BASE & 0x00ffffff @@ -36,8 +37,8 @@ .else mov \rp, #0 .endif - orr \rv, \rp, #0x42000000 - orr \rp, \rp, #dc21285_high + orr \rv, \rp, #dc21285_high + orr \rp, \rp, #0x42000000 .endm .macro senduart,rd,rx From 7d7975a0e1da7d6e558211b6296a96f1d6bf60ce Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 11 Jun 2011 00:46:17 +0100 Subject: [PATCH 306/595] ARM: footbridge: fix clock event support 4e8d7637 (ARM: footbridge: convert to clockevents/clocksource) did not set the cpumask for the clock event device. This causes boot to fail. Add the necessary initialization. Signed-off-by: Russell King --- arch/arm/mach-footbridge/dc21285-timer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index 5f1f9867fc70..121ad1d4fa39 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -103,6 +103,7 @@ static void __init footbridge_timer_init(void) clockevents_calc_mult_shift(ce, mem_fclk_21285, 5); ce->max_delta_ns = clockevent_delta2ns(0xffffff, ce); ce->min_delta_ns = clockevent_delta2ns(0x000004, ce); + ce->cpumask = cpumask_of(smp_processor_id()); clockevents_register_device(ce); } From fe744fdb74f2417d8571faefa45f72b0ead25f89 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 25 May 2011 23:00:27 +0900 Subject: [PATCH 307/595] nilfs2: fix incorrect block address termination in node concatenation nilfs_btree_delete function wrongly terminates virtual block address of the btree node held by its parent at index 0. When concatenating the index-0 node with its right sibling node, nilfs_btree_delete terminates the block address of index-0 node instead of the right sibling node which should be deleted. This bug not only wears disk space in the long run, but also causes file system corruption. This will fix it. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/btree.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index 7eafe468a29c..fd4f05b91942 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -1356,20 +1356,19 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, struct buffer_head *bh; struct nilfs_btree_node *node, *parent, *sib; __u64 sibptr; - int pindex, level, ncmin, ncmax, ncblk, ret; + int pindex, dindex, level, ncmin, ncmax, ncblk, ret; ret = 0; stats->bs_nblocks = 0; ncmin = NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree)); ncblk = nilfs_btree_nchildren_per_block(btree); - for (level = NILFS_BTREE_LEVEL_NODE_MIN; + for (level = NILFS_BTREE_LEVEL_NODE_MIN, dindex = path[level].bp_index; level < nilfs_btree_height(btree) - 1; level++) { node = nilfs_btree_get_nonroot_node(path, level); path[level].bp_oldreq.bpr_ptr = - nilfs_btree_node_get_ptr(node, path[level].bp_index, - ncblk); + nilfs_btree_node_get_ptr(node, dindex, ncblk); ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat); if (ret < 0) @@ -1383,6 +1382,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); pindex = path[level + 1].bp_index; + dindex = pindex; if (pindex > 0) { /* left sibling */ @@ -1421,6 +1421,14 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, path[level].bp_sib_bh = bh; path[level].bp_op = nilfs_btree_concat_right; stats->bs_nblocks++; + /* + * When merging right sibling node + * into the current node, pointer to + * the right sibling node must be + * terminated instead. The adjustment + * below is required for that. + */ + dindex = pindex + 1; /* continue; */ } } else { @@ -1443,7 +1451,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, node = nilfs_btree_get_root(btree); path[level].bp_oldreq.bpr_ptr = - nilfs_btree_node_get_ptr(node, path[level].bp_index, + nilfs_btree_node_get_ptr(node, dindex, NILFS_BTREE_ROOT_NCHILDREN_MAX); ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat); From d40990537c9ea85dfe75dbe0ffba5e1002dfdf3f Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 25 May 2011 23:00:27 +0900 Subject: [PATCH 308/595] nilfs2: fix missing block address termination in btree node shrinking nilfs_btree_delete function does not terminate part of virtual block addresses when shrinking the last remaining child node into the root node. The missing address termination causes that dead btree node blocks persist and chip away free disk space. This fixes the leak bug on the btree node deletion. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/btree.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index fd4f05b91942..b2e3ff347620 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -1346,6 +1346,11 @@ static void nilfs_btree_shrink(struct nilfs_bmap *btree, path[level].bp_bh = NULL; } +static void nilfs_btree_nop(struct nilfs_bmap *btree, + struct nilfs_btree_path *path, + int level, __u64 *keyp, __u64 *ptrp) +{ +} static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, struct nilfs_btree_path *path, @@ -1439,16 +1444,22 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, NILFS_BTREE_ROOT_NCHILDREN_MAX) { path[level].bp_op = nilfs_btree_shrink; stats->bs_nblocks += 2; + level++; + path[level].bp_op = nilfs_btree_nop; + goto shrink_root_child; } else { path[level].bp_op = nilfs_btree_do_delete; stats->bs_nblocks++; + goto out; } - - goto out; - } } + /* child of the root node is deleted */ + path[level].bp_op = nilfs_btree_do_delete; + stats->bs_nblocks++; + +shrink_root_child: node = nilfs_btree_get_root(btree); path[level].bp_oldreq.bpr_ptr = nilfs_btree_node_get_ptr(node, dindex, @@ -1458,10 +1469,6 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, if (ret < 0) goto err_out_child_node; - /* child of the root node is deleted */ - path[level].bp_op = nilfs_btree_do_delete; - stats->bs_nblocks++; - /* success */ out: *levelp = level; From 071d73cfe5c38cf62338b952bd350ff3de541b75 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 10 Jun 2011 00:33:06 +0900 Subject: [PATCH 309/595] nilfs2: fix problem in setting checkpoint interval Checkpoint generation interval of nilfs goes wrong after user has changed the interval parameter with nilfs-tune tool. segctord starting. Construction interval = 5 seconds, CP frequency < 30 seconds segctord starting. Construction interval = 0 seconds, CP frequency < 30 seconds This turned out to be caused by a trivial bug in initialization code of log writer. This will fix it. Reported-by: Andrea Gelmini Signed-off-by: Ryusuke Konishi --- fs/nilfs2/segment.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 141646e88fb5..bb24ab6c282f 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -2573,7 +2573,7 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb, sci->sc_watermark = NILFS_SC_DEFAULT_WATERMARK; if (nilfs->ns_interval) - sci->sc_interval = nilfs->ns_interval; + sci->sc_interval = HZ * nilfs->ns_interval; if (nilfs->ns_watermark) sci->sc_watermark = nilfs->ns_watermark; return sci; From 30b4caf5d73af5c99cf1b2b46496d8bc35330992 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 8 Jun 2011 03:56:44 +0000 Subject: [PATCH 310/595] Btrfs: use join_transaction in btrfs_evict_inode() The WARN_ON() in start_transaction() was triggered while balancing. The cause is btrfs_relocate_chunk() started a transaction and then called iput() on the inode that stores free space cache, and iput() called btrfs_start_transaction() again. Reported-by: Tsutomu Itoh Signed-off-by: Li Zefan Reviewed-by: Josef Bacik Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 113913ae36e0..c15636b17874 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3646,7 +3646,7 @@ void btrfs_evict_inode(struct inode *inode) btrfs_i_size_write(inode, 0); while (1) { - trans = btrfs_start_transaction(root, 0); + trans = btrfs_join_transaction(root); BUG_ON(IS_ERR(trans)); trans->block_rsv = root->orphan_block_rsv; From 56a210526adb2854d5b7c398a40260720390ee05 Mon Sep 17 00:00:00 2001 From: David Howells Date: Sat, 11 Jun 2011 12:29:58 +0100 Subject: [PATCH 311/595] linux/seqlock.h should #include asm/processor.h for cpu_relax() It uses cpu_relax(), and so needs Without this patch, I see: CC arch/mn10300/kernel/asm-offsets.s In file included from include/linux/time.h:8, from include/linux/timex.h:56, from include/linux/sched.h:57, from arch/mn10300/kernel/asm-offsets.c:7: include/linux/seqlock.h: In function 'read_seqbegin': include/linux/seqlock.h:91: error: implicit declaration of function 'cpu_relax' whilst building asb2364_defconfig on MN10300. Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- include/linux/seqlock.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h index e9811892844f..c6db9fb33c44 100644 --- a/include/linux/seqlock.h +++ b/include/linux/seqlock.h @@ -28,6 +28,7 @@ #include #include +#include typedef struct { unsigned sequence; From 3307d0d83b7bf636dc6dd2aa4a584d0f52cc185b Mon Sep 17 00:00:00 2001 From: Connor Hansen Date: Sat, 11 Jun 2011 15:06:48 -0700 Subject: [PATCH 312/595] ide-cd: signedness warning fix again One of the legit warnings 'make W=3 drivers/ide/ide-cd.c' generates is: drivers/ide/ide-cd.c: In function ide_cd_do_request drivers/ide/ide-cd.c:828:2: warning: conversion to int from \ unsigned int may change the sign of the result drivers/ide/ide-cd.c:833:2: warning: conversion to int from \ unsigned int may change the sign of the result nsectors is declared int, should be unsigned int. blk_rq_sectors() returns unsigned int, and ide_complete_rq expects unsigned int as well. Fixes both warnings. Signed-off-by: Connor Hansen Signed-off-by: David S. Miller --- drivers/ide/ide-cd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 144d27261e43..04b09564bfa9 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -778,7 +778,8 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, sector_t block) { struct ide_cmd cmd; - int uptodate = 0, nsectors; + int uptodate = 0; + unsigned int nsectors; ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, block: %llu", rq->cmd[0], (unsigned long long)block); From d814dee0e1a5d9b2f858b91551a0dd0608f777a1 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Fri, 10 Jun 2011 00:51:54 +0000 Subject: [PATCH 313/595] NET: am79c961: ensure asm() statements are marked volatile Without this the compiler can (and does) optimize register reads away from within loops, and other such optimizations. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/arm/am79c961a.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 0c9217f48b72..084b67fbe7aa 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -50,7 +50,7 @@ static const char version[] = #ifdef __arm__ static void write_rreg(u_long base, u_int reg, u_int val) { - __asm__( + asm volatile( "str%?h %1, [%2] @ NET_RAP\n\t" "str%?h %0, [%2, #-4] @ NET_RDP" : @@ -60,7 +60,7 @@ static void write_rreg(u_long base, u_int reg, u_int val) static inline unsigned short read_rreg(u_long base_addr, u_int reg) { unsigned short v; - __asm__( + asm volatile( "str%?h %1, [%2] @ NET_RAP\n\t" "ldr%?h %0, [%2, #-4] @ NET_RDP" : "=r" (v) @@ -70,7 +70,7 @@ static inline unsigned short read_rreg(u_long base_addr, u_int reg) static inline void write_ireg(u_long base, u_int reg, u_int val) { - __asm__( + asm volatile( "str%?h %1, [%2] @ NET_RAP\n\t" "str%?h %0, [%2, #8] @ NET_IDP" : @@ -80,7 +80,7 @@ static inline void write_ireg(u_long base, u_int reg, u_int val) static inline unsigned short read_ireg(u_long base_addr, u_int reg) { u_short v; - __asm__( + asm volatile( "str%?h %1, [%2] @ NAT_RAP\n\t" "ldr%?h %0, [%2, #8] @ NET_IDP\n\t" : "=r" (v) @@ -131,7 +131,7 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned length = (length + 1) & ~1; if ((int)buf & 2) { unsigned int tmp; - __asm__ __volatile__( + asm volatile( "ldr%?h %2, [%0], #4\n\t" "str%?b %2, [%1], #1\n\t" "mov%? %2, %2, lsr #8\n\t" @@ -141,7 +141,7 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned } while (length > 8) { unsigned int tmp, tmp2, tmp3; - __asm__ __volatile__( + asm volatile( "ldr%?h %2, [%0], #4\n\t" "ldr%?h %3, [%0], #4\n\t" "orr%? %2, %2, %3, lsl #16\n\t" @@ -155,7 +155,7 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned } while (length > 0) { unsigned int tmp; - __asm__ __volatile__( + asm volatile( "ldr%?h %2, [%0], #4\n\t" "str%?b %2, [%1], #1\n\t" "mov%? %2, %2, lsr #8\n\t" From bfc6501324427a97814de1587f89d73bf8677057 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Fri, 10 Jun 2011 00:52:14 +0000 Subject: [PATCH 314/595] NET: am79c961: ensure multicast filter is correctly set at open We were clearing out the multicast filter whenever the interface was upped, and not setting the mode bits correctly. This can cause problems if there are any multicast addresses already set at this point, or if ALLMULTI was set. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/arm/am79c961a.c | 77 +++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 084b67fbe7aa..79d88a0b00a3 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -196,6 +196,42 @@ am79c961_ramtest(struct net_device *dev, unsigned int val) return errorcount; } +static void am79c961_mc_hash(char *addr, u16 *hash) +{ + if (addr[0] & 0x01) { + int idx, bit; + u32 crc; + + crc = ether_crc_le(ETH_ALEN, addr); + + idx = crc >> 30; + bit = (crc >> 26) & 15; + + hash[idx] |= 1 << bit; + } +} + +static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash) +{ + unsigned int mode = MODE_PORT_10BT; + + if (dev->flags & IFF_PROMISC) { + mode |= MODE_PROMISC; + memset(hash, 0xff, 4 * sizeof(*hash)); + } else if (dev->flags & IFF_ALLMULTI) { + memset(hash, 0xff, 4 * sizeof(*hash)); + } else { + struct netdev_hw_addr *ha; + + memset(hash, 0, 4 * sizeof(*hash)); + + netdev_for_each_mc_addr(ha, dev) + am79c961_mc_hash(ha->addr, hash); + } + + return mode; +} + static void am79c961_init_for_open(struct net_device *dev) { @@ -203,6 +239,7 @@ am79c961_init_for_open(struct net_device *dev) unsigned long flags; unsigned char *p; u_int hdr_addr, first_free_addr; + u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash); int i; /* @@ -218,16 +255,12 @@ am79c961_init_for_open(struct net_device *dev) write_ireg (dev->base_addr, 2, 0x0000); /* MODE register selects media */ for (i = LADRL; i <= LADRH; i++) - write_rreg (dev->base_addr, i, 0); + write_rreg (dev->base_addr, i, multi_hash[i - LADRL]); for (i = PADRL, p = dev->dev_addr; i <= PADRH; i++, p += 2) write_rreg (dev->base_addr, i, p[0] | (p[1] << 8)); - i = MODE_PORT_10BT; - if (dev->flags & IFF_PROMISC) - i |= MODE_PROMISC; - - write_rreg (dev->base_addr, MODE, i); + write_rreg (dev->base_addr, MODE, mode); write_rreg (dev->base_addr, POLLINT, 0); write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS); write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS); @@ -340,21 +373,6 @@ am79c961_close(struct net_device *dev) return 0; } -static void am79c961_mc_hash(char *addr, unsigned short *hash) -{ - if (addr[0] & 0x01) { - int idx, bit; - u32 crc; - - crc = ether_crc_le(ETH_ALEN, addr); - - idx = crc >> 30; - bit = (crc >> 26) & 15; - - hash[idx] |= 1 << bit; - } -} - /* * Set or clear promiscuous/multicast mode filter for this adapter. */ @@ -362,24 +380,9 @@ static void am79c961_setmulticastlist (struct net_device *dev) { struct dev_priv *priv = netdev_priv(dev); unsigned long flags; - unsigned short multi_hash[4], mode; + u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash); int i, stopped; - mode = MODE_PORT_10BT; - - if (dev->flags & IFF_PROMISC) { - mode |= MODE_PROMISC; - } else if (dev->flags & IFF_ALLMULTI) { - memset(multi_hash, 0xff, sizeof(multi_hash)); - } else { - struct netdev_hw_addr *ha; - - memset(multi_hash, 0x00, sizeof(multi_hash)); - - netdev_for_each_mc_addr(ha, dev) - am79c961_mc_hash(ha->addr, multi_hash); - } - spin_lock_irqsave(&priv->chip_lock, flags); stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP; From f777737885a69d37132c956f1e8deab676693157 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Fri, 10 Jun 2011 00:52:35 +0000 Subject: [PATCH 315/595] NET: am79c961: fix assembler warnings Fix: /tmp/ccvoZ6h8.s: Assembler messages: /tmp/ccvoZ6h8.s:284: Warning: register range not in ascending order /tmp/ccvoZ6h8.s:881: Warning: register range not in ascending order /tmp/ccvoZ6h8.s:1087: Warning: register range not in ascending order by ensuring that we have temporary variables placed into specific registers. Reorder the code a bit to allow the resulting assembly to be slightly more optimal. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/arm/am79c961a.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 79d88a0b00a3..7b3e23f38913 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -91,40 +91,41 @@ static inline unsigned short read_ireg(u_long base_addr, u_int reg) #define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1)) #define am_readword(dev,off) __raw_readw(ISAMEM_BASE + ((off) << 1)) -static inline void +static void am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length) { offset = ISAMEM_BASE + (offset << 1); length = (length + 1) & ~1; if ((int)buf & 2) { - __asm__ __volatile__("str%?h %2, [%0], #4" + asm volatile("str%?h %2, [%0], #4" : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8))); buf += 2; length -= 2; } while (length > 8) { - unsigned int tmp, tmp2; - __asm__ __volatile__( - "ldm%?ia %1!, {%2, %3}\n\t" + register unsigned int tmp asm("r2"), tmp2 asm("r3"); + asm volatile( + "ldm%?ia %0!, {%1, %2}" + : "+r" (buf), "=&r" (tmp), "=&r" (tmp2)); + length -= 8; + asm volatile( + "str%?h %1, [%0], #4\n\t" + "mov%? %1, %1, lsr #16\n\t" + "str%?h %1, [%0], #4\n\t" "str%?h %2, [%0], #4\n\t" "mov%? %2, %2, lsr #16\n\t" - "str%?h %2, [%0], #4\n\t" - "str%?h %3, [%0], #4\n\t" - "mov%? %3, %3, lsr #16\n\t" - "str%?h %3, [%0], #4" - : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2) - : "0" (offset), "1" (buf)); - length -= 8; + "str%?h %2, [%0], #4" + : "+r" (offset), "=&r" (tmp), "=&r" (tmp2)); } while (length > 0) { - __asm__ __volatile__("str%?h %2, [%0], #4" + asm volatile("str%?h %2, [%0], #4" : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8))); buf += 2; length -= 2; } } -static inline void +static void am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length) { offset = ISAMEM_BASE + (offset << 1); @@ -140,12 +141,12 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned length -= 2; } while (length > 8) { - unsigned int tmp, tmp2, tmp3; + register unsigned int tmp asm("r2"), tmp2 asm("r3"), tmp3; asm volatile( "ldr%?h %2, [%0], #4\n\t" + "ldr%?h %4, [%0], #4\n\t" "ldr%?h %3, [%0], #4\n\t" - "orr%? %2, %2, %3, lsl #16\n\t" - "ldr%?h %3, [%0], #4\n\t" + "orr%? %2, %2, %4, lsl #16\n\t" "ldr%?h %4, [%0], #4\n\t" "orr%? %3, %3, %4, lsl #16\n\t" "stm%?ia %1!, {%2, %3}" From 06866bf5c5ad8989119a145fdb54a9fbcafa702d Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 10 Jun 2011 04:55:16 +0000 Subject: [PATCH 316/595] dl2k: EEPROM CRC calculation wrong endianess on bigendian machine Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- drivers/net/dl2k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index c445457b66d5..23179dbcedd2 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -346,7 +346,7 @@ parse_eeprom (struct net_device *dev) if (np->pdev->vendor == PCI_VENDOR_ID_DLINK) { /* D-Link Only */ /* Check CRC */ crc = ~ether_crc_le (256 - 4, sromdata); - if (psrom->crc != crc) { + if (psrom->crc != cpu_to_le32(crc)) { printk (KERN_ERR "%s: EEPROM data CRC error.\n", dev->name); return -1; From 0b5c9db1b11d3175bb42b80663a9f072f801edf5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 10 Jun 2011 06:56:58 +0000 Subject: [PATCH 317/595] vlan: Fix the ingress VLAN_FLAG_REORDER_HDR check Testing of VLAN_FLAG_REORDER_HDR does not belong in vlan_untag but rather in vlan_do_receive. Otherwise the vlan header will not be properly put on the packet in the case of vlan header accelleration. As we remove the check from vlan_check_reorder_header rename it vlan_reorder_header to keep the naming clean. Fix up the skb->pkt_type early so we don't look at the packet after adding the vlan tag, which guarantees we don't goof and look at the wrong field. Use a simple if statement instead of a complicated switch statement to decided that we need to increment rx_stats for a multicast packet. Hopefully at somepoint we will just declare the case where VLAN_FLAG_REORDER_HDR is cleared as unsupported and remove the code. Until then this keeps it working correctly. Signed-off-by: Eric W. Biederman Signed-off-by: Jiri Pirko Acked-by: Changli Gao Signed-off-by: David S. Miller --- include/linux/if_vlan.h | 25 ++++++++++++++--- include/linux/skbuff.h | 5 ++++ net/8021q/vlan_core.c | 60 ++++++++++++++++++++++------------------- net/core/dev.c | 2 +- 4 files changed, 61 insertions(+), 31 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index dc01681fbb42..affa27380b72 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -225,7 +225,7 @@ static inline int vlan_hwaccel_receive_skb(struct sk_buff *skb, } /** - * __vlan_put_tag - regular VLAN tag inserting + * vlan_insert_tag - regular VLAN tag inserting * @skb: skbuff to tag * @vlan_tci: VLAN TCI to insert * @@ -234,8 +234,10 @@ static inline int vlan_hwaccel_receive_skb(struct sk_buff *skb, * * Following the skb_unshare() example, in case of error, the calling function * doesn't have to worry about freeing the original skb. + * + * Does not change skb->protocol so this function can be used during receive. */ -static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci) +static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb, u16 vlan_tci) { struct vlan_ethhdr *veth; @@ -255,8 +257,25 @@ static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci) /* now, the TCI */ veth->h_vlan_TCI = htons(vlan_tci); - skb->protocol = htons(ETH_P_8021Q); + return skb; +} +/** + * __vlan_put_tag - regular VLAN tag inserting + * @skb: skbuff to tag + * @vlan_tci: VLAN TCI to insert + * + * Inserts the VLAN tag into @skb as part of the payload + * Returns a VLAN tagged skb. If a new skb is created, @skb is freed. + * + * Following the skb_unshare() example, in case of error, the calling function + * doesn't have to worry about freeing the original skb. + */ +static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci) +{ + skb = vlan_insert_tag(skb, vlan_tci); + if (skb) + skb->protocol = htons(ETH_P_8021Q); return skb; } diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index e8b78ce14474..c0a4f3ab0cc0 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1256,6 +1256,11 @@ static inline void skb_reserve(struct sk_buff *skb, int len) skb->tail += len; } +static inline void skb_reset_mac_len(struct sk_buff *skb) +{ + skb->mac_len = skb->network_header - skb->mac_header; +} + #ifdef NET_SKBUFF_DATA_USES_OFFSET static inline unsigned char *skb_transport_header(const struct sk_buff *skb) { diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 41495dc2a4c9..fcc684678af6 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -23,6 +23,31 @@ bool vlan_do_receive(struct sk_buff **skbp) return false; skb->dev = vlan_dev; + if (skb->pkt_type == PACKET_OTHERHOST) { + /* Our lower layer thinks this is not local, let's make sure. + * This allows the VLAN to have a different MAC than the + * underlying device, and still route correctly. */ + if (!compare_ether_addr(eth_hdr(skb)->h_dest, + vlan_dev->dev_addr)) + skb->pkt_type = PACKET_HOST; + } + + if (!(vlan_dev_info(vlan_dev)->flags & VLAN_FLAG_REORDER_HDR)) { + unsigned int offset = skb->data - skb_mac_header(skb); + + /* + * vlan_insert_tag expect skb->data pointing to mac header. + * So change skb->data before calling it and change back to + * original position later + */ + skb_push(skb, offset); + skb = *skbp = vlan_insert_tag(skb, skb->vlan_tci); + if (!skb) + return false; + skb_pull(skb, offset + VLAN_HLEN); + skb_reset_mac_len(skb); + } + skb->priority = vlan_get_ingress_priority(vlan_dev, skb->vlan_tci); skb->vlan_tci = 0; @@ -31,22 +56,8 @@ bool vlan_do_receive(struct sk_buff **skbp) u64_stats_update_begin(&rx_stats->syncp); rx_stats->rx_packets++; rx_stats->rx_bytes += skb->len; - - switch (skb->pkt_type) { - case PACKET_BROADCAST: - break; - case PACKET_MULTICAST: + if (skb->pkt_type == PACKET_MULTICAST) rx_stats->rx_multicast++; - break; - case PACKET_OTHERHOST: - /* Our lower layer thinks this is not local, let's make sure. - * This allows the VLAN to have a different MAC than the - * underlying device, and still route correctly. */ - if (!compare_ether_addr(eth_hdr(skb)->h_dest, - vlan_dev->dev_addr)) - skb->pkt_type = PACKET_HOST; - break; - } u64_stats_update_end(&rx_stats->syncp); return true; @@ -89,18 +100,13 @@ gro_result_t vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, } EXPORT_SYMBOL(vlan_gro_frags); -static struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) +static struct sk_buff *vlan_reorder_header(struct sk_buff *skb) { - if (vlan_dev_info(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) { - if (skb_cow(skb, skb_headroom(skb)) < 0) - skb = NULL; - if (skb) { - /* Lifted from Gleb's VLAN code... */ - memmove(skb->data - ETH_HLEN, - skb->data - VLAN_ETH_HLEN, 12); - skb->mac_header += VLAN_HLEN; - } - } + if (skb_cow(skb, skb_headroom(skb)) < 0) + 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; } @@ -161,7 +167,7 @@ struct sk_buff *vlan_untag(struct sk_buff *skb) skb_pull_rcsum(skb, VLAN_HLEN); vlan_set_encap_proto(skb, vhdr); - skb = vlan_check_reorder_header(skb); + skb = vlan_reorder_header(skb); if (unlikely(!skb)) goto err_free; diff --git a/net/core/dev.c b/net/core/dev.c index a54c9f87ddbb..9c58c1ec41a9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3114,7 +3114,7 @@ static int __netif_receive_skb(struct sk_buff *skb) skb_reset_network_header(skb); skb_reset_transport_header(skb); - skb->mac_len = skb->network_header - skb->mac_header; + skb_reset_mac_len(skb); pt_prev = NULL; From fa70cf472c0bc3a0d7e613a418cfc1117b796c6c Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 11 Jun 2011 08:39:54 +0000 Subject: [PATCH 318/595] ep93xx: set DMA masks for the ep93xx_eth Since the driver uses the DMA API, we should pass it valid DMA masks. Signed-off-by: Mika Westerberg Acked-by: Russell King Acked-by: H Hartley Sweeten Tested-by: Petr Stetiar Signed-off-by: David S. Miller --- arch/arm/mach-ep93xx/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 82079545adc4..1d4b65fd673e 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -402,11 +402,15 @@ static struct resource ep93xx_eth_resource[] = { } }; +static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32); + static struct platform_device ep93xx_eth_device = { .name = "ep93xx-eth", .id = -1, .dev = { - .platform_data = &ep93xx_eth_data, + .platform_data = &ep93xx_eth_data, + .coherent_dma_mask = DMA_BIT_MASK(32), + .dma_mask = &ep93xx_eth_dma_mask, }, .num_resources = ARRAY_SIZE(ep93xx_eth_resource), .resource = ep93xx_eth_resource, From fc9b4910b00039da054f221e2821be0519261101 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 11 Jun 2011 08:39:55 +0000 Subject: [PATCH 319/595] net: ep93xx_eth: pass struct device to DMA API functions We shouldn't use NULL for any DMA API functions, unless we are dealing with ISA or EISA device. So pass correct struct dev pointer to these functions. Signed-off-by: Mika Westerberg Signed-off-by: David S. Miller --- drivers/net/arm/ep93xx_eth.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 5a77001b6d10..f65dfb6e5705 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -284,7 +284,7 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget) skb = dev_alloc_skb(length + 2); if (likely(skb != NULL)) { skb_reserve(skb, 2); - dma_sync_single_for_cpu(NULL, ep->descs->rdesc[entry].buf_addr, + dma_sync_single_for_cpu(dev->dev.parent, ep->descs->rdesc[entry].buf_addr, length, DMA_FROM_DEVICE); skb_copy_to_linear_data(skb, ep->rx_buf[entry], length); skb_put(skb, length); @@ -362,7 +362,7 @@ static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) ep->descs->tdesc[entry].tdesc1 = TDESC1_EOF | (entry << 16) | (skb->len & 0xfff); skb_copy_and_csum_dev(skb, ep->tx_buf[entry]); - dma_sync_single_for_cpu(NULL, ep->descs->tdesc[entry].buf_addr, + dma_sync_single_for_cpu(dev->dev.parent, ep->descs->tdesc[entry].buf_addr, skb->len, DMA_TO_DEVICE); dev_kfree_skb(skb); @@ -457,6 +457,7 @@ static irqreturn_t ep93xx_irq(int irq, void *dev_id) static void ep93xx_free_buffers(struct ep93xx_priv *ep) { + struct device *dev = ep->dev->dev.parent; int i; for (i = 0; i < RX_QUEUE_ENTRIES; i += 2) { @@ -464,7 +465,7 @@ static void ep93xx_free_buffers(struct ep93xx_priv *ep) d = ep->descs->rdesc[i].buf_addr; if (d) - dma_unmap_single(NULL, d, PAGE_SIZE, DMA_FROM_DEVICE); + dma_unmap_single(dev, d, PAGE_SIZE, DMA_FROM_DEVICE); if (ep->rx_buf[i] != NULL) free_page((unsigned long)ep->rx_buf[i]); @@ -475,13 +476,13 @@ static void ep93xx_free_buffers(struct ep93xx_priv *ep) d = ep->descs->tdesc[i].buf_addr; if (d) - dma_unmap_single(NULL, d, PAGE_SIZE, DMA_TO_DEVICE); + dma_unmap_single(dev, d, PAGE_SIZE, DMA_TO_DEVICE); if (ep->tx_buf[i] != NULL) free_page((unsigned long)ep->tx_buf[i]); } - dma_free_coherent(NULL, sizeof(struct ep93xx_descs), ep->descs, + dma_free_coherent(dev, sizeof(struct ep93xx_descs), ep->descs, ep->descs_dma_addr); } @@ -491,9 +492,10 @@ static void ep93xx_free_buffers(struct ep93xx_priv *ep) */ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep) { + struct device *dev = ep->dev->dev.parent; int i; - ep->descs = dma_alloc_coherent(NULL, sizeof(struct ep93xx_descs), + ep->descs = dma_alloc_coherent(dev, sizeof(struct ep93xx_descs), &ep->descs_dma_addr, GFP_KERNEL | GFP_DMA); if (ep->descs == NULL) return 1; @@ -506,8 +508,8 @@ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep) if (page == NULL) goto err; - d = dma_map_single(NULL, page, PAGE_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(NULL, d)) { + d = dma_map_single(dev, page, PAGE_SIZE, DMA_FROM_DEVICE); + if (dma_mapping_error(dev, d)) { free_page((unsigned long)page); goto err; } @@ -529,8 +531,8 @@ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep) if (page == NULL) goto err; - d = dma_map_single(NULL, page, PAGE_SIZE, DMA_TO_DEVICE); - if (dma_mapping_error(NULL, d)) { + d = dma_map_single(dev, page, PAGE_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(dev, d)) { free_page((unsigned long)page); goto err; } @@ -829,6 +831,7 @@ static int ep93xx_eth_probe(struct platform_device *pdev) } ep = netdev_priv(dev); ep->dev = dev; + SET_NETDEV_DEV(dev, &pdev->dev); netif_napi_add(dev, &ep->napi, ep93xx_poll, 64); platform_set_drvdata(pdev, dev); From 3247a1fcee49b571b40c4bd723439ce5c64f56ad Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 11 Jun 2011 08:39:56 +0000 Subject: [PATCH 320/595] net: ep93xx_eth: allocate buffers using kmalloc() We can use simply kmalloc() to allocate the buffers. This also simplifies the code and allows us to perform DMA sync operations more easily. Memory is allocated with only GFP_KERNEL since there are no DMA allocation restrictions on this platform. Signed-off-by: Mika Westerberg Acked-by: Russell King Acked-by: H Hartley Sweeten Tested-by: Petr Stetiar Signed-off-by: David S. Miller --- drivers/net/arm/ep93xx_eth.c | 51 ++++++++++++++---------------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index f65dfb6e5705..97bf6b10ce61 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -460,36 +460,32 @@ static void ep93xx_free_buffers(struct ep93xx_priv *ep) struct device *dev = ep->dev->dev.parent; int i; - for (i = 0; i < RX_QUEUE_ENTRIES; i += 2) { + for (i = 0; i < RX_QUEUE_ENTRIES; i++) { dma_addr_t d; d = ep->descs->rdesc[i].buf_addr; if (d) - dma_unmap_single(dev, d, PAGE_SIZE, DMA_FROM_DEVICE); + dma_unmap_single(dev, d, PKT_BUF_SIZE, DMA_FROM_DEVICE); if (ep->rx_buf[i] != NULL) - free_page((unsigned long)ep->rx_buf[i]); + kfree(ep->rx_buf[i]); } - for (i = 0; i < TX_QUEUE_ENTRIES; i += 2) { + for (i = 0; i < TX_QUEUE_ENTRIES; i++) { dma_addr_t d; d = ep->descs->tdesc[i].buf_addr; if (d) - dma_unmap_single(dev, d, PAGE_SIZE, DMA_TO_DEVICE); + dma_unmap_single(dev, d, PKT_BUF_SIZE, DMA_TO_DEVICE); if (ep->tx_buf[i] != NULL) - free_page((unsigned long)ep->tx_buf[i]); + kfree(ep->tx_buf[i]); } dma_free_coherent(dev, sizeof(struct ep93xx_descs), ep->descs, ep->descs_dma_addr); } -/* - * The hardware enforces a sub-2K maximum packet size, so we put - * two buffers on every hardware page. - */ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep) { struct device *dev = ep->dev->dev.parent; @@ -500,48 +496,41 @@ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep) if (ep->descs == NULL) return 1; - for (i = 0; i < RX_QUEUE_ENTRIES; i += 2) { - void *page; + for (i = 0; i < RX_QUEUE_ENTRIES; i++) { + void *buf; dma_addr_t d; - page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); - if (page == NULL) + buf = kmalloc(PKT_BUF_SIZE, GFP_KERNEL); + if (buf == NULL) goto err; - d = dma_map_single(dev, page, PAGE_SIZE, DMA_FROM_DEVICE); + d = dma_map_single(dev, buf, PKT_BUF_SIZE, DMA_FROM_DEVICE); if (dma_mapping_error(dev, d)) { - free_page((unsigned long)page); + kfree(buf); goto err; } - ep->rx_buf[i] = page; + ep->rx_buf[i] = buf; ep->descs->rdesc[i].buf_addr = d; ep->descs->rdesc[i].rdesc1 = (i << 16) | PKT_BUF_SIZE; - - ep->rx_buf[i + 1] = page + PKT_BUF_SIZE; - ep->descs->rdesc[i + 1].buf_addr = d + PKT_BUF_SIZE; - ep->descs->rdesc[i + 1].rdesc1 = ((i + 1) << 16) | PKT_BUF_SIZE; } - for (i = 0; i < TX_QUEUE_ENTRIES; i += 2) { - void *page; + for (i = 0; i < TX_QUEUE_ENTRIES; i++) { + void *buf; dma_addr_t d; - page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); - if (page == NULL) + buf = kmalloc(PKT_BUF_SIZE, GFP_KERNEL); + if (buf == NULL) goto err; - d = dma_map_single(dev, page, PAGE_SIZE, DMA_TO_DEVICE); + d = dma_map_single(dev, buf, PKT_BUF_SIZE, DMA_TO_DEVICE); if (dma_mapping_error(dev, d)) { - free_page((unsigned long)page); + kfree(buf); goto err; } - ep->tx_buf[i] = page; + ep->tx_buf[i] = buf; ep->descs->tdesc[i].buf_addr = d; - - ep->tx_buf[i + 1] = page + PKT_BUF_SIZE; - ep->descs->tdesc[i + 1].buf_addr = d + PKT_BUF_SIZE; } return 0; From 1f758a4341ac83289a549e6ba2d29a08cf639717 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 11 Jun 2011 08:39:57 +0000 Subject: [PATCH 321/595] net: ep93xx_eth: drop GFP_DMA from call to dma_alloc_coherent() Commit a197b59ae6e8 (mm: fail GFP_DMA allocations when ZONE_DMA is not configured) made page allocator to return NULL if GFP_DMA is set but CONFIG_ZONE_DMA is disabled. This causes ep93xx_eth to fail: WARNING: at mm/page_alloc.c:2251 __alloc_pages_nodemask+0x11c/0x638() Modules linked in: [] (unwind_backtrace+0x0/0xf4) from [] (warn_slowpath_common+0x48/0x60) [] (warn_slowpath_common+0x48/0x60) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null+0x1c/0x24) from [] (__alloc_pages_nodemask+0x11c/0x638) [] (__alloc_pages_nodemask+0x11c/0x638) from [] (__dma_alloc+0x8c/0x3ec) [] (__dma_alloc+0x8c/0x3ec) from [] (dma_alloc_coherent+0x54/0x60) [] (dma_alloc_coherent+0x54/0x60) from [] (ep93xx_open+0x20/0x864) [] (ep93xx_open+0x20/0x864) from [] (__dev_open+0xb8/0x108) [] (__dev_open+0xb8/0x108) from [] (__dev_change_flags+0x70/0x128) [] (__dev_change_flags+0x70/0x128) from [] (dev_change_flags+0x10/0x48) [] (dev_change_flags+0x10/0x48) from [] (ip_auto_config+0x190/0xf68) [] (ip_auto_config+0x190/0xf68) from [] (do_one_initcall+0x34/0x18c) [] (do_one_initcall+0x34/0x18c) from [] (kernel_init+0x94/0x134) [] (kernel_init+0x94/0x134) from [] (kernel_thread_exit+0x0/0x8) Since there is no restrictions for DMA on ep93xx, we can fix this by just removing the GFP_DMA flag from the call. Signed-off-by: Mika Westerberg Acked-by: Russell King Acked-by: H Hartley Sweeten Tested-by: Petr Stetiar Signed-off-by: David S. Miller --- drivers/net/arm/ep93xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 97bf6b10ce61..bef38116abaf 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -492,7 +492,7 @@ static int ep93xx_alloc_buffers(struct ep93xx_priv *ep) int i; ep->descs = dma_alloc_coherent(dev, sizeof(struct ep93xx_descs), - &ep->descs_dma_addr, GFP_KERNEL | GFP_DMA); + &ep->descs_dma_addr, GFP_KERNEL); if (ep->descs == NULL) return 1; From f1c089e3192f1afdfa76226dc38ef81b08ac810d Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 11 Jun 2011 08:39:58 +0000 Subject: [PATCH 322/595] net: ep93xx_eth: fix DMA API violations Russell King said: > > So, to summarize what its doing: > > 1. It allocates buffers for rx and tx. > 2. It maps them with dma_map_single(). > This transfers ownership of the buffer to the DMA device. > 3. In ep93xx_xmit, > 3a. It copies the data into the buffer with skb_copy_and_csum_dev() > This violates the DMA buffer ownership rules - the CPU should > not be writing to this buffer while it is (in principle) owned > by the DMA device. > 3b. It then calls dma_sync_single_for_cpu() for the buffer. > This transfers ownership of the buffer to the CPU, which surely > is the wrong direction. > 4. In ep93xx_rx, > 4a. It calls dma_sync_single_for_cpu() for the buffer. > This at least transfers the DMA buffer ownership to the CPU > before the CPU reads the buffer > 4b. It then uses skb_copy_to_linear_data() to copy the data out. > At no point does it transfer ownership back to the DMA device. > 5. When the driver is removed, it dma_unmap_single()'s the buffer. > This transfers ownership of the buffer to the CPU. > 6. It frees the buffer. > > While it may work on ep93xx, it's not respecting the DMA API rules, > and with DMA debugging enabled it will probably encounter quite a few > warnings. This patch fixes these violations. Signed-off-by: Mika Westerberg Acked-by: Russell King Acked-by: H Hartley Sweeten Tested-by: Petr Stetiar Signed-off-by: David S. Miller --- drivers/net/arm/ep93xx_eth.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index bef38116abaf..0b46b8ea0e80 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -283,10 +283,14 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget) skb = dev_alloc_skb(length + 2); if (likely(skb != NULL)) { + struct ep93xx_rdesc *rxd = &ep->descs->rdesc[entry]; skb_reserve(skb, 2); - dma_sync_single_for_cpu(dev->dev.parent, ep->descs->rdesc[entry].buf_addr, + dma_sync_single_for_cpu(dev->dev.parent, rxd->buf_addr, length, DMA_FROM_DEVICE); skb_copy_to_linear_data(skb, ep->rx_buf[entry], length); + dma_sync_single_for_device(dev->dev.parent, + rxd->buf_addr, length, + DMA_FROM_DEVICE); skb_put(skb, length); skb->protocol = eth_type_trans(skb, dev); @@ -348,6 +352,7 @@ static int ep93xx_poll(struct napi_struct *napi, int budget) static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) { struct ep93xx_priv *ep = netdev_priv(dev); + struct ep93xx_tdesc *txd; int entry; if (unlikely(skb->len > MAX_PKT_SIZE)) { @@ -359,11 +364,14 @@ static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) entry = ep->tx_pointer; ep->tx_pointer = (ep->tx_pointer + 1) & (TX_QUEUE_ENTRIES - 1); - ep->descs->tdesc[entry].tdesc1 = - TDESC1_EOF | (entry << 16) | (skb->len & 0xfff); + txd = &ep->descs->tdesc[entry]; + + txd->tdesc1 = TDESC1_EOF | (entry << 16) | (skb->len & 0xfff); + dma_sync_single_for_cpu(dev->dev.parent, txd->buf_addr, skb->len, + DMA_TO_DEVICE); skb_copy_and_csum_dev(skb, ep->tx_buf[entry]); - dma_sync_single_for_cpu(dev->dev.parent, ep->descs->tdesc[entry].buf_addr, - skb->len, DMA_TO_DEVICE); + dma_sync_single_for_device(dev->dev.parent, txd->buf_addr, skb->len, + DMA_TO_DEVICE); dev_kfree_skb(skb); spin_lock_irq(&ep->tx_pending_lock); From 83fe32de63e60af34fa8dae83716cb13b8677abd Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 11 Jun 2011 18:55:22 -0700 Subject: [PATCH 323/595] netpoll: call dev_put() on error in netpoll_setup() There is a dev_put(ndev) missing on an error path. This was introduced in 0c1ad04aecb "netpoll: prevent netpoll setup on slave devices". Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- net/core/netpoll.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 42ea4b0e59f1..18d9cbda3a39 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -795,7 +795,8 @@ int netpoll_setup(struct netpoll *np) if (ndev->master) { printk(KERN_ERR "%s: %s is a slave device, aborting.\n", np->name, np->dev_name); - return -EBUSY; + err = -EBUSY; + goto put; } if (!netif_running(ndev)) { From 84860c725364372a331589a600ce6a00437a14f8 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sat, 11 Jun 2011 06:36:42 +0000 Subject: [PATCH 324/595] ISDN, hfcsusb: Don't leak in hfcsusb_ph_info() We leak the memory allocated to 'phi' when the variable goes out of scope in hfcsusb_ph_info(). Signed-off-by: Jesper Juhl Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/hfcsusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index 3ccbff13eaf2..71a8eb6ef71e 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c @@ -283,6 +283,7 @@ hfcsusb_ph_info(struct hfcsusb *hw) _queue_data(&dch->dev.D, MPH_INFORMATION_IND, MISDN_ID_ANY, sizeof(struct ph_info_dch) + dch->dev.nrbchan * sizeof(struct ph_info_ch), phi, GFP_ATOMIC); + kfree(phi); } /* From c0da00145f9a32ef33b14508e6fd90fc130afbdc Mon Sep 17 00:00:00 2001 From: Adrian Knoth Date: Sun, 12 Jun 2011 17:26:17 +0200 Subject: [PATCH 325/595] ALSA: hdspm - Fix locking in snd_hdspm_midi_input_read For the MIDI part, we need to acquire (and release) the hmidi->lock, access to the global hdspm structure is serialized through hmidi->hdspm->lock instead. Signed-off-by: Adrian Knoth Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdspm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 949691a876d3..32d80af012cc 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1639,12 +1639,14 @@ static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi) } } hmidi->pending = 0; + spin_unlock_irqrestore(&hmidi->lock, flags); + spin_lock_irqsave(&hmidi->hdspm->lock, flags); hmidi->hdspm->control_register |= hmidi->ie; hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register); + spin_unlock_irqrestore(&hmidi->hdspm->lock, flags); - spin_unlock_irqrestore (&hmidi->lock, flags); return snd_hdspm_midi_output_write (hmidi); } From fedf1535ab5ee02acbbc235c2272d84bb9334758 Mon Sep 17 00:00:00 2001 From: Adrian Knoth Date: Sun, 12 Jun 2011 17:26:18 +0200 Subject: [PATCH 326/595] ALSA: hdspm - Fix jumping external wordclock frequency in AutoSync mode When using Word Clock on RME MADI cards, AutoSync mode was alternating betweeen MADI and WC due to a typo: AutoSync is indicated in the second status register (status2), not the first one (status). While the proc output was always correct, the reported WC frequency to ALSA was unstable as mentioned in http://mailman.alsa-project.org/pipermail/alsa-devel/2008-March/006723.html Signed-off-by: Adrian Knoth Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdspm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 32d80af012cc..d03ef94d570e 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1143,7 +1143,7 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) /* if wordclock has synced freq and wordclock is valid */ if ((status2 & HDSPM_wcLock) != 0 && - (status & HDSPM_SelSyncRef0) == 0) { + (status2 & HDSPM_SelSyncRef0) == 0) { rate_bits = status2 & HDSPM_wcFreqMask; From efef054e8c4bc4fd48a0b4deb5491116d9f557c7 Mon Sep 17 00:00:00 2001 From: Adrian Knoth Date: Sun, 12 Jun 2011 17:26:19 +0200 Subject: [PATCH 327/595] ALSA: hdspm - Add firmware revision ID for RME MADI PCI version The PCI version of the RME HDSP MADI card uses 0xcf as revision ID. Just add this to the list of supported cards. Signed-off-by: Adrian Knoth Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdspm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index d03ef94d570e..3f08afc0f0d3 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -521,6 +521,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) /* revisions >= 230 indicate AES32 card */ +#define HDSPM_MADI_OLD_REV 207 #define HDSPM_MADI_REV 210 #define HDSPM_RAYDAT_REV 211 #define HDSPM_AIO_REV 212 @@ -6379,6 +6380,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, switch (hdspm->firmware_rev) { case HDSPM_MADI_REV: + case HDSPM_MADI_OLD_REV: hdspm->io_type = MADI; hdspm->card_name = "RME MADI"; hdspm->midiPorts = 3; From ac5d4b404e78bd7eb67fc70c2acb437a25497e98 Mon Sep 17 00:00:00 2001 From: Florian Zeitz Date: Sun, 12 Jun 2011 01:15:42 +0200 Subject: [PATCH 328/595] ALSA: emu10k1: Add details for E-mu 0404 PCIe version This patch adds the necessary details to support the PCIe version of E-MU's 0404 card. From comparing the PCBs it seems the PCIe version just added a PCIe chipset and left all other components pretty much in place. For anyone intrigued to take a look at the PCB there are pictures I took at . Signed-off-by: Florian Zeitz Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emu10k1_main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 5e619a84da06..15f0161ce4a2 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1440,6 +1440,14 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0102_chip = 1, .spk71 = 1, .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ + /* EMU0404 PCIe */ + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40051102, + .driver = "Audigy2", .name = "E-mu 0404 PCIe [MAEM8984]", + .id = "EMU0404", + .emu10k2_chip = 1, + .ca0108_chip = 1, + .spk71 = 1, + .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */ /* Note that all E-mu cards require kernel 2.6 or newer. */ {.vendor = 0x1102, .device = 0x0008, .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]", From 89b882a25e703b72c3e84c582357e3e864d8ccca Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 1 Jun 2011 10:59:10 -0700 Subject: [PATCH 329/595] MAINTAINERS: Update CPU FREQUENCY patterns Commit bb0a56ecc4ba ("[CPUFREQ] Move x86 drivers to drivers/cpufreq/") moved the files, remove the old pattern. Signed-off-by: Joe Perches Signed-off-by: Dave Jones --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 29801f760b6f..55d7b8062b30 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1889,7 +1889,6 @@ L: cpufreq@vger.kernel.org W: http://www.codemonkey.org.uk/projects/cpufreq/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git S: Maintained -F: arch/x86/kernel/cpu/cpufreq/ F: drivers/cpufreq/ F: include/linux/cpufreq.h From 13f067537f34456443f61c950cd6dc37d1d5f3ee Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 12 Jun 2011 16:35:28 -0400 Subject: [PATCH 330/595] [CPUFREQ] Remove cpufreq_stats sysfs entries on module unload. cpufreq_stats leaves behind its sysfs entries, which causes a panic when something stumbled across them. (Discovered by unloading cpufreq_stats while powertop was loaded). Signed-off-by: Dave Jones Cc: stable@kernel.org --- drivers/cpufreq/cpufreq_stats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index b60a4c263686..853f92d23ddb 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -387,6 +387,7 @@ static void __exit cpufreq_stats_exit(void) unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier); for_each_online_cpu(cpu) { cpufreq_stats_free_table(cpu); + cpufreq_stats_free_sysfs(cpu); } } From ff78fca2a03c08436535d3f7152a30752d8131d1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 Jun 2011 09:42:17 -0400 Subject: [PATCH 331/595] fix leak in proc_set_super() set_anon_super() can fail... Signed-off-by: Al Viro --- fs/proc/root.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/proc/root.c b/fs/proc/root.c index a9000e9cfee5..d6c3b416529b 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -28,11 +28,12 @@ static int proc_test_super(struct super_block *sb, void *data) static int proc_set_super(struct super_block *sb, void *data) { - struct pid_namespace *ns; - - ns = (struct pid_namespace *)data; - sb->s_fs_info = get_pid_ns(ns); - return set_anon_super(sb, NULL); + int err = set_anon_super(sb, NULL); + if (!err) { + struct pid_namespace *ns = (struct pid_namespace *)data; + sb->s_fs_info = get_pid_ns(ns); + } + return err; } static struct dentry *proc_mount(struct file_system_type *fs_type, From b1c27ab3f93daede979f804afc38b189c2f17c60 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 Jun 2011 10:07:03 -0400 Subject: [PATCH 332/595] ubifs: split allocation of ubifs_info into a separate function preparation to ubifs sget() race fixes Signed-off-by: Al Viro --- fs/ubifs/super.c | 87 ++++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index b5aeb5a8ebed..ddc3b02e8cf0 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1971,6 +1971,53 @@ static struct ubi_volume_desc *open_ubi(const char *name, int mode) return ERR_PTR(-EINVAL); } +static struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi) +{ + struct ubifs_info *c; + + c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL); + if (c) { + spin_lock_init(&c->cnt_lock); + spin_lock_init(&c->cs_lock); + spin_lock_init(&c->buds_lock); + spin_lock_init(&c->space_lock); + spin_lock_init(&c->orphan_lock); + init_rwsem(&c->commit_sem); + mutex_init(&c->lp_mutex); + mutex_init(&c->tnc_mutex); + mutex_init(&c->log_mutex); + mutex_init(&c->mst_mutex); + mutex_init(&c->umount_mutex); + mutex_init(&c->bu_mutex); + mutex_init(&c->write_reserve_mutex); + init_waitqueue_head(&c->cmt_wq); + c->buds = RB_ROOT; + c->old_idx = RB_ROOT; + c->size_tree = RB_ROOT; + c->orph_tree = RB_ROOT; + INIT_LIST_HEAD(&c->infos_list); + INIT_LIST_HEAD(&c->idx_gc); + INIT_LIST_HEAD(&c->replay_list); + INIT_LIST_HEAD(&c->replay_buds); + INIT_LIST_HEAD(&c->uncat_list); + INIT_LIST_HEAD(&c->empty_list); + INIT_LIST_HEAD(&c->freeable_list); + INIT_LIST_HEAD(&c->frdi_idx_list); + INIT_LIST_HEAD(&c->unclean_leb_list); + INIT_LIST_HEAD(&c->old_buds); + INIT_LIST_HEAD(&c->orph_list); + INIT_LIST_HEAD(&c->orph_new); + c->no_chk_data_crc = 1; + + c->highest_inum = UBIFS_FIRST_INO; + c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; + + ubi_get_volume_info(ubi, &c->vi); + ubi_get_device_info(c->vi.ubi_num, &c->di); + } + return c; +} + static int ubifs_fill_super(struct super_block *sb, void *data, int silent) { struct ubi_volume_desc *ubi = sb->s_fs_info; @@ -1978,49 +2025,11 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) struct inode *root; int err; - c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL); + c = alloc_ubifs_info(ubi); if (!c) return -ENOMEM; - spin_lock_init(&c->cnt_lock); - spin_lock_init(&c->cs_lock); - spin_lock_init(&c->buds_lock); - spin_lock_init(&c->space_lock); - spin_lock_init(&c->orphan_lock); - init_rwsem(&c->commit_sem); - mutex_init(&c->lp_mutex); - mutex_init(&c->tnc_mutex); - mutex_init(&c->log_mutex); - mutex_init(&c->mst_mutex); - mutex_init(&c->umount_mutex); - mutex_init(&c->bu_mutex); - mutex_init(&c->write_reserve_mutex); - init_waitqueue_head(&c->cmt_wq); - c->buds = RB_ROOT; - c->old_idx = RB_ROOT; - c->size_tree = RB_ROOT; - c->orph_tree = RB_ROOT; - INIT_LIST_HEAD(&c->infos_list); - INIT_LIST_HEAD(&c->idx_gc); - INIT_LIST_HEAD(&c->replay_list); - INIT_LIST_HEAD(&c->replay_buds); - INIT_LIST_HEAD(&c->uncat_list); - INIT_LIST_HEAD(&c->empty_list); - INIT_LIST_HEAD(&c->freeable_list); - INIT_LIST_HEAD(&c->frdi_idx_list); - INIT_LIST_HEAD(&c->unclean_leb_list); - INIT_LIST_HEAD(&c->old_buds); - INIT_LIST_HEAD(&c->orph_list); - INIT_LIST_HEAD(&c->orph_new); - c->no_chk_data_crc = 1; - c->vfs_sb = sb; - c->highest_inum = UBIFS_FIRST_INO; - c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; - - ubi_get_volume_info(ubi, &c->vi); - ubi_get_device_info(c->vi.ubi_num, &c->di); - /* Re-open the UBI device in read-write mode */ c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE); if (IS_ERR(c->ubi)) { From d251ed271d528afb407cc2ede30923e34cb209a5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 Jun 2011 10:24:33 -0400 Subject: [PATCH 333/595] ubifs: fix sget races * allocate ubifs_info in ->mount(), fill it enough for sb_test() and set ->s_fs_info to it in set() callback passed to sget(). * do *not* free it in ->put_super(); do that in ->kill_sb() after we'd done kill_anon_super(). * don't free it in ubifs_fill_super() either - deactivate_locked_super() done by caller when ubifs_fill_super() returns an error will take care of that sucker. * get rid of kludge with passing ubi to ubifs_fill_super() in ->s_fs_info; we only need it in alloc_ubifs_info(), so ubifs_fill_super() will need only ubifs_info. Which it will find in ->s_fs_info just fine, no need to reassign anything... As the result, sb_test() becomes safe to apply to all superblocks that can be found by sget() (and a kludge with temporary use of ->s_fs_info to store a pointer to very different structure goes away). Signed-off-by: Al Viro --- fs/ubifs/super.c | 54 +++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index ddc3b02e8cf0..8c892c2d5300 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1848,7 +1848,6 @@ static void ubifs_put_super(struct super_block *sb) bdi_destroy(&c->bdi); ubi_close_volume(c->ubi); mutex_unlock(&c->umount_mutex); - kfree(c); } static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) @@ -2020,21 +2019,16 @@ static struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi) static int ubifs_fill_super(struct super_block *sb, void *data, int silent) { - struct ubi_volume_desc *ubi = sb->s_fs_info; - struct ubifs_info *c; + struct ubifs_info *c = sb->s_fs_info; struct inode *root; int err; - c = alloc_ubifs_info(ubi); - if (!c) - return -ENOMEM; - c->vfs_sb = sb; /* Re-open the UBI device in read-write mode */ c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE); if (IS_ERR(c->ubi)) { err = PTR_ERR(c->ubi); - goto out_free; + goto out; } /* @@ -2100,24 +2094,29 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) bdi_destroy(&c->bdi); out_close: ubi_close_volume(c->ubi); -out_free: - kfree(c); +out: return err; } static int sb_test(struct super_block *sb, void *data) { - dev_t *dev = data; + struct ubifs_info *c1 = data; struct ubifs_info *c = sb->s_fs_info; - return c->vi.cdev == *dev; + return c->vi.cdev == c1->vi.cdev; +} + +static int sb_set(struct super_block *sb, void *data) +{ + sb->s_fs_info = data; + return set_anon_super(sb, NULL); } static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, const char *name, void *data) { struct ubi_volume_desc *ubi; - struct ubi_volume_info vi; + struct ubifs_info *c; struct super_block *sb; int err; @@ -2134,19 +2133,24 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, name, (int)PTR_ERR(ubi)); return ERR_CAST(ubi); } - ubi_get_volume_info(ubi, &vi); - dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id); + c = alloc_ubifs_info(ubi); + if (!c) { + err = -ENOMEM; + goto out_close; + } + + dbg_gen("opened ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); - sb = sget(fs_type, &sb_test, &set_anon_super, &vi.cdev); + sb = sget(fs_type, sb_test, sb_set, c); if (IS_ERR(sb)) { err = PTR_ERR(sb); - goto out_close; + kfree(c); } if (sb->s_root) { struct ubifs_info *c1 = sb->s_fs_info; - + kfree(c); /* A new mount point for already mounted UBIFS */ dbg_gen("this ubi volume is already mounted"); if (!!(flags & MS_RDONLY) != c1->ro_mount) { @@ -2155,11 +2159,6 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, } } else { sb->s_flags = flags; - /* - * Pass 'ubi' to 'fill_super()' in sb->s_fs_info where it is - * replaced by 'c'. - */ - sb->s_fs_info = ubi; err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); if (err) goto out_deact; @@ -2179,11 +2178,18 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, return ERR_PTR(err); } +static void kill_ubifs_super(struct super_block *s) +{ + struct ubifs_info *c = s->s_fs_info; + kill_anon_super(s); + kfree(c); +} + static struct file_system_type ubifs_fs_type = { .name = "ubifs", .owner = THIS_MODULE, .mount = ubifs_mount, - .kill_sb = kill_anon_super, + .kill_sb = kill_ubifs_super, }; /* From dde194a64bb5c3fd05d965775dc92e8a4920a53a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 Jun 2011 16:01:21 -0400 Subject: [PATCH 334/595] afs: fix sget() races, close leak on umount * set ->s_fs_info in set() callback passed to sget() * allocate the thing and set it up enough for afs_test_super() before making it visible * have it freed in ->kill_sb() (current tree simply leaks it) * have ->put_super() leave ->s_fs_info->volume alone; it's too early for dropping it; do that from ->kill_sb() after having called kill_anon_super(). Signed-off-by: Al Viro --- fs/afs/super.c | 73 ++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 41 deletions(-) diff --git a/fs/afs/super.c b/fs/afs/super.c index fb240e8766d6..b7d48d7eaa1e 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -31,8 +31,8 @@ static void afs_i_init_once(void *foo); static struct dentry *afs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data); +static void afs_kill_super(struct super_block *sb); static struct inode *afs_alloc_inode(struct super_block *sb); -static void afs_put_super(struct super_block *sb); static void afs_destroy_inode(struct inode *inode); static int afs_statfs(struct dentry *dentry, struct kstatfs *buf); @@ -40,7 +40,7 @@ struct file_system_type afs_fs_type = { .owner = THIS_MODULE, .name = "afs", .mount = afs_mount, - .kill_sb = kill_anon_super, + .kill_sb = afs_kill_super, .fs_flags = 0, }; @@ -50,7 +50,6 @@ static const struct super_operations afs_super_ops = { .drop_inode = afs_drop_inode, .destroy_inode = afs_destroy_inode, .evict_inode = afs_evict_inode, - .put_super = afs_put_super, .show_options = generic_show_options, }; @@ -282,19 +281,25 @@ static int afs_parse_device_name(struct afs_mount_params *params, */ static int afs_test_super(struct super_block *sb, void *data) { - struct afs_mount_params *params = data; + struct afs_super_info *as1 = data; struct afs_super_info *as = sb->s_fs_info; - return as->volume == params->volume; + return as->volume == as1->volume; +} + +static int afs_set_super(struct super_block *sb, void *data) +{ + sb->s_fs_info = data; + return set_anon_super(sb, NULL); } /* * fill in the superblock */ -static int afs_fill_super(struct super_block *sb, void *data) +static int afs_fill_super(struct super_block *sb, + struct afs_mount_params *params) { - struct afs_mount_params *params = data; - struct afs_super_info *as = NULL; + struct afs_super_info *as = sb->s_fs_info; struct afs_fid fid; struct dentry *root = NULL; struct inode *inode = NULL; @@ -302,22 +307,11 @@ static int afs_fill_super(struct super_block *sb, void *data) _enter(""); - /* allocate a superblock info record */ - as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); - if (!as) { - _leave(" = -ENOMEM"); - return -ENOMEM; - } - - afs_get_volume(params->volume); - as->volume = params->volume; - /* fill in the superblock */ sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = AFS_FS_MAGIC; sb->s_op = &afs_super_ops; - sb->s_fs_info = as; sb->s_bdi = &as->volume->bdi; /* allocate the root inode and dentry */ @@ -326,7 +320,7 @@ static int afs_fill_super(struct super_block *sb, void *data) fid.unique = 1; inode = afs_iget(sb, params->key, &fid, NULL, NULL); if (IS_ERR(inode)) - goto error_inode; + return PTR_ERR(inode); if (params->autocell) set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags); @@ -342,16 +336,8 @@ static int afs_fill_super(struct super_block *sb, void *data) _leave(" = 0"); return 0; -error_inode: - ret = PTR_ERR(inode); - inode = NULL; error: iput(inode); - afs_put_volume(as->volume); - kfree(as); - - sb->s_fs_info = NULL; - _leave(" = %d", ret); return ret; } @@ -367,6 +353,7 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, struct afs_volume *vol; struct key *key; char *new_opts = kstrdup(options, GFP_KERNEL); + struct afs_super_info *as; int ret; _enter(",,%s,%p", dev_name, options); @@ -399,12 +386,22 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, ret = PTR_ERR(vol); goto error; } - params.volume = vol; + + /* allocate a superblock info record */ + as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); + if (!as) { + ret = -ENOMEM; + afs_put_volume(vol); + goto error; + } + as->volume = vol; /* allocate a deviceless superblock */ - sb = sget(fs_type, afs_test_super, set_anon_super, ¶ms); + sb = sget(fs_type, afs_test_super, afs_set_super, as); if (IS_ERR(sb)) { ret = PTR_ERR(sb); + afs_put_volume(vol); + kfree(as); goto error; } @@ -422,16 +419,16 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, } else { _debug("reuse"); ASSERTCMP(sb->s_flags, &, MS_ACTIVE); + afs_put_volume(vol); + kfree(as); } - afs_put_volume(params.volume); afs_put_cell(params.cell); kfree(new_opts); _leave(" = 0 [%p]", sb); return dget(sb->s_root); error: - afs_put_volume(params.volume); afs_put_cell(params.cell); key_put(params.key); kfree(new_opts); @@ -439,18 +436,12 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, return ERR_PTR(ret); } -/* - * finish the unmounting process on the superblock - */ -static void afs_put_super(struct super_block *sb) +static void afs_kill_super(struct super_block *sb) { struct afs_super_info *as = sb->s_fs_info; - - _enter(""); - + kill_anon_super(sb); afs_put_volume(as->volume); - - _leave(""); + kfree(as); } /* From a685e08987d1edf1995b76511d4c98ea0e905377 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Jun 2011 21:13:01 -0400 Subject: [PATCH 335/595] Delay struct net freeing while there's a sysfs instance refering to it * new refcount in struct net, controlling actual freeing of the memory * new method in kobj_ns_type_operations (->drop_ns()) * ->current_ns() semantics change - it's supposed to be followed by corresponding ->drop_ns(). For struct net in case of CONFIG_NET_NS it bumps the new refcount; net_drop_ns() decrements it and calls net_free() if the last reference has been dropped. Method renamed to ->grab_current_ns(). * old net_free() callers call net_drop_ns() instead. * sysfs_exit_ns() is gone, along with a large part of callchain leading to it; now that the references stored in ->ns[...] stay valid we do not need to hunt them down and replace them with NULL. That fixes problems in sysfs_lookup() and sysfs_readdir(), along with getting rid of sb->s_instances abuse. Note that struct net *shutdown* logics has not changed - net_cleanup() is called exactly when it used to be called. The only thing postponed by having a sysfs instance refering to that struct net is actual freeing of memory occupied by struct net. Signed-off-by: Al Viro --- fs/sysfs/mount.c | 37 +++++++++++-------------------------- fs/sysfs/sysfs.h | 2 +- include/linux/kobject_ns.h | 10 ++++++---- include/linux/sysfs.h | 7 ------- include/net/net_namespace.h | 10 +++++++++- lib/kobject.c | 26 +++++++++----------------- net/core/net-sysfs.c | 23 +++++++++-------------- net/core/net_namespace.c | 12 ++++++++++-- 8 files changed, 55 insertions(+), 72 deletions(-) diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 266895783b47..e34f0d99ea4e 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -95,6 +95,14 @@ static int sysfs_set_super(struct super_block *sb, void *data) return error; } +static void free_sysfs_super_info(struct sysfs_super_info *info) +{ + int type; + for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) + kobj_ns_drop(type, info->ns[type]); + kfree(info); +} + static struct dentry *sysfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { @@ -108,11 +116,11 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, return ERR_PTR(-ENOMEM); for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) - info->ns[type] = kobj_ns_current(type); + info->ns[type] = kobj_ns_grab_current(type); sb = sget(fs_type, sysfs_test_super, sysfs_set_super, info); if (IS_ERR(sb) || sb->s_fs_info != info) - kfree(info); + free_sysfs_super_info(info); if (IS_ERR(sb)) return ERR_CAST(sb); if (!sb->s_root) { @@ -131,12 +139,11 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, static void sysfs_kill_sb(struct super_block *sb) { struct sysfs_super_info *info = sysfs_info(sb); - /* Remove the superblock from fs_supers/s_instances * so we can't find it, before freeing sysfs_super_info. */ kill_anon_super(sb); - kfree(info); + free_sysfs_super_info(info); } static struct file_system_type sysfs_fs_type = { @@ -145,28 +152,6 @@ static struct file_system_type sysfs_fs_type = { .kill_sb = sysfs_kill_sb, }; -void sysfs_exit_ns(enum kobj_ns_type type, const void *ns) -{ - struct super_block *sb; - - mutex_lock(&sysfs_mutex); - spin_lock(&sb_lock); - list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { - struct sysfs_super_info *info = sysfs_info(sb); - /* - * If we see a superblock on the fs_supers/s_instances - * list the unmount has not completed and sb->s_fs_info - * points to a valid struct sysfs_super_info. - */ - /* Ignore superblocks with the wrong ns */ - if (info->ns[type] != ns) - continue; - info->ns[type] = NULL; - } - spin_unlock(&sb_lock); - mutex_unlock(&sysfs_mutex); -} - int __init sysfs_init(void) { int err = -ENOMEM; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 3d28af31d863..2ed2404f3113 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -136,7 +136,7 @@ struct sysfs_addrm_cxt { * instance). */ struct sysfs_super_info { - const void *ns[KOBJ_NS_TYPES]; + void *ns[KOBJ_NS_TYPES]; }; #define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info)) extern struct sysfs_dirent sysfs_root; diff --git a/include/linux/kobject_ns.h b/include/linux/kobject_ns.h index 82cb5bf461fb..f66b065a8b5f 100644 --- a/include/linux/kobject_ns.h +++ b/include/linux/kobject_ns.h @@ -32,15 +32,17 @@ enum kobj_ns_type { /* * Callbacks so sysfs can determine namespaces - * @current_ns: return calling task's namespace + * @grab_current_ns: return a new reference to calling task's namespace * @netlink_ns: return namespace to which a sock belongs (right?) * @initial_ns: return the initial namespace (i.e. init_net_ns) + * @drop_ns: drops a reference to namespace */ struct kobj_ns_type_operations { enum kobj_ns_type type; - const void *(*current_ns)(void); + void *(*grab_current_ns)(void); const void *(*netlink_ns)(struct sock *sk); const void *(*initial_ns)(void); + void (*drop_ns)(void *); }; int kobj_ns_type_register(const struct kobj_ns_type_operations *ops); @@ -48,9 +50,9 @@ int kobj_ns_type_registered(enum kobj_ns_type type); const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent); const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj); -const void *kobj_ns_current(enum kobj_ns_type type); +void *kobj_ns_grab_current(enum kobj_ns_type type); const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk); const void *kobj_ns_initial(enum kobj_ns_type type); -void kobj_ns_exit(enum kobj_ns_type type, const void *ns); +void kobj_ns_drop(enum kobj_ns_type type, void *ns); #endif /* _LINUX_KOBJECT_NS_H */ diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index c3acda60eee0..e2696d76a599 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -177,9 +177,6 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd); void sysfs_put(struct sysfs_dirent *sd); -/* Called to clear a ns tag when it is no longer valid */ -void sysfs_exit_ns(enum kobj_ns_type type, const void *tag); - int __must_check sysfs_init(void); #else /* CONFIG_SYSFS */ @@ -338,10 +335,6 @@ static inline void sysfs_put(struct sysfs_dirent *sd) { } -static inline void sysfs_exit_ns(int type, const void *tag) -{ -} - static inline int __must_check sysfs_init(void) { return 0; diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 2bf9ed9ef26b..aef430d779bd 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -35,8 +35,11 @@ struct netns_ipvs; #define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS) struct net { + atomic_t passive; /* To decided when the network + * namespace should be freed. + */ atomic_t count; /* To decided when the network - * namespace should be freed. + * namespace should be shut down. */ #ifdef NETNS_REFCNT_DEBUG atomic_t use_count; /* To track references we @@ -154,6 +157,9 @@ int net_eq(const struct net *net1, const struct net *net2) { return net1 == net2; } + +extern void net_drop_ns(void *); + #else static inline struct net *get_net(struct net *net) @@ -175,6 +181,8 @@ int net_eq(const struct net *net1, const struct net *net2) { return 1; } + +#define net_drop_ns NULL #endif diff --git a/lib/kobject.c b/lib/kobject.c index 82dc34c095c2..640bd98a4c8a 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -948,14 +948,14 @@ const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj) } -const void *kobj_ns_current(enum kobj_ns_type type) +void *kobj_ns_grab_current(enum kobj_ns_type type) { - const void *ns = NULL; + void *ns = NULL; spin_lock(&kobj_ns_type_lock); if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) && kobj_ns_ops_tbl[type]) - ns = kobj_ns_ops_tbl[type]->current_ns(); + ns = kobj_ns_ops_tbl[type]->grab_current_ns(); spin_unlock(&kobj_ns_type_lock); return ns; @@ -987,23 +987,15 @@ const void *kobj_ns_initial(enum kobj_ns_type type) return ns; } -/* - * kobj_ns_exit - invalidate a namespace tag - * - * @type: the namespace type (i.e. KOBJ_NS_TYPE_NET) - * @ns: the actual namespace being invalidated - * - * This is called when a tag is no longer valid. For instance, - * when a network namespace exits, it uses this helper to - * make sure no sb's sysfs_info points to the now-invalidated - * netns. - */ -void kobj_ns_exit(enum kobj_ns_type type, const void *ns) +void kobj_ns_drop(enum kobj_ns_type type, void *ns) { - sysfs_exit_ns(type, ns); + spin_lock(&kobj_ns_type_lock); + if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) && + kobj_ns_ops_tbl[type] && kobj_ns_ops_tbl[type]->drop_ns) + kobj_ns_ops_tbl[type]->drop_ns(ns); + spin_unlock(&kobj_ns_type_lock); } - EXPORT_SYMBOL(kobject_get); EXPORT_SYMBOL(kobject_put); EXPORT_SYMBOL(kobject_del); diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 11b98bc2aa8f..33d2a1fba131 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -1179,9 +1179,14 @@ static void remove_queue_kobjects(struct net_device *net) #endif } -static const void *net_current_ns(void) +static void *net_grab_current_ns(void) { - return current->nsproxy->net_ns; + struct net *ns = current->nsproxy->net_ns; +#ifdef CONFIG_NET_NS + if (ns) + atomic_inc(&ns->passive); +#endif + return ns; } static const void *net_initial_ns(void) @@ -1196,22 +1201,13 @@ static const void *net_netlink_ns(struct sock *sk) struct kobj_ns_type_operations net_ns_type_operations = { .type = KOBJ_NS_TYPE_NET, - .current_ns = net_current_ns, + .grab_current_ns = net_grab_current_ns, .netlink_ns = net_netlink_ns, .initial_ns = net_initial_ns, + .drop_ns = net_drop_ns, }; EXPORT_SYMBOL_GPL(net_ns_type_operations); -static void net_kobj_ns_exit(struct net *net) -{ - kobj_ns_exit(KOBJ_NS_TYPE_NET, net); -} - -static struct pernet_operations kobj_net_ops = { - .exit = net_kobj_ns_exit, -}; - - #ifdef CONFIG_HOTPLUG static int netdev_uevent(struct device *d, struct kobj_uevent_env *env) { @@ -1339,6 +1335,5 @@ EXPORT_SYMBOL(netdev_class_remove_file); int netdev_kobject_init(void) { kobj_ns_type_register(&net_ns_type_operations); - register_pernet_subsys(&kobj_net_ops); return class_register(&net_class); } diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 6c6b86d0da15..cdcbc3cb00a9 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -128,6 +128,7 @@ static __net_init int setup_net(struct net *net) LIST_HEAD(net_exit_list); atomic_set(&net->count, 1); + atomic_set(&net->passive, 1); #ifdef NETNS_REFCNT_DEBUG atomic_set(&net->use_count, 0); @@ -210,6 +211,13 @@ static void net_free(struct net *net) kmem_cache_free(net_cachep, net); } +void net_drop_ns(void *p) +{ + struct net *ns = p; + if (ns && atomic_dec_and_test(&ns->passive)) + net_free(ns); +} + struct net *copy_net_ns(unsigned long flags, struct net *old_net) { struct net *net; @@ -230,7 +238,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) } mutex_unlock(&net_mutex); if (rv < 0) { - net_free(net); + net_drop_ns(net); return ERR_PTR(rv); } return net; @@ -286,7 +294,7 @@ static void cleanup_net(struct work_struct *work) /* Finally it is safe to free my network namespace structure */ list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { list_del_init(&net->exit_list); - net_free(net); + net_drop_ns(net); } } static DECLARE_WORK(net_cleanup_work, cleanup_net); From b84bd27fe70206f9253c395958134e4e4b7e55f0 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Sun, 12 Jun 2011 08:22:08 +0200 Subject: [PATCH 336/595] HID: hid-multitouch: fix broken eGalax Since the inclusion of eGalax devices in 2.6.39, I've got some bug reports for 480d and other devices. The problem lies in the reports descriptors: eGalax supports both pen and fingers, and so the reports descriptors contained both. But hid-multitouch relies on them to detect the last item in each field to send the multitouch events. In 480d, the last item is not Y as it should but Pressure. That means that the fields are not aligned and X,Y are at 0,0 (the other touch coordinates of the report). With this patch, the detection is made only when the field ContactID has been detected inside the collection. There is still a problem with the detections of the range as stylus and fingers may not have the same min/max, but it's a start. Signed-off-by: Benjamin Tissoires Reviewed-by: Henrik Rydberg Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 57 ++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 8bc32a0fa00e..0b2dcd0ee591 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -64,6 +64,7 @@ struct mt_device { struct mt_class *mtclass; /* our mt device class */ unsigned last_field_index; /* last field index of the report */ unsigned last_slot_field; /* the last field of a slot */ + int last_mt_collection; /* last known mt-related collection */ __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ __u8 num_received; /* how many contacts we received */ __u8 num_expected; /* expected last contact index */ @@ -225,8 +226,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, cls->sn_move); /* touchscreen emulation */ set_abs(hi->input, ABS_X, field, cls->sn_move); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_GD_Y: if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) @@ -237,8 +240,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, cls->sn_move); /* touchscreen emulation */ set_abs(hi->input, ABS_Y, field, cls->sn_move); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; } return 0; @@ -246,31 +251,40 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, case HID_UP_DIGITIZER: switch (usage->hid) { case HID_DG_INRANGE: - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_CONFIDENCE: - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_TIPSWITCH: hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); input_set_capability(hi->input, EV_KEY, BTN_TOUCH); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_CONTACTID: input_mt_init_slots(hi->input, td->maxcontacts); td->last_slot_field = usage->hid; td->last_field_index = field->index; + td->last_mt_collection = usage->collection_index; return 1; case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MAJOR); set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, cls->sn_width); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, @@ -279,8 +293,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, cls->sn_height); input_set_abs_params(hi->input, ABS_MT_ORIENTATION, 0, 1, 0, 0); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_TIPPRESSURE: if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) @@ -292,16 +308,20 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, /* touchscreen emulation */ set_abs(hi->input, ABS_PRESSURE, field, cls->sn_pressure); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_CONTACTCOUNT: - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) + td->last_field_index = field->index; return 1; case HID_DG_CONTACTMAX: /* we don't set td->last_slot_field as contactcount and * contact max are global to the report */ - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) + td->last_field_index = field->index; return -1; } /* let hid-input decide for the others */ @@ -516,6 +536,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) } td->mtclass = mtclass; td->inputmode = -1; + td->last_mt_collection = -1; hid_set_drvdata(hdev, td); ret = hid_parse(hdev); From 54463a66b91cf491a7c9af612b0e310babc5fa24 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 13 Jun 2011 08:32:06 +0200 Subject: [PATCH 337/595] ALSA: hda - Fix wrong auto-mute type for Acer Aspire-one The auto-mute setup for Acer Aspire-one with ALC268 was set wrongly during the clean-up of auto-mute function. Fixed now. Tested-by: Borislav Petkov Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 43fcfbd32847..61a774b3d3cb 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -13316,9 +13316,8 @@ static void alc268_acer_lc_setup(struct hda_codec *codec) struct alc_spec *spec = codec->spec; spec->autocfg.hp_pins[0] = 0x15; spec->autocfg.speaker_pins[0] = 0x14; - spec->automute_mixer_nid[0] = 0x0f; spec->automute = 1; - spec->automute_mode = ALC_AUTOMUTE_MIXER; + spec->automute_mode = ALC_AUTOMUTE_AMP; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x12; From 2308f4add3de9f6c9c9f02e49461e94d84bb200a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 12 Jun 2011 13:02:43 -0700 Subject: [PATCH 338/595] ALSA: hda - Fix beep_device compilation warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using static inline functions can reduce compilation messages and macro misuse. sound/pci/hda/patch_conexant.c: In function ‘patch_cxt5045’: sound/pci/hda/patch_conexant.c:1232:3: warning: statement with no effect Signed-off-by: Joe Perches Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index f1de1bac042c..4967eabe774e 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -50,7 +50,12 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable); int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); void snd_hda_detach_beep_device(struct hda_codec *codec); #else -#define snd_hda_attach_beep_device(...) 0 -#define snd_hda_detach_beep_device(...) +static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) +{ + return 0; +} +void snd_hda_detach_beep_device(struct hda_codec *codec) +{ +} #endif #endif From 8f4e0a18682d91abfad72ede3d3cb5f3ebdf54b4 Mon Sep 17 00:00:00 2001 From: Hans Schillstrom Date: Mon, 13 Jun 2011 09:06:57 +0200 Subject: [PATCH 339/595] IPVS netns exit causes crash in conntrack Quote from Patric Mc Hardy "This looks like nfnetlink.c excited and destroyed the nfnl socket, but ip_vs was still holding a reference to a conntrack. When the conntrack got destroyed it created a ctnetlink event, causing an oops in netlink_has_listeners when trying to use the destroyed nfnetlink socket." If nf_conntrack_netlink is loaded before ip_vs this is not a problem. This patch simply avoids calling ip_vs_conn_drop_conntrack() when netns is dying as suggested by Julian. Signed-off-by: Hans Schillstrom Signed-off-by: Simon Horman --- net/netfilter/ipvs/ip_vs_conn.c | 10 +++++++++- net/netfilter/ipvs/ip_vs_core.c | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index bf28ac2fc99b..782db275ac53 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -776,8 +776,16 @@ static void ip_vs_conn_expire(unsigned long data) if (cp->control) ip_vs_control_del(cp); - if (cp->flags & IP_VS_CONN_F_NFCT) + if (cp->flags & IP_VS_CONN_F_NFCT) { ip_vs_conn_drop_conntrack(cp); + /* Do not access conntracks during subsys cleanup + * because nf_conntrack_find_get can not be used after + * conntrack cleanup for the net. + */ + smp_rmb(); + if (ipvs->enable) + ip_vs_conn_drop_conntrack(cp); + } ip_vs_pe_put(cp->pe); kfree(cp->pe_data); diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 55af2242bccd..24c28d238dcb 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1945,6 +1945,7 @@ static void __net_exit __ip_vs_dev_cleanup(struct net *net) { EnterFunction(2); net_ipvs(net)->enable = 0; /* Disable packet reception */ + smp_wmb(); __ip_vs_sync_cleanup(net); LeaveFunction(2); } From 9d5ae7cd6cb9ead43336fec1094184d1dc740fbd Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Fri, 3 Jun 2011 20:24:03 +0000 Subject: [PATCH 340/595] omap: pandora: fix NAND support Commit d5ce2b65 "omap3630: nand: fix device size to work in polled mode" changed values for .devsize in nand platform data, now we have to pass NAND_BUSWIDTH_16 instead of '1' to select 16bit NAND. Update pandora's platform data accordingly, also specify appropriate transfer type. Signed-off-by: Grazvydas Ignotas Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-omap3pandora.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 1d10736c6d3c..a3d655c0a49b 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -86,7 +86,8 @@ static struct mtd_partition omap3pandora_nand_partitions[] = { static struct omap_nand_platform_data pandora_nand_data = { .cs = 0, - .devsize = 1, /* '0' for 8-bit, '1' for 16-bit device */ + .devsize = NAND_BUSWIDTH_16, + .xfer_type = NAND_OMAP_PREFETCH_DMA, .parts = omap3pandora_nand_partitions, .nr_parts = ARRAY_SIZE(omap3pandora_nand_partitions), }; From e3f88ae9960920598cad132c553019ee79ff3aca Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Mon, 13 Jun 2011 16:23:46 +0530 Subject: [PATCH 341/595] spi-pl022: Add missing return value update Return error on out of range cpsdvsr value. Acked-by: Linus Walleij Signed-off-by: Virupax Sadashivpetimath Signed-off-by: Grant Likely --- drivers/spi/amba-pl022.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index 6a9e58dd36c7..d18ce9e946d8 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -1861,6 +1861,7 @@ static int pl022_setup(struct spi_device *spi) } if ((clk_freq.cpsdvsr < CPSDVR_MIN) || (clk_freq.cpsdvsr > CPSDVR_MAX)) { + status = -EINVAL; dev_err(&spi->dev, "cpsdvsr is configured incorrectly\n"); goto err_config_params; From ac08aedfa5d3de0dcb3825b598d16c2e57991f54 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 13 Jun 2011 11:28:50 -0400 Subject: [PATCH 342/595] Btrfs: check the return value from set_anon_super Al Viro noticed we weren't checking for set_anon_super failures. This adds the required checks. Signed-off-by: Chris Mason --- fs/btrfs/disk-io.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 9f68c6898653..20c111b3fa0d 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1312,7 +1312,9 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, spin_lock_init(&root->cache_lock); init_waitqueue_head(&root->cache_wait); - set_anon_super(&root->anon_super, NULL); + ret = set_anon_super(&root->anon_super, NULL); + if (ret) + goto fail; if (btrfs_root_refs(&root->root_item) == 0) { ret = -ENOENT; From f4c44016218a6fce357715b9bbabbbbe1f69853c Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 13 Jun 2011 11:30:47 -0400 Subject: [PATCH 343/595] Btrfs: drop the delalloc_bytes check in shrink_delalloc Even when delalloc_bytes is zero, we may need to sleep while waiting for delalloc space. Signed-off-by: Chris Mason --- fs/btrfs/extent-tree.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index b42efc2ded51..1f61bf5b4960 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3314,10 +3314,6 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, if (reserved == 0) return 0; - /* nothing to shrink - nothing to reclaim */ - if (root->fs_info->delalloc_bytes == 0) - return 0; - max_reclaim = min(reserved, to_reclaim); while (loops < 1024) { From cd51875d53ae1459a2b09b4338166a218c0635a7 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Thu, 9 Jun 2011 12:58:53 +0400 Subject: [PATCH 344/595] CIFS: Fix sparse error cifs_sb_master_tlink was declared as inline, but without a definition. Remove the declaration and move the definition up. Signed-off-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index bb659eb73810..9190018f97e1 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2149,7 +2149,10 @@ cifs_put_tlink(struct tcon_link *tlink) } static inline struct tcon_link * -cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb); +cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb) +{ + return cifs_sb->master_tlink; +} static int compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data) @@ -3484,12 +3487,6 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) return tcon; } -static inline struct tcon_link * -cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb) -{ - return cifs_sb->master_tlink; -} - struct cifs_tcon * cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) { From 7fdbaa1b8daa1009b705985b903e3d2ebccad456 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 10 Jun 2011 16:14:57 -0400 Subject: [PATCH 345/595] cifs: don't allow cifs_reconnect to exit with NULL socket pointer It's possible for the following set of events to happen: cifsd calls cifs_reconnect which reconnects the socket. A userspace process then calls cifs_negotiate_protocol to handle the NEGOTIATE and gets a reply. But, while processing the reply, cifsd calls cifs_reconnect again. Eventually the GlobalMid_Lock is dropped and the reply from the earlier NEGOTIATE completes and the tcpStatus is set to CifsGood. cifs_reconnect then goes through and closes the socket and sets the pointer to zero, but because the status is now CifsGood, the new socket is not created and cifs_reconnect exits with the socket pointer set to NULL. Fix this by only setting the tcpStatus to CifsGood if the tcpStatus is CifsNeedNegotiate, and by making sure that generic_ip_connect is always called at least once in cifs_reconnect. Note that this is not a perfect fix for this issue. It's still possible that the NEGOTIATE reply is handled after the socket has been closed and reconnected. In that case, the socket state will look correct but it no NEGOTIATE was performed on it be for the wrong socket. In that situation though the server should just shut down the socket on the next attempted send, rather than causing the oops that occurs today. Cc: # .38.x: fd88ce9: [CIFS] cifs: clarify the meaning of tcpStatus == CifsGood Reported-and-Tested-by: Ben Greear Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 9190018f97e1..fa73e2a51cf2 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -152,7 +152,7 @@ cifs_reconnect(struct TCP_Server_Info *server) mid_entry->callback(mid_entry); } - while (server->tcpStatus == CifsNeedReconnect) { + do { try_to_freeze(); /* we should try only the port we connected to before */ @@ -167,7 +167,7 @@ cifs_reconnect(struct TCP_Server_Info *server) server->tcpStatus = CifsNeedNegotiate; spin_unlock(&GlobalMid_Lock); } - } + } while (server->tcpStatus == CifsNeedReconnect); return rc; } @@ -3374,7 +3374,7 @@ int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses) } if (rc == 0) { spin_lock(&GlobalMid_Lock); - if (server->tcpStatus != CifsExiting) + if (server->tcpStatus == CifsNeedNegotiate) server->tcpStatus = CifsGood; else rc = -EHOSTDOWN; From 3e715513643f0207c8f3c22010b54954cd697474 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 13 Jun 2011 11:50:41 -0400 Subject: [PATCH 346/595] cifs: show sec= option in /proc/mounts Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 989442dcfb45..e9def996e383 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -352,6 +352,37 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) } } +static void +cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server) +{ + seq_printf(s, ",sec="); + + switch (server->secType) { + case LANMAN: + seq_printf(s, "lanman"); + break; + case NTLMv2: + seq_printf(s, "ntlmv2"); + break; + case NTLM: + seq_printf(s, "ntlm"); + break; + case Kerberos: + seq_printf(s, "krb5"); + break; + case RawNTLMSSP: + seq_printf(s, "ntlmssp"); + break; + default: + /* shouldn't ever happen */ + seq_printf(s, "unknown"); + break; + } + + if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + seq_printf(s, "i"); +} + /* * cifs_show_options() is for displaying mount options in /proc/mounts. * Not all settable options are displayed but most of the important @@ -365,6 +396,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) struct sockaddr *srcaddr; srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; + cifs_show_security(s, tcon->ses->server); + seq_printf(s, ",unc=%s", tcon->treeName); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) From 8d1bca328b7c17af33bcf966d799c556ecbf370f Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sat, 11 Jun 2011 21:17:10 -0400 Subject: [PATCH 347/595] cifs: correctly handle NULL tcon pointer in CIFSTCon Long ago (in commit 00e485b0), I added some code to handle share-level passwords in CIFSTCon. That code ignored the fact that it's legit to pass in a NULL tcon pointer when connecting to the IPC$ share on the server. This wasn't really a problem until recently as we only called CIFSTCon this way when the server returned -EREMOTE. With the introduction of commit c1508ca2 however, it gets called this way on every mount, causing an oops when share-level security is in effect. Fix this by simply treating a NULL tcon pointer as if user-level security were in effect. I'm not aware of any servers that protect the IPC$ share with a specific password anyway. Also, add a comment to the top of CIFSTCon to ensure that we don't make the same mistake again. Cc: Reported-by: Martijn Uffing Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index fa73e2a51cf2..12cf72dd0c42 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3174,6 +3174,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, return rc; } +/* + * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon + * pointer may be NULL. + */ int CIFSTCon(unsigned int xid, struct cifs_ses *ses, const char *tree, struct cifs_tcon *tcon, @@ -3208,7 +3212,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, pSMB->AndXCommand = 0xFF; pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); bcc_ptr = &pSMB->Password[0]; - if ((ses->server->sec_mode) & SECMODE_USER) { + if (!tcon || (ses->server->sec_mode & SECMODE_USER)) { pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ *bcc_ptr = 0; /* password is null byte */ bcc_ptr++; /* skip password */ From b9cabe52c27cf834137f3aaa46da23bcf32284e8 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 12 Jun 2011 04:28:16 +0000 Subject: [PATCH 348/595] ieee802154: Don't leak memory in ieee802154_nl_fill_phy In net/ieee802154/nl-phy.c::ieee802154_nl_fill_phy() I see two small issues. 1) If the allocation of 'buf' fails we may just as well return -EMSGSIZE directly rather than jumping to 'out:' and do a pointless kfree(0). 2) We do not free 'buf' unless we jump to one of the error labels and this leaks memory. This patch should address both. Signed-off-by: Jesper Juhl Acked-by: Dmitry Eremin-Solenikov Signed-off-by: David S. Miller --- net/ieee802154/nl-phy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index ed0eab39f531..02548b292b53 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c @@ -44,7 +44,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid, pr_debug("%s\n", __func__); if (!buf) - goto out; + return -EMSGSIZE; hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags, IEEE802154_LIST_PHY); @@ -65,6 +65,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid, pages * sizeof(uint32_t), buf); mutex_unlock(&phy->pib_lock); + kfree(buf); return genlmsg_end(msg, hdr); nla_put_failure: From 1ffde03d2aa112750468cff07efc9e0a504517dd Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 12 Jun 2011 09:40:49 +0000 Subject: [PATCH 349/595] 3c503: fix broken IRQ autoprobing Fix broken IRQ autoprobing in 3c503 driver: - improper IRQ freeing (does not free IRQs causes WARN) - missing break when an working IRQ is found The driver works with this patch. Signed-off-by: Ondrej Zary Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/3c503.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index d84f6e8903a5..5b732988d493 100644 --- a/drivers/net/3c503.c +++ b/drivers/net/3c503.c @@ -412,7 +412,7 @@ el2_open(struct net_device *dev) outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR); outb_p(0x00, E33G_IDCFR); msleep(1); - free_irq(*irqp, el2_probe_interrupt); + free_irq(*irqp, &seen); if (!seen) continue; @@ -422,6 +422,7 @@ el2_open(struct net_device *dev) continue; if (retval < 0) goto err_disable; + break; } while (*++irqp); if (*irqp == 0) { From 2c53b436a30867eb6b47dd7bab23ba638d1fb0d2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 13 Jun 2011 15:29:59 -0700 Subject: [PATCH 350/595] Linux 3.0-rc3 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 72c0e321f2da..badb9239e2bb 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 0 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc3 NAME = Sneaky Weasel # *DOCUMENTATION* From 9281b2a2e2e02ad4bcc2fdd11797709b815d5f8e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 13 Jun 2011 08:17:36 +0000 Subject: [PATCH 351/595] net/hplance: hplance_init() should be __devinit WARNING: vmlinux.o(.devinit.text+0x253e): Section mismatch in reference from the function hplance_init_one() to the function .init.text:hplance_init() The forward declaration had the correct attribute, but the actual function definition hadn't. Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/hplance.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c index b6060f7538df..a900d5bf2948 100644 --- a/drivers/net/hplance.c +++ b/drivers/net/hplance.c @@ -135,7 +135,7 @@ static void __devexit hplance_remove_one(struct dio_dev *d) } /* Initialise a single lance board at the given DIO device */ -static void __init hplance_init(struct net_device *dev, struct dio_dev *d) +static void __devinit hplance_init(struct net_device *dev, struct dio_dev *d) { unsigned long va = (d->resource.start + DIO_VIRADDRBASE); struct hplance_private *lp; From 96bf8bd1c953c3b9d89eac9f13dfdbf5e580060f Mon Sep 17 00:00:00 2001 From: Greg Dietsche Date: Mon, 13 Jun 2011 09:40:38 -0500 Subject: [PATCH 352/595] savage: remove unnecessary if statement the code always returns ret regardless, so if(ret) check is unnecessary. v2: fixed up the spelling. Signed-off-by: Greg Dietsche Reviewed-by: Nicolas Kaiser Signed-off-by: Dave Airlie --- drivers/gpu/drm/savage/savage_bci.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c index bf5f83ea14fe..cb1ee4e0050a 100644 --- a/drivers/gpu/drm/savage/savage_bci.c +++ b/drivers/gpu/drm/savage/savage_bci.c @@ -647,9 +647,6 @@ int savage_driver_firstopen(struct drm_device *dev) ret = drm_addmap(dev, aperture_base, SAVAGE_APERTURE_SIZE, _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING, &dev_priv->aperture); - if (ret) - return ret; - return ret; } From 82ba3fef67829813d0ed4c45231235084a07f081 Mon Sep 17 00:00:00 2001 From: Jay Estabrook Date: Thu, 9 Jun 2011 18:18:39 -0400 Subject: [PATCH 353/595] alpha/drm: Cleanup Alpha support in DRM generic code Remove an obsolete Alpha adjustment, and modify another, to go with the current Alpha architecture support. Signed-off-by: Jay Estabrook Tested-by: Matt Turner Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_bufs.c | 3 --- drivers/gpu/drm/drm_vm.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 3e257a50bf56..e1bd713d91a2 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -182,9 +182,6 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset, kfree(map); return -EINVAL; } -#endif -#ifdef __alpha__ - map->offset += dev->hose->mem_space->start; #endif /* Some drivers preinitialize some maps, without the X Server * needing to be aware of it. Therefore, we just return success diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index 2c3fcbdfd8ff..5db96d45fc71 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -526,7 +526,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) static resource_size_t drm_core_get_reg_ofs(struct drm_device *dev) { #ifdef __alpha__ - return dev->hose->dense_mem_base - dev->hose->mem_space->start; + return dev->hose->dense_mem_base; #else return 0; #endif From 83533c132a55aac735028f6fb9b956e8c078db1f Mon Sep 17 00:00:00 2001 From: Jay Estabrook Date: Thu, 9 Jun 2011 18:19:12 -0400 Subject: [PATCH 354/595] alpha, drm: Remove obsolete Alpha support in MGA DRM code Remove an obsolete Alpha adjustment in the drm for MGA on Alpha. Signed-off-by: Jay Estabrook Tested-by: Matt Turner Signed-off-by: Dave Airlie --- drivers/gpu/drm/mga/mga_drv.h | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h index 1084fa4d261b..54558a01969a 100644 --- a/drivers/gpu/drm/mga/mga_drv.h +++ b/drivers/gpu/drm/mga/mga_drv.h @@ -195,29 +195,10 @@ extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, #define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER() -#if defined(__linux__) && defined(__alpha__) -#define MGA_BASE(reg) ((unsigned long)(dev_priv->mmio->handle)) -#define MGA_ADDR(reg) (MGA_BASE(reg) + reg) - -#define MGA_DEREF(reg) (*(volatile u32 *)MGA_ADDR(reg)) -#define MGA_DEREF8(reg) (*(volatile u8 *)MGA_ADDR(reg)) - -#define MGA_READ(reg) (_MGA_READ((u32 *)MGA_ADDR(reg))) -#define MGA_READ8(reg) (_MGA_READ((u8 *)MGA_ADDR(reg))) -#define MGA_WRITE(reg, val) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF(reg) = val; } while (0) -#define MGA_WRITE8(reg, val) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8(reg) = val; } while (0) - -static inline u32 _MGA_READ(u32 *addr) -{ - DRM_MEMORYBARRIER(); - return *(volatile u32 *)addr; -} -#else #define MGA_READ8(reg) DRM_READ8(dev_priv->mmio, (reg)) #define MGA_READ(reg) DRM_READ32(dev_priv->mmio, (reg)) #define MGA_WRITE8(reg, val) DRM_WRITE8(dev_priv->mmio, (reg), (val)) #define MGA_WRITE(reg, val) DRM_WRITE32(dev_priv->mmio, (reg), (val)) -#endif #define DWGREG0 0x1c00 #define DWGREG0_END 0x1dff From 7ad35cf288fd63a19bf50e490440a992de808b2b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 25 May 2011 14:00:49 +1000 Subject: [PATCH 355/595] x86/uv/x2apic: update for change in pci bridge handling. When I added 3448a19da479b6bd1e28e2a2be9fa16c6a6feb39 I forgot about the special uv handling code for this, so this patch fixes it up. Acked-by: Jesse Barnes Acked-by: Ingo Molnar Signed-off-by: Dave Airlie --- arch/x86/kernel/apic/x2apic_uv_x.c | 8 ++++---- drivers/pci/pci.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index b511a011b7d0..adc66c3a1fef 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -632,14 +632,14 @@ late_initcall(uv_init_heartbeat); /* Direct Legacy VGA I/O traffic to designated IOH */ int uv_set_vga_state(struct pci_dev *pdev, bool decode, - unsigned int command_bits, bool change_bridge) + unsigned int command_bits, u32 flags) { int domain, bus, rc; - PR_DEVEL("devfn %x decode %d cmd %x chg_brdg %d\n", - pdev->devfn, decode, command_bits, change_bridge); + PR_DEVEL("devfn %x decode %d cmd %x flags %d\n", + pdev->devfn, decode, command_bits, flags); - if (!change_bridge) + if (!(flags & PCI_VGA_STATE_CHANGE_BRIDGE)) return 0; if ((command_bits & PCI_COMMAND_IO) == 0) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 56098b3e17c0..5f10c23dff94 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3271,11 +3271,11 @@ void __init pci_register_set_vga_state(arch_set_vga_state_t func) } static int pci_set_vga_state_arch(struct pci_dev *dev, bool decode, - unsigned int command_bits, bool change_bridge) + unsigned int command_bits, u32 flags) { if (arch_set_vga_state) return arch_set_vga_state(dev, decode, command_bits, - change_bridge); + flags); return 0; } From ab21e60beaa96f2c55604f633dfe74076c531df7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 6 Jun 2011 12:53:30 -0400 Subject: [PATCH 356/595] drm/radeon/kms: fix mac g5 quirk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apple uses the same subsystem pci ids for lots of hardware much of which is wired up differently. In this case, the G5 imac and the G5 tower. Only apply the quirk configuration to G5 towers. Reported-by: Joachim Henke Signed-off-by: Alex Deucher Cc: Joachim Henke Cc: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_combios.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index d1b95b70af61..797c8bcbb6a4 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -1553,9 +1553,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) (rdev->pdev->subsystem_device == 0x4a48)) { /* Mac X800 */ rdev->mode_info.connector_table = CT_MAC_X800; - } else if ((rdev->pdev->device == 0x4150) && - (rdev->pdev->subsystem_vendor == 0x1002) && - (rdev->pdev->subsystem_device == 0x4150)) { + } else if (of_machine_is_compatible("PowerMac7,2") || + of_machine_is_compatible("PowerMac7,3")) { /* Mac G5 9600 */ rdev->mode_info.connector_table = CT_MAC_G5_9600; } else From a27bb4b209dd6c327fa4e7185f2487f9508a58db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Fri, 10 Jun 2011 14:41:26 +0000 Subject: [PATCH 357/595] drm/radeon/kms: do bounds checking for 3D_LOAD_VBPNTR and bump array limit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To my knowledge, the limit is 16 on r300. (the docs don't say what the limit is) The lack of bounds checking can be abused to do all sorts of things (from bypassing parts of the CS checker to crashing the kernel). Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=36745 Cc: stable@kernel.org Signed-off-by: Marek Olšák Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100_track.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h index 2fef9de7f363..686f9dc5d4bd 100644 --- a/drivers/gpu/drm/radeon/r100_track.h +++ b/drivers/gpu/drm/radeon/r100_track.h @@ -63,7 +63,7 @@ struct r100_cs_track { unsigned num_arrays; unsigned max_indx; unsigned color_channel_mask; - struct r100_cs_track_array arrays[11]; + struct r100_cs_track_array arrays[16]; struct r100_cs_track_cb cb[R300_MAX_CB]; struct r100_cs_track_cb zb; struct r100_cs_track_cb aa; @@ -146,6 +146,12 @@ static inline int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, ib = p->ib->ptr; track = (struct r100_cs_track *)p->track; c = radeon_get_ib_value(p, idx++) & 0x1F; + if (c > 16) { + DRM_ERROR("Only 16 vertex buffers are allowed %d\n", + pkt->opcode); + r100_cs_dump_packet(p, pkt); + return -EINVAL; + } track->num_arrays = c; for (i = 0; i < (c - 1); i+=2, idx+=3) { r = r100_cs_packet_next_reloc(p, &reloc); From b65552f06ca866f587a0a50d1f4dbdd3a00ec532 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 12 Jun 2011 20:53:44 +0000 Subject: [PATCH 358/595] drm/i915: Don't leak in i915_gem_shmem_pread_slow() It seems to me that we are leaking 'user_pages' in drivers/gpu/drm/i915/i915_gem.c::i915_gem_shmem_pread_slow() if read_cache_page_gfp() fails. Signed-off-by: Jesper Juhl Signed-off-by: Chris Wilson Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 12d32579b951..94c84d744100 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -465,8 +465,10 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, GFP_HIGHUSER | __GFP_RECLAIMABLE); - if (IS_ERR(page)) - return PTR_ERR(page); + if (IS_ERR(page)) { + ret = PTR_ERR(page); + goto out; + } if (do_bit17_swizzling) { slow_shmem_bit17_copy(page, From 66aa6962ff520804f9874e57ea97995153f499d8 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Mon, 30 May 2011 19:45:43 +0000 Subject: [PATCH 359/595] drm: Compare only lower 32 bits of framebuffer map offsets Drivers using multiple framebuffers got broken by commit 41c2e75e60200a860a74b7c84a6375c105e7437f which ignored the framebuffer (or register) map offset when looking for existing maps. The rationale was that the kernel-userspace ABI is fixed at a 32-bit offset, so the real offsets could not always be handed over for comparison. Instead of ignoring the offset we will compare the lower 32 bit. Drivers using multiple framebuffers should just make sure that the lower 32 bit are different. The existing drivers in question are practically limited to 32-bit systems so that should be fine for them. It is assumed that current drivers always specify a correct framebuffer map offset, even if this offset was ignored since above commit. So this patch should not change anything for drivers using only one framebuffer. Drivers needing multiple framebuffers with 64-bit map offsets will need to cook up something, for instance keeping an ID in the lower bit which is to be aligned away when it comes to using the offset. All of above applies to _DRM_REGISTERS as well. Signed-off-by: Tormod Volden Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_bufs.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index e1bd713d91a2..61e1ef90d4e5 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -46,10 +46,11 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, list_for_each_entry(entry, &dev->maplist, head) { /* * Because the kernel-userspace ABI is fixed at a 32-bit offset - * while PCI resources may live above that, we ignore the map - * offset for maps of type _DRM_FRAMEBUFFER or _DRM_REGISTERS. - * It is assumed that each driver will have only one resource of - * each type. + * while PCI resources may live above that, we only compare the + * lower 32 bits of the map offset for maps of type + * _DRM_FRAMEBUFFER or _DRM_REGISTERS. + * It is assumed that if a driver have more than one resource + * of each type, the lower 32 bits are different. */ if (!entry->map || map->type != entry->map->type || @@ -59,9 +60,12 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, case _DRM_SHM: if (map->flags != _DRM_CONTAINS_LOCK) break; + return entry; case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: - return entry; + if ((entry->map->offset & 0xffffffff) == + (map->offset & 0xffffffff)) + return entry; default: /* Make gcc happy */ ; } From dab104a73694b06fe4a162cb39d678716da62a67 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Thu, 2 Jun 2011 14:09:32 +1000 Subject: [PATCH 360/595] m68knommu: fix linker script exported name sections The recent commit titled "module: Sort exported symbols" (f02e8a65) changed the exported symbol name sections. Bring the m68knommu linker script into line with those changes - including the sorting of the symbol names. Signed-off-by: Greg Ungerer --- arch/m68k/kernel/vmlinux.lds_no.S | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/m68k/kernel/vmlinux.lds_no.S b/arch/m68k/kernel/vmlinux.lds_no.S index f4d715cdca0e..7dc4087a9545 100644 --- a/arch/m68k/kernel/vmlinux.lds_no.S +++ b/arch/m68k/kernel/vmlinux.lds_no.S @@ -84,52 +84,52 @@ SECTIONS { /* Kernel symbol table: Normal symbols */ . = ALIGN(4); __start___ksymtab = .; - *(__ksymtab) + *(SORT(___ksymtab+*)) __stop___ksymtab = .; /* Kernel symbol table: GPL-only symbols */ __start___ksymtab_gpl = .; - *(__ksymtab_gpl) + *(SORT(___ksymtab_gpl+*)) __stop___ksymtab_gpl = .; /* Kernel symbol table: Normal unused symbols */ __start___ksymtab_unused = .; - *(__ksymtab_unused) + *(SORT(___ksymtab_unused+*)) __stop___ksymtab_unused = .; /* Kernel symbol table: GPL-only unused symbols */ __start___ksymtab_unused_gpl = .; - *(__ksymtab_unused_gpl) + *(SORT(___ksymtab_unused_gpl+*)) __stop___ksymtab_unused_gpl = .; /* Kernel symbol table: GPL-future symbols */ __start___ksymtab_gpl_future = .; - *(__ksymtab_gpl_future) + *(SORT(___ksymtab_gpl_future+*)) __stop___ksymtab_gpl_future = .; /* Kernel symbol table: Normal symbols */ __start___kcrctab = .; - *(__kcrctab) + *(SORT(___kcrctab+*)) __stop___kcrctab = .; /* Kernel symbol table: GPL-only symbols */ __start___kcrctab_gpl = .; - *(__kcrctab_gpl) + *(SORT(___kcrctab_gpl+*)) __stop___kcrctab_gpl = .; /* Kernel symbol table: Normal unused symbols */ __start___kcrctab_unused = .; - *(__kcrctab_unused) + *(SORT(___kcrctab_unused+*)) __stop___kcrctab_unused = .; /* Kernel symbol table: GPL-only unused symbols */ __start___kcrctab_unused_gpl = .; - *(__kcrctab_unused_gpl) + *(SORT(___kcrctab_unused_gpl+*)) __stop___kcrctab_unused_gpl = .; /* Kernel symbol table: GPL-future symbols */ __start___kcrctab_gpl_future = .; - *(__kcrctab_gpl_future) + *(SORT(___kcrctab_gpl_future+*)) __stop___kcrctab_gpl_future = .; /* Kernel symbol table: strings */ From 62356725987fa44bbebeb656b2a0d8c803e32ef2 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Thu, 2 Jun 2011 15:50:48 +1000 Subject: [PATCH 361/595] m68knommu: create config options for CPU classes There are 3 families of CPU core types that we support in the m68knommu architecture branch. They are . traditional 68000 . CPU32 (a 68020 core derivative without MMU or bitfield instructions) . ColdFire It will be useful going forward to have a CONFIG_ option defined for each type. We already have one for ColdFire (CONFIG_COLDFIRE), so add for the other 2 families, CONFIG_M68000 and CONFIG_MCPU32. Signed-off-by: Greg Ungerer --- arch/m68k/Kconfig.nommu | 52 +++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/arch/m68k/Kconfig.nommu b/arch/m68k/Kconfig.nommu index fc98f9b9d4d2..b004dc1b1710 100644 --- a/arch/m68k/Kconfig.nommu +++ b/arch/m68k/Kconfig.nommu @@ -14,6 +14,33 @@ config GENERIC_CLOCKEVENTS bool default n +config M68000 + bool + help + The Freescale (was Motorola) 68000 CPU is the first generation of + the well known M68K family of processors. The CPU core as well as + being available as a stand alone CPU was also used in many + System-On-Chip devices (eg 68328, 68302, etc). It does not contain + a paging MMU. + +config MCPU32 + bool + help + The Freescale (was then Motorola) CPU32 is a CPU core that is + based on the 68020 processor. For the most part it is used in + System-On-Chip parts, and does not contain a paging MMU. + +config COLDFIRE + bool + select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB + help + The Freescale ColdFire family of processors is a modern derivitive + of the 68000 processor family. They are mainly targeted at embedded + applications, and are all System-On-Chip (SOC) devices, as opposed + to stand alone CPUs. They implement a subset of the original 68000 + processor instruction set. + config COLDFIRE_SW_A7 bool default n @@ -36,26 +63,31 @@ choice config M68328 bool "MC68328" + select M68000 help Motorola 68328 processor support. config M68EZ328 bool "MC68EZ328" + select M68000 help Motorola 68EX328 processor support. config M68VZ328 bool "MC68VZ328" + select M68000 help Motorola 68VZ328 processor support. config M68360 bool "MC68360" + select MCPU32 help Motorola 68360 processor support. config M5206 bool "MCF5206" + select COLDFIRE select COLDFIRE_SW_A7 select HAVE_MBAR help @@ -63,6 +95,7 @@ config M5206 config M5206e bool "MCF5206e" + select COLDFIRE select COLDFIRE_SW_A7 select HAVE_MBAR help @@ -70,6 +103,7 @@ config M5206e config M520x bool "MCF520x" + select COLDFIRE select GENERIC_CLOCKEVENTS select HAVE_CACHE_SPLIT help @@ -77,6 +111,7 @@ config M520x config M523x bool "MCF523x" + select COLDFIRE select GENERIC_CLOCKEVENTS select HAVE_CACHE_SPLIT select HAVE_IPSBAR @@ -85,6 +120,7 @@ config M523x config M5249 bool "MCF5249" + select COLDFIRE select COLDFIRE_SW_A7 select HAVE_MBAR help @@ -92,6 +128,7 @@ config M5249 config M5271 bool "MCF5271" + select COLDFIRE select HAVE_CACHE_SPLIT select HAVE_IPSBAR help @@ -99,6 +136,7 @@ config M5271 config M5272 bool "MCF5272" + select COLDFIRE select COLDFIRE_SW_A7 select HAVE_MBAR help @@ -106,6 +144,7 @@ config M5272 config M5275 bool "MCF5275" + select COLDFIRE select HAVE_CACHE_SPLIT select HAVE_IPSBAR help @@ -113,6 +152,7 @@ config M5275 config M528x bool "MCF528x" + select COLDFIRE select GENERIC_CLOCKEVENTS select HAVE_CACHE_SPLIT select HAVE_IPSBAR @@ -121,6 +161,7 @@ config M528x config M5307 bool "MCF5307" + select COLDFIRE select COLDFIRE_SW_A7 select HAVE_CACHE_CB select HAVE_MBAR @@ -129,12 +170,14 @@ config M5307 config M532x bool "MCF532x" + select COLDFIRE select HAVE_CACHE_CB help Freescale (Motorola) ColdFire 532x processor support. config M5407 bool "MCF5407" + select COLDFIRE select COLDFIRE_SW_A7 select HAVE_CACHE_CB select HAVE_MBAR @@ -143,6 +186,7 @@ config M5407 config M547x bool "MCF547x" + select COLDFIRE select HAVE_CACHE_CB select HAVE_MBAR help @@ -150,6 +194,7 @@ config M547x config M548x bool "MCF548x" + select COLDFIRE select HAVE_CACHE_CB select HAVE_MBAR help @@ -168,13 +213,6 @@ config M54xx depends on (M548x || M547x) default y -config COLDFIRE - bool - depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407 || M54xx) - select GENERIC_GPIO - select ARCH_REQUIRE_GPIOLIB - default y - config CLOCK_SET bool "Enable setting the CPU clock frequency" default n From 734c3ce3bd4d51c932893b9f6d32b9ded31acdff Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Thu, 2 Jun 2011 16:07:33 +1000 Subject: [PATCH 362/595] m68k: use kernel processor defines for conditional optimizations Older m68k-linux compilers will include pre-defined symbols that confuse what processor it is being targeted for. For example gcc-4.1.2 will pre-define __mc68020__ even if you specify the target processor as -m68000 on the gcc command line. Newer versions of gcc have this corrected. In a few places the m68k code uses defined(__mc68020__) for optimizations that include instructions that are specific to the CPU 68020 and above. When compiling with older compilers this will be true even when we have selected to compile for the older 68000 processors. Switch to using the kernel processor defines, CONFIG_M68020 and friends. Signed-off-by: Greg Ungerer --- arch/m68k/kernel/m68k_ksyms.c | 3 +-- arch/m68k/lib/memcpy.c | 9 ++++----- arch/m68k/lib/memset.c | 9 ++++----- arch/m68k/lib/muldi3.c | 21 ++++++++++----------- 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index 33f82769547c..1b7a14d1a000 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -14,8 +14,7 @@ EXPORT_SYMBOL(__ashrdi3); EXPORT_SYMBOL(__lshrdi3); EXPORT_SYMBOL(__muldi3); -#if !defined(__mc68020__) && !defined(__mc68030__) && \ - !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcpu32__) +#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) /* * Simpler 68k and ColdFire parts also need a few other gcc functions. */ diff --git a/arch/m68k/lib/memcpy.c b/arch/m68k/lib/memcpy.c index 62182c81e91c..064889316974 100644 --- a/arch/m68k/lib/memcpy.c +++ b/arch/m68k/lib/memcpy.c @@ -34,8 +34,10 @@ void *memcpy(void *to, const void *from, size_t n) if (temp) { long *lto = to; const long *lfrom = from; -#if defined(__mc68020__) || defined(__mc68030__) || \ - defined(__mc68040__) || defined(__mc68060__) || defined(__mcpu32__) +#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) + for (; temp; temp--) + *lto++ = *lfrom++; +#else asm volatile ( " movel %2,%3\n" " andw #7,%3\n" @@ -56,9 +58,6 @@ void *memcpy(void *to, const void *from, size_t n) " jpl 4b" : "=a" (lfrom), "=a" (lto), "=d" (temp), "=&d" (temp1) : "0" (lfrom), "1" (lto), "2" (temp)); -#else - for (; temp; temp--) - *lto++ = *lfrom++; #endif to = lto; from = lfrom; diff --git a/arch/m68k/lib/memset.c b/arch/m68k/lib/memset.c index f649e6a2e644..8a7639f0a2fe 100644 --- a/arch/m68k/lib/memset.c +++ b/arch/m68k/lib/memset.c @@ -32,8 +32,10 @@ void *memset(void *s, int c, size_t count) temp = count >> 2; if (temp) { long *ls = s; -#if defined(__mc68020__) || defined(__mc68030__) || \ - defined(__mc68040__) || defined(__mc68060__) || defined(__mcpu32__) +#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) + for (; temp; temp--) + *ls++ = c; +#else size_t temp1; asm volatile ( " movel %1,%2\n" @@ -55,9 +57,6 @@ void *memset(void *s, int c, size_t count) " jpl 1b" : "=a" (ls), "=d" (temp), "=&d" (temp1) : "d" (c), "0" (ls), "1" (temp)); -#else - for (; temp; temp--) - *ls++ = c; #endif s = ls; } diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c index 079bafca073e..79e928a525d0 100644 --- a/arch/m68k/lib/muldi3.c +++ b/arch/m68k/lib/muldi3.c @@ -19,17 +19,7 @@ along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#if defined(__mc68020__) || defined(__mc68030__) || \ - defined(__mc68040__) || defined(__mc68060__) || defined(__mcpu32__) - -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("mulu%.l %3,%1:%0" \ - : "=d" ((USItype)(w0)), \ - "=d" ((USItype)(w1)) \ - : "%0" ((USItype)(u)), \ - "dmi" ((USItype)(v))) - -#else +#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) #define SI_TYPE_SIZE 32 #define __BITS4 (SI_TYPE_SIZE / 4) @@ -61,6 +51,15 @@ Boston, MA 02111-1307, USA. */ (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ } while (0) +#else + +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "dmi" ((USItype)(v))) + #endif #define __umulsidi3(u, v) \ From 9b2dc8b665932a8e681a7ab3237f60475e75e161 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 13 Jun 2011 14:48:22 +0900 Subject: [PATCH 363/595] md/raid5: fix raid5_set_bi_hw_segments The @bio->bi_phys_segments consists of active stripes count in the lower 16 bits and processed stripes count in the upper 16 bits. So logical-OR operator should be bitwise one. This bug has been present since 2.6.27 and the fix is suitable for any -stable kernel since then. Fortunately the bad code is only used on error paths and is relatively unlikely to be hit. Cc: stable@kernel.org Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown --- drivers/md/raid5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index f9d2fbc64977..af8a9a89e4da 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -129,7 +129,7 @@ static inline int raid5_dec_bi_hw_segments(struct bio *bio) static inline void raid5_set_bi_hw_segments(struct bio *bio, unsigned int cnt) { - bio->bi_phys_segments = raid5_bi_phys_segments(bio) || (cnt << 16); + bio->bi_phys_segments = raid5_bi_phys_segments(bio) | (cnt << 16); } /* Find first data disk in a raid6 stripe */ From b062962edb086011e94ec4d9eb3f6a6d814f2a8f Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 14 Jun 2011 14:20:19 +1000 Subject: [PATCH 364/595] md/raid5: fix FUA request handling in ops_run_io() Commit e9c7469bb4f5 ("md: implment REQ_FLUSH/FUA support") introduced R5_WantFUA flag and set rw to WRITE_FUA in that case. However remaining code still checks whether rw is exactly same as WRITE or not, so FUAed-write ends up with being treated as READ. Fix it. This bug has been present since 2.6.37 and the fix is suitable for any -stable kernel since then. It is not clear why this has not caused more problems. Cc: Tejun Heo Cc: stable@kernel.org Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown --- drivers/md/raid5.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index af8a9a89e4da..b7dcc677dda4 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -514,7 +514,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) bi = &sh->dev[i].req; bi->bi_rw = rw; - if (rw == WRITE) + if (rw & WRITE) bi->bi_end_io = raid5_end_write_request; else bi->bi_end_io = raid5_end_read_request; @@ -548,13 +548,13 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) bi->bi_io_vec[0].bv_offset = 0; bi->bi_size = STRIPE_SIZE; bi->bi_next = NULL; - if (rw == WRITE && + if ((rw & WRITE) && test_bit(R5_ReWrite, &sh->dev[i].flags)) atomic_add(STRIPE_SECTORS, &rdev->corrected_errors); generic_make_request(bi); } else { - if (rw == WRITE) + if (rw & WRITE) set_bit(STRIPE_DEGRADED, &sh->state); pr_debug("skip op %ld on disc %d for sector %llu\n", bi->bi_rw, i, (unsigned long long)sh->sector); From fcde90759a985d8bfa4391346a821cc12fc16207 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 14 Jun 2011 14:23:57 +1000 Subject: [PATCH 365/595] md/raid5: remove unusual use of bio_iovec_idx() In the bio_for_each_segment loop, bvl always points current bio_vec, so the same as bio_iovec_idx(, i). Let's get rid of it. Cc: Dan Williams Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown --- drivers/md/raid5.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index b7dcc677dda4..b72edf35ec54 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -585,7 +585,7 @@ async_copy_data(int frombio, struct bio *bio, struct page *page, init_async_submit(&submit, flags, tx, NULL, NULL, NULL); bio_for_each_segment(bvl, bio, i) { - int len = bio_iovec_idx(bio, i)->bv_len; + int len = bvl->bv_len; int clen; int b_offset = 0; @@ -601,8 +601,8 @@ async_copy_data(int frombio, struct bio *bio, struct page *page, clen = len; if (clen > 0) { - b_offset += bio_iovec_idx(bio, i)->bv_offset; - bio_page = bio_iovec_idx(bio, i)->bv_page; + b_offset += bvl->bv_offset; + bio_page = bvl->bv_page; if (frombio) tx = async_memcpy(page, bio_page, page_offset, b_offset, clen, &submit); From 4e78c724d47e2342aa8fde61f6b8536f662f795f Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 13 Jun 2011 13:49:11 +0900 Subject: [PATCH 366/595] TOMOYO: Fix oops in tomoyo_mount_acl(). In tomoyo_mount_acl() since 2.6.36, kern_path() was called without checking dev_name != NULL. As a result, an unprivileged user can trigger oops by issuing mount(NULL, "/", "ext3", 0, NULL) request. Fix this by checking dev_name != NULL before calling kern_path(dev_name). Signed-off-by: Tetsuo Handa Cc: stable@kernel.org Signed-off-by: James Morris --- security/tomoyo/mount.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 162a864dba24..9fc2e15841c9 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -138,7 +138,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, } if (need_dev) { /* Get mount point or device file. */ - if (kern_path(dev_name, LOOKUP_FOLLOW, &path)) { + if (!dev_name || kern_path(dev_name, LOOKUP_FOLLOW, &path)) { error = -ENOENT; goto out; } From 37f7ec38ea5c31180461f82e895e13fdd549b595 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 13 Jun 2011 23:52:02 +0200 Subject: [PATCH 367/595] ALSA: 6fire: Fix double-free bug in usb6fire_fw_ezusb_upload() We have a double-free bug in sound/usb/6fire/firmware.c::usb6fire_fw_ezusb_upload(). We already call release_firmware(fw) on line 258, so when we then do it again after usb6fire_fw_ezusb_write() returns <0, we have a double-free. Easily fixed by just removing the last call to release_firmware(). Signed-off-by: Jesper Juhl Signed-off-by: Takashi Iwai --- sound/usb/6fire/firmware.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c index a91719d5918b..1e3ae3327dd3 100644 --- a/sound/usb/6fire/firmware.c +++ b/sound/usb/6fire/firmware.c @@ -270,7 +270,6 @@ static int usb6fire_fw_ezusb_upload( data = 0x00; /* resume ezusb cpu */ ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1); if (ret < 0) { - release_firmware(fw); snd_printk(KERN_ERR PREFIX "unable to upload ezusb " "firmware %s: end message.\n", fwname); return ret; From dcee0bb713d0ba0d32c5ce6fe0c5aa22e6fc274a Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 9 Jun 2011 06:35:08 +0000 Subject: [PATCH 368/595] dmaengine: shdma: SH_DMAC_MAX_CHANNELS message fix Fix the recently added SH_DMAC_MAX_CHANNELS handling code in 300e5f9 dmaengine: shdma: Fix SH_DMAC_MAX_CHANNELS handling Without this fix the shdma driver outputs silly messages in case SH_DMAC_MAX_CHANNELS happens to match the platform data: sh-dma-engine sh-dma-engine.0: Attempting to register 20 DMA channels when a max imum of 20 are supported. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/dma/shdma.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 2a638f9f09a2..028330044201 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -1221,6 +1221,11 @@ static int __init sh_dmae_probe(struct platform_device *pdev) } else { do { for (i = chanirq_res->start; i <= chanirq_res->end; i++) { + if (irq_cnt >= SH_DMAC_MAX_CHANNELS) { + irq_cap = 1; + break; + } + if ((errirq_res->flags & IORESOURCE_BITS) == IORESOURCE_IRQ_SHAREABLE) chan_flag[irq_cnt] = IRQF_SHARED; @@ -1230,15 +1235,11 @@ static int __init sh_dmae_probe(struct platform_device *pdev) "Found IRQ %d for channel %d\n", i, irq_cnt); chan_irq[irq_cnt++] = i; - - if (irq_cnt >= SH_DMAC_MAX_CHANNELS) - break; } - if (irq_cnt >= SH_DMAC_MAX_CHANNELS) { - irq_cap = 1; + if (irq_cnt >= SH_DMAC_MAX_CHANNELS) break; - } + chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, ++irqres); } while (irq_cnt < pdata->channel_num && chanirq_res); From 5294206053f9ab522fbd6bfde1cf7629dc564d5e Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 9 Jun 2011 09:02:25 +0000 Subject: [PATCH 369/595] ARM: mach-shmobile: AG5EVM SDHI1 platform data update Add a flag for SDHI1 to enable SDIO IRQ, and remove DMA Engine slave id:s to disable DMA as a workaround. Tested on sh73a0/AG5EVM with a BCM4318-based SDIO card. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-ag5evm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index c95258c274c1..1e2aba23e0d6 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -382,10 +382,8 @@ void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state) } static struct sh_mobile_sdhi_info sh_sdhi1_platdata = { - .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, - .dma_slave_rx = SHDMA_SLAVE_SDHI1_RX, .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE, - .tmio_caps = MMC_CAP_NONREMOVABLE, + .tmio_caps = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ, .tmio_ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, .set_pwr = ag5evm_sdhi1_set_pwr, }; From e2a53b7c5bcfb63114c02c32117ed62eae463dc2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 9 Jun 2011 07:03:37 +0000 Subject: [PATCH 370/595] ARM: mach-shmobile: Mackerel USB platform data update This patch updates the board specific USB support code for the sh7372 Mackerel board. With this patch applied port CN22 is driven by the recently added renesas_usbhs driver using the first USB controller included in sh7372 aka USBHS0. Hotplugging of USBHS0 unfortunately has to be handled by software polling. The sh7372 SoC itself obviously supports hotplug notification by IRQ but on the Mackerel board this IRQ happens to be used for the touch screen. Also fix the pinmux configuration to avoid setting up unused pins and fix minor spelling errors. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-mackerel.c | 225 +++++++++++++++++------- 1 file changed, 160 insertions(+), 65 deletions(-) diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 776f20560e72..1037bd2ffdb9 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -126,7 +126,7 @@ * ------+--------------------+--------------------+------- * IRQ0 | ICR1A.IRQ0SA=0010 | SDHI2 card detect | Low * IRQ6 | ICR1A.IRQ6SA=0011 | Ether(LAN9220) | High - * IRQ7 | ICR1A.IRQ7SA=0010 | LCD Tuch Panel | Low + * IRQ7 | ICR1A.IRQ7SA=0010 | LCD Touch Panel | Low * IRQ8 | ICR2A.IRQ8SA=0010 | MMC/SD card detect | Low * IRQ9 | ICR2A.IRQ9SA=0010 | KEY(TCA6408) | Low * IRQ21 | ICR4A.IRQ21SA=0011 | Sensor(ADXL345) | High @@ -165,10 +165,10 @@ * USB1 can become Host by r8a66597, and become Function by renesas_usbhs. * But don't select both drivers in same time. * These uses same IRQ number for request_irq(), and aren't supporting - * IRQF_SHARD / IORESOURCE_IRQ_SHAREABLE. + * IRQF_SHARED / IORESOURCE_IRQ_SHAREABLE. * * Actually these are old/new version of USB driver. - * This mean its register will be broken if it supports SHARD IRQ, + * This mean its register will be broken if it supports shared IRQ, */ /* @@ -562,7 +562,136 @@ static void __init hdmi_init_pm_clock(void) clk_put(hdmi_ick); } -/* USB1 (Host) */ +/* USBHS0 is connected to CN22 which takes a USB Mini-B plug + * + * The sh7372 SoC has IRQ7 set aside for USBHS0 hotplug, + * but on this particular board IRQ7 is already used by + * the touch screen. This leaves us with software polling. + */ +#define USBHS0_POLL_INTERVAL (HZ * 5) + +struct usbhs_private { + unsigned int usbphyaddr; + unsigned int usbcrcaddr; + struct renesas_usbhs_platform_info info; + struct delayed_work work; + struct platform_device *pdev; +}; + +#define usbhs_get_priv(pdev) \ + container_of(renesas_usbhs_get_info(pdev), \ + struct usbhs_private, info) + +#define usbhs_is_connected(priv) \ + (!((1 << 7) & __raw_readw(priv->usbcrcaddr))) + +static int usbhs_get_vbus(struct platform_device *pdev) +{ + return usbhs_is_connected(usbhs_get_priv(pdev)); +} + +static void usbhs_phy_reset(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + /* init phy */ + __raw_writew(0x8a0a, priv->usbcrcaddr); +} + +static int usbhs0_get_id(struct platform_device *pdev) +{ + return USBHS_GADGET; +} + +static void usbhs0_work_function(struct work_struct *work) +{ + struct usbhs_private *priv = container_of(work, struct usbhs_private, + work.work); + + renesas_usbhs_call_notify_hotplug(priv->pdev); + schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL); +} + +static int usbhs0_hardware_init(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + priv->pdev = pdev; + INIT_DELAYED_WORK(&priv->work, usbhs0_work_function); + schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL); + return 0; +} + +static void usbhs0_hardware_exit(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + cancel_delayed_work_sync(&priv->work); +} + +static u32 usbhs0_pipe_cfg[] = { + USB_ENDPOINT_XFER_CONTROL, + USB_ENDPOINT_XFER_ISOC, + USB_ENDPOINT_XFER_ISOC, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_BULK, +}; + +static struct usbhs_private usbhs0_private = { + .usbcrcaddr = 0xe605810c, /* USBCR2 */ + .info = { + .platform_callback = { + .hardware_init = usbhs0_hardware_init, + .hardware_exit = usbhs0_hardware_exit, + .phy_reset = usbhs_phy_reset, + .get_id = usbhs0_get_id, + .get_vbus = usbhs_get_vbus, + }, + .driver_param = { + .buswait_bwait = 4, + .pipe_type = usbhs0_pipe_cfg, + .pipe_size = ARRAY_SIZE(usbhs0_pipe_cfg), + }, + }, +}; + +static struct resource usbhs0_resources[] = { + [0] = { + .name = "USBHS0", + .start = 0xe6890000, + .end = 0xe68900e6 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = evt2irq(0x1ca0) /* USB0_USB0I0 */, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usbhs0_device = { + .name = "renesas_usbhs", + .id = 0, + .dev = { + .platform_data = &usbhs0_private.info, + }, + .num_resources = ARRAY_SIZE(usbhs0_resources), + .resource = usbhs0_resources, +}; + +/* USBHS1 is connected to CN31 which takes a USB Mini-AB plug + * + * Use J30 to select between Host and Function. This setting + * can however not be detected by software. Hotplug of USBHS1 + * is provided via IRQ8. + */ +#define IRQ8 evt2irq(0x0300) + +/* USBHS1 USB Host support via r8a66597_hcd */ static void usb1_host_port_power(int port, int power) { if (!power) /* only power-on is supported for now */ @@ -579,9 +708,9 @@ static struct r8a66597_platdata usb1_host_data = { static struct resource usb1_host_resources[] = { [0] = { - .name = "USBHS", - .start = 0xE68B0000, - .end = 0xE68B00E6 - 1, + .name = "USBHS1", + .start = 0xe68b0000, + .end = 0xe68b00e6 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -602,37 +731,14 @@ static struct platform_device usb1_host_device = { .resource = usb1_host_resources, }; -/* USB1 (Function) */ +/* USBHS1 USB Function support via renesas_usbhs */ + #define USB_PHY_MODE (1 << 4) #define USB_PHY_INT_EN ((1 << 3) | (1 << 2)) #define USB_PHY_ON (1 << 1) #define USB_PHY_OFF (1 << 0) #define USB_PHY_INT_CLR (USB_PHY_ON | USB_PHY_OFF) -struct usbhs_private { - unsigned int irq; - unsigned int usbphyaddr; - unsigned int usbcrcaddr; - struct renesas_usbhs_platform_info info; -}; - -#define usbhs_get_priv(pdev) \ - container_of(renesas_usbhs_get_info(pdev), \ - struct usbhs_private, info) - -#define usbhs_is_connected(priv) \ - (!((1 << 7) & __raw_readw(priv->usbcrcaddr))) - -static int usbhs1_get_id(struct platform_device *pdev) -{ - return USBHS_GADGET; -} - -static int usbhs1_get_vbus(struct platform_device *pdev) -{ - return usbhs_is_connected(usbhs_get_priv(pdev)); -} - static irqreturn_t usbhs1_interrupt(int irq, void *data) { struct platform_device *pdev = data; @@ -654,12 +760,10 @@ static int usbhs1_hardware_init(struct platform_device *pdev) struct usbhs_private *priv = usbhs_get_priv(pdev); int ret; - irq_set_irq_type(priv->irq, IRQ_TYPE_LEVEL_HIGH); - /* clear interrupt status */ __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr); - ret = request_irq(priv->irq, usbhs1_interrupt, 0, + ret = request_irq(IRQ8, usbhs1_interrupt, IRQF_TRIGGER_HIGH, dev_name(&pdev->dev), pdev); if (ret) { dev_err(&pdev->dev, "request_irq err\n"); @@ -679,15 +783,7 @@ static void usbhs1_hardware_exit(struct platform_device *pdev) /* clear interrupt status */ __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr); - free_irq(priv->irq, pdev); -} - -static void usbhs1_phy_reset(struct platform_device *pdev) -{ - struct usbhs_private *priv = usbhs_get_priv(pdev); - - /* init phy */ - __raw_writew(0x8a0a, priv->usbcrcaddr); + free_irq(IRQ8, pdev); } static u32 usbhs1_pipe_cfg[] = { @@ -710,16 +806,14 @@ static u32 usbhs1_pipe_cfg[] = { }; static struct usbhs_private usbhs1_private = { - .irq = evt2irq(0x0300), /* IRQ8 */ - .usbphyaddr = 0xE60581E2, /* USBPHY1INTAP */ - .usbcrcaddr = 0xE6058130, /* USBCR4 */ + .usbphyaddr = 0xe60581e2, /* USBPHY1INTAP */ + .usbcrcaddr = 0xe6058130, /* USBCR4 */ .info = { .platform_callback = { .hardware_init = usbhs1_hardware_init, .hardware_exit = usbhs1_hardware_exit, - .phy_reset = usbhs1_phy_reset, - .get_id = usbhs1_get_id, - .get_vbus = usbhs1_get_vbus, + .phy_reset = usbhs_phy_reset, + .get_vbus = usbhs_get_vbus, }, .driver_param = { .buswait_bwait = 4, @@ -731,9 +825,9 @@ static struct usbhs_private usbhs1_private = { static struct resource usbhs1_resources[] = { [0] = { - .name = "USBHS", - .start = 0xE68B0000, - .end = 0xE68B00E6 - 1, + .name = "USBHS1", + .start = 0xe68b0000, + .end = 0xe68b00e6 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -752,7 +846,6 @@ static struct platform_device usbhs1_device = { .resource = usbhs1_resources, }; - /* LED */ static struct gpio_led mackerel_leds[] = { { @@ -1203,6 +1296,7 @@ static struct platform_device *mackerel_devices[] __initdata = { &nor_flash_device, &smc911x_device, &lcdc_device, + &usbhs0_device, &usb1_host_device, &usbhs1_device, &leds_device, @@ -1301,6 +1395,7 @@ static void __init mackerel_map_io(void) #define GPIO_PORT9CR 0xE6051009 #define GPIO_PORT10CR 0xE605100A +#define GPIO_PORT167CR 0xE60520A7 #define GPIO_PORT168CR 0xE60520A8 #define SRCR4 0xe61580bc #define USCCR1 0xE6058144 @@ -1354,17 +1449,17 @@ static void __init mackerel_init(void) gpio_request(GPIO_PORT151, NULL); /* LCDDON */ gpio_direction_output(GPIO_PORT151, 1); - /* USB enable */ - gpio_request(GPIO_FN_VBUS0_1, NULL); - gpio_request(GPIO_FN_IDIN_1_18, NULL); - gpio_request(GPIO_FN_PWEN_1_115, NULL); - gpio_request(GPIO_FN_OVCN_1_114, NULL); - gpio_request(GPIO_FN_EXTLP_1, NULL); - gpio_request(GPIO_FN_OVCN2_1, NULL); - gpio_pull_down(GPIO_PORT168CR); - - /* setup USB phy */ - __raw_writew(0x8a0a, 0xE6058130); /* USBCR4 */ + /* USBHS0 */ + gpio_request(GPIO_FN_VBUS0_0, NULL); + gpio_pull_down(GPIO_PORT168CR); /* VBUS0_0 pull down */ + + /* USBHS1 */ + gpio_request(GPIO_FN_VBUS0_1, NULL); + gpio_pull_down(GPIO_PORT167CR); /* VBUS0_1 pull down */ + gpio_request(GPIO_FN_IDIN_1_113, NULL); + + /* USB phy tweak to make the r8a66597_hcd host driver work */ + __raw_writew(0x8a0a, 0xe6058130); /* USBCR4 */ /* enable FSI2 port A (ak4643) */ gpio_request(GPIO_FN_FSIAIBT, NULL); From 485b2ab55477f46cd1f7d16ba9f87cd074051811 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 9 Jun 2011 06:20:03 +0000 Subject: [PATCH 371/595] ARM: mach-shmobile: sh73a0 gic_arch_extn.irq_set_wake() fix Initialize ->irq_set_wake() in gic_arch_extn to unbreak wake up from the KEYSC device on AG5EVM in case of Suspend-to-RAM. Without this patch "echo mem > /sys/power/state" and a key press results in the following message on resume: WARNING: at kernel/irq/manage.c:507 irq_set_irq_wake+0x7c/0xd8() Unbalanced IRQ 103 wake disable Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/intc-sh73a0.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c index 5d0e1503ece6..a911a60e7719 100644 --- a/arch/arm/mach-shmobile/intc-sh73a0.c +++ b/arch/arm/mach-shmobile/intc-sh73a0.c @@ -250,6 +250,11 @@ static irqreturn_t sh73a0_intcs_demux(int irq, void *dev_id) return IRQ_HANDLED; } +static int sh73a0_set_wake(struct irq_data *data, unsigned int on) +{ + return 0; /* always allow wakeup */ +} + void __init sh73a0_init_irq(void) { void __iomem *gic_dist_base = __io(0xf0001000); @@ -257,6 +262,7 @@ void __init sh73a0_init_irq(void) void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); gic_init(0, 29, gic_dist_base, gic_cpu_base); + gic_arch_extn.irq_set_wake = sh73a0_set_wake; register_intc_controller(&intcs_desc); From 311057250e87f7470ccca8bd68bf9e67f6b6db09 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 14 Jun 2011 15:07:06 +0900 Subject: [PATCH 372/595] ARM: mach-shmobile: Correct SCIF port types for SH7367. While SH7377 and others were updated to properly use SCIFA/B port types, SH7367 was left behind. Fix it up accordingly. Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/setup-sh7367.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-shmobile/setup-sh7367.c b/arch/arm/mach-shmobile/setup-sh7367.c index 2c10190dbb55..e546017f15de 100644 --- a/arch/arm/mach-shmobile/setup-sh7367.c +++ b/arch/arm/mach-shmobile/setup-sh7367.c @@ -38,7 +38,7 @@ static struct plat_sci_port scif0_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc00), evt2irq(0xc00), evt2irq(0xc00), evt2irq(0xc00) }, }; @@ -57,7 +57,7 @@ static struct plat_sci_port scif1_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc20), evt2irq(0xc20), evt2irq(0xc20), evt2irq(0xc20) }, }; @@ -76,7 +76,7 @@ static struct plat_sci_port scif2_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc40), evt2irq(0xc40), evt2irq(0xc40), evt2irq(0xc40) }, }; @@ -95,7 +95,7 @@ static struct plat_sci_port scif3_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xc60), evt2irq(0xc60), evt2irq(0xc60), evt2irq(0xc60) }, }; @@ -114,7 +114,7 @@ static struct plat_sci_port scif4_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xd20), evt2irq(0xd20), evt2irq(0xd20), evt2irq(0xd20) }, }; @@ -133,7 +133,7 @@ static struct plat_sci_port scif5_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFA, .irqs = { evt2irq(0xd40), evt2irq(0xd40), evt2irq(0xd40), evt2irq(0xd40) }, }; @@ -152,7 +152,7 @@ static struct plat_sci_port scif6_platform_data = { .flags = UPF_BOOT_AUTOCONF, .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, - .type = PORT_SCIF, + .type = PORT_SCIFB, .irqs = { evt2irq(0xd60), evt2irq(0xd60), evt2irq(0xd60), evt2irq(0xd60) }, }; From ca2585afa013ec2cf99a48e46d6b82df2e240493 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Jun 2011 08:14:32 +0200 Subject: [PATCH 373/595] ALSA: hda - Fix missing static inline to beep dummy function The commit 2308f4add3de9f6c9c9f02e49461e94d84bb200a missed static inline thus it resulted in multiple-definitions error at linking. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index 4967eabe774e..55f0647458c7 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -54,7 +54,7 @@ static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) { return 0; } -void snd_hda_detach_beep_device(struct hda_codec *codec) +static inline void snd_hda_detach_beep_device(struct hda_codec *codec) { } #endif From 583af252ab07cd1e8721878463da5b7016c18fdc Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 13 Jun 2011 04:42:15 +0000 Subject: [PATCH 374/595] drivers: sh: resume enabled clocks fix Extend the SH / SH-Mobile ARM clock framework to only resume clocks that have been enabled. Without this fix divide-by-zero is triggering on sh7372 FSIDIV during system wide resume of Suspend-to-RAM. Signed-off-by: Magnus Damm Reviewed-by: Simon Horman Signed-off-by: Paul Mundt --- drivers/sh/clk/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c index 4f64183b27fa..7e9c39951ecb 100644 --- a/drivers/sh/clk/core.c +++ b/drivers/sh/clk/core.c @@ -635,7 +635,7 @@ static void clks_core_resume(void) struct clk *clkp; list_for_each_entry(clkp, &clock_list, node) { - if (likely(clkp->ops)) { + if (likely(clkp->usecount && clkp->ops)) { unsigned long rate = clkp->rate; if (likely(clkp->ops->set_parent)) From 201fbceb258650157fcc4fd746abcdd3a571eada Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Fri, 10 Jun 2011 13:10:48 +0000 Subject: [PATCH 375/595] sh, exec: remove redundant set_fs(USER_DS) The address limit is already set in flush_old_exec() so those calls to set_fs(USER_DS) are redundant. Signed-off-by: Mathias Krause Signed-off-by: Paul Mundt --- arch/sh/include/asm/processor_64.h | 1 - arch/sh/kernel/process_32.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h index 2a541ddb5a1b..e25c4c7d6b63 100644 --- a/arch/sh/include/asm/processor_64.h +++ b/arch/sh/include/asm/processor_64.h @@ -150,7 +150,6 @@ struct thread_struct { #define SR_USER (SR_MMU | SR_FD) #define start_thread(_regs, new_pc, new_sp) \ - set_fs(USER_DS); \ _regs->sr = SR_USER; /* User mode. */ \ _regs->pc = new_pc - 4; /* Compensate syscall exit */ \ _regs->pc |= 1; /* Set SHmedia ! */ \ diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index b473f0c06fbc..aaf6d59c2012 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -102,8 +102,6 @@ EXPORT_SYMBOL(kernel_thread); void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned long new_sp) { - set_fs(USER_DS); - regs->pr = 0; regs->sr = SR_FD; regs->pc = new_pc; From e6b8480cdf27953c3d13e6e34dd075f8287b02f0 Mon Sep 17 00:00:00 2001 From: Wanlong Gao Date: Sun, 12 Jun 2011 10:52:33 +0000 Subject: [PATCH 376/595] efifb: Fix call to wrong unregister function platform_device_unregister() needs to unregister the device, not the driver. Signed-off-by: Wanlong Gao Signed-off-by: Maarten Lankhorst Acked-by: Andy Lutomirski Signed-off-by: Paul Mundt --- drivers/video/efifb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 69c49dfce9cf..784139aed079 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -541,7 +541,7 @@ static int __init efifb_init(void) */ ret = platform_driver_probe(&efifb_driver, efifb_probe); if (ret) { - platform_device_unregister(&efifb_driver); + platform_device_unregister(&efifb_device); return ret; } From d64c132ffe04c0941d3008f178f8cca157dd7f16 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 13 Jun 2011 18:12:58 +0000 Subject: [PATCH 377/595] fbdev/atyfb: Fix 2 defined-but-not-used warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_FB_ATY_BACKLIGHT=y but CONFIG_PCI=n: drivers/video/aty/atyfb_base.c:2272: warning: ‘aty_bl_exit’ defined but not used If CONFIG_ATARI=y for a modular build: drivers/video/aty/atyfb_base.c:2794: warning: ‘store_video_par’ defined but not used Signed-off-by: Geert Uytterhoeven Signed-off-by: Paul Mundt --- drivers/video/aty/atyfb_base.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index ebb893c49e90..d7aaec5667bf 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -248,10 +248,6 @@ static int atyfb_sync(struct fb_info *info); static int aty_init(struct fb_info *info); -#ifdef CONFIG_ATARI -static int store_video_par(char *videopar, unsigned char m64_num); -#endif - static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc); static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc); @@ -2268,11 +2264,13 @@ static void aty_bl_init(struct atyfb_par *par) return; } +#ifdef CONFIG_PCI static void aty_bl_exit(struct backlight_device *bd) { backlight_device_unregister(bd); printk("aty: Backlight unloaded\n"); } +#endif /* CONFIG_PCI */ #endif /* CONFIG_FB_ATY_BACKLIGHT */ @@ -2789,7 +2787,7 @@ static int __devinit aty_init(struct fb_info *info) return ret; } -#ifdef CONFIG_ATARI +#if defined(CONFIG_ATARI) && !defined(MODULE) static int __devinit store_video_par(char *video_str, unsigned char m64_num) { char *p; @@ -2818,7 +2816,7 @@ static int __devinit store_video_par(char *video_str, unsigned char m64_num) phys_vmembase[m64_num] = 0; return -1; } -#endif /* CONFIG_ATARI */ +#endif /* CONFIG_ATARI && !MODULE */ /* * Blank the display. From 1123d93963cbd2546449d4d9f0c568e323cb0ac6 Mon Sep 17 00:00:00 2001 From: Max Asbock Date: Mon, 13 Jun 2011 10:18:32 -0700 Subject: [PATCH 378/595] timerfd: Fix wakeup of processes when timer is cancelled on clock change Currently processes waiting with poll on cancelable timerfd timers are not woken up when the timers are canceled. When the system time is set the clock_was_set() function calls timerfd_clock_was_set() to cancel and wake up processes waiting on potential cancelable timerfd timers. However the wake up currently has no effect because in the case of timerfd_read it is dependent on ctx->ticks not being 0. timerfd_poll also requires ctx->ticks being non zero. As a consequence processes waiting on cancelable timers only get woken up when the timers expire. This patch fixes this by incrementing ctx->ticks before calling wake_up. Signed-off-by: Max Asbock Cc: kay.sievers@vrfy.org Cc: virtuoso@slind.org Cc: johnstul Link: http://lkml.kernel.org/r/1307985512.4710.41.camel@w-amax.beaverton.ibm.com Signed-off-by: Thomas Gleixner --- fs/timerfd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/timerfd.c b/fs/timerfd.c index f67acbdda5e8..dffeb3795af1 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -61,7 +61,9 @@ static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr) /* * Called when the clock was set to cancel the timers in the cancel - * list. + * list. This will wake up processes waiting on these timers. The + * wake-up requires ctx->ticks to be non zero, therefore we increment + * it before calling wake_up_locked(). */ void timerfd_clock_was_set(void) { @@ -76,6 +78,7 @@ void timerfd_clock_was_set(void) spin_lock_irqsave(&ctx->wqh.lock, flags); if (ctx->moffs.tv64 != moffs.tv64) { ctx->moffs.tv64 = KTIME_MAX; + ctx->ticks++; wake_up_locked(&ctx->wqh); } spin_unlock_irqrestore(&ctx->wqh.lock, flags); From 7bbf1d46b28455aed6aa6df772b91d51408c6c81 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Wed, 1 Jun 2011 11:08:01 +0200 Subject: [PATCH 379/595] avr32: fix use of non-existing portnr variable in at32_map_usart() This patch fixes the use of the non-existing portnr variable in at32_map_usart() to use the provided line number instead. Typo was introduced in commit 2b348e2f82f532e3aff8e0ce9293033b3294c1e0. Signed-off-by: Hans-Christian Egtvedt --- arch/avr32/mach-at32ap/at32ap700x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index aa677e2a3823..1b7ad97524b8 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -1044,7 +1044,7 @@ void __init at32_map_usart(unsigned int hw_id, unsigned int line, int flags) } pdata = pdev->dev.platform_data; - pdata->num = portnr; + pdata->num = line; at32_usarts[line] = pdev; } From 4137b31566fd112c8e2d9d4701de5e7a000bcc2d Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Wed, 8 Jun 2011 10:47:25 +0200 Subject: [PATCH 380/595] avr32/at32ap: fix mapping of platform device id for USART This patch will fix the mapping of the platform device id when mapping USART peripheral ID to UART platform device id. Not setting the platform device id will in most cases (when you map USART > 0 to UART 0) make the console not available. Signed-off-by: Hans-Christian Egtvedt --- arch/avr32/mach-at32ap/at32ap700x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 1b7ad97524b8..7fbf0dcb9afe 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -1043,6 +1043,7 @@ void __init at32_map_usart(unsigned int hw_id, unsigned int line, int flags) data->regs = (void __iomem *)pdev->resource[0].start; } + pdev->id = line; pdata = pdev->dev.platform_data; pdata->num = line; at32_usarts[line] = pdev; From a527a1453dd6dd89f07f1e5b2d24fc6559922461 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Wed, 1 Jun 2011 15:10:49 +0200 Subject: [PATCH 381/595] avr32: set CONFIG_CC_OPTIMIZE_FOR_SIZE=y for all defconfigs This patch makes sure the kconfig option CC_OPTIMIZE_FOR_SIZE is set to yes for all default configuration files. This ensures the kernel is optimized for size, and avoids potential relocation truncated to fit problems. Signed-off-by: Hans-Christian Egtvedt --- arch/avr32/configs/atngw100_defconfig | 1 + arch/avr32/configs/atngw100_evklcd100_defconfig | 1 + arch/avr32/configs/atngw100_evklcd101_defconfig | 1 + arch/avr32/configs/atngw100_mrmt_defconfig | 1 + arch/avr32/configs/atngw100mkii_defconfig | 1 + arch/avr32/configs/atngw100mkii_evklcd100_defconfig | 1 + arch/avr32/configs/atngw100mkii_evklcd101_defconfig | 1 + arch/avr32/configs/atstk1002_defconfig | 1 + arch/avr32/configs/atstk1003_defconfig | 1 + arch/avr32/configs/atstk1004_defconfig | 1 + arch/avr32/configs/atstk1006_defconfig | 1 + arch/avr32/configs/favr-32_defconfig | 1 + arch/avr32/configs/hammerhead_defconfig | 1 + arch/avr32/configs/merisc_defconfig | 1 + arch/avr32/configs/mimc200_defconfig | 1 + 15 files changed, 15 insertions(+) diff --git a/arch/avr32/configs/atngw100_defconfig b/arch/avr32/configs/atngw100_defconfig index 6f9ca56de1f6..a06bfccc2840 100644 --- a/arch/avr32/configs/atngw100_defconfig +++ b/arch/avr32/configs/atngw100_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atngw100_evklcd100_defconfig b/arch/avr32/configs/atngw100_evklcd100_defconfig index 7eece0af34c9..d8f1fe80d210 100644 --- a/arch/avr32/configs/atngw100_evklcd100_defconfig +++ b/arch/avr32/configs/atngw100_evklcd100_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atngw100_evklcd101_defconfig b/arch/avr32/configs/atngw100_evklcd101_defconfig index 387eb9d6e423..d4c5b19ec950 100644 --- a/arch/avr32/configs/atngw100_evklcd101_defconfig +++ b/arch/avr32/configs/atngw100_evklcd101_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atngw100_mrmt_defconfig b/arch/avr32/configs/atngw100_mrmt_defconfig index 19f6ceeeff7b..6cb786c0baf6 100644 --- a/arch/avr32/configs/atngw100_mrmt_defconfig +++ b/arch/avr32/configs/atngw100_mrmt_defconfig @@ -7,6 +7,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_SLUB_DEBUG is not set diff --git a/arch/avr32/configs/atngw100mkii_defconfig b/arch/avr32/configs/atngw100mkii_defconfig index f0fe237133a9..6e0dca4d3131 100644 --- a/arch/avr32/configs/atngw100mkii_defconfig +++ b/arch/avr32/configs/atngw100mkii_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atngw100mkii_evklcd100_defconfig b/arch/avr32/configs/atngw100mkii_evklcd100_defconfig index e4a7c1dc8380..7f2a344a5fa8 100644 --- a/arch/avr32/configs/atngw100mkii_evklcd100_defconfig +++ b/arch/avr32/configs/atngw100mkii_evklcd100_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atngw100mkii_evklcd101_defconfig b/arch/avr32/configs/atngw100mkii_evklcd101_defconfig index 6f37f70c2c37..085eeba88f67 100644 --- a/arch/avr32/configs/atngw100mkii_evklcd101_defconfig +++ b/arch/avr32/configs/atngw100mkii_evklcd101_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig index 4fb01f5ab42f..d1a887e64055 100644 --- a/arch/avr32/configs/atstk1002_defconfig +++ b/arch/avr32/configs/atstk1002_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atstk1003_defconfig b/arch/avr32/configs/atstk1003_defconfig index 9faaf9b900f2..956f2819ad45 100644 --- a/arch/avr32/configs/atstk1003_defconfig +++ b/arch/avr32/configs/atstk1003_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atstk1004_defconfig b/arch/avr32/configs/atstk1004_defconfig index 3d2a5d85f970..40c69f38c61a 100644 --- a/arch/avr32/configs/atstk1004_defconfig +++ b/arch/avr32/configs/atstk1004_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/atstk1006_defconfig b/arch/avr32/configs/atstk1006_defconfig index 1ed8f22d4fe2..511eb8af356d 100644 --- a/arch/avr32/configs/atstk1006_defconfig +++ b/arch/avr32/configs/atstk1006_defconfig @@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/favr-32_defconfig b/arch/avr32/configs/favr-32_defconfig index aeadc955db32..19973b06170c 100644 --- a/arch/avr32/configs/favr-32_defconfig +++ b/arch/avr32/configs/favr-32_defconfig @@ -6,6 +6,7 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/hammerhead_defconfig b/arch/avr32/configs/hammerhead_defconfig index 1692beeb7ed3..6f45681196d1 100644 --- a/arch/avr32/configs/hammerhead_defconfig +++ b/arch/avr32/configs/hammerhead_defconfig @@ -7,6 +7,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set diff --git a/arch/avr32/configs/merisc_defconfig b/arch/avr32/configs/merisc_defconfig index 8b670a6530bf..3befab966827 100644 --- a/arch/avr32/configs/merisc_defconfig +++ b/arch/avr32/configs/merisc_defconfig @@ -7,6 +7,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set CONFIG_MODULES=y diff --git a/arch/avr32/configs/mimc200_defconfig b/arch/avr32/configs/mimc200_defconfig index 5a51f2e7ffb9..1bee51f22154 100644 --- a/arch/avr32/configs/mimc200_defconfig +++ b/arch/avr32/configs/mimc200_defconfig @@ -7,6 +7,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_BASE_FULL is not set # CONFIG_COMPAT_BRK is not set From 3000f0077a5745918830f40826c23fe5bf934b8b Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Sun, 15 May 2011 00:23:32 +0200 Subject: [PATCH 382/595] avr32: add some more at91 to cpu.h definition Somme common drivers will need those at91 cpu_is_xxx() definitions. Those definitions are already in Linus' tree so if we want to use them in common drivers, we will need them in AVR32 cpu.h file. Signed-off-by: Nicolas Ferre Acked-by: Hans-Christian Egtvedt --- arch/avr32/mach-at32ap/include/mach/cpu.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/avr32/mach-at32ap/include/mach/cpu.h b/arch/avr32/mach-at32ap/include/mach/cpu.h index 9c96a130f3a8..8181293115e4 100644 --- a/arch/avr32/mach-at32ap/include/mach/cpu.h +++ b/arch/avr32/mach-at32ap/include/mach/cpu.h @@ -31,8 +31,20 @@ #define cpu_is_at91sam9263() (0) #define cpu_is_at91sam9rl() (0) #define cpu_is_at91cap9() (0) +#define cpu_is_at91cap9_revB() (0) +#define cpu_is_at91cap9_revC() (0) #define cpu_is_at91sam9g10() (0) +#define cpu_is_at91sam9g20() (0) #define cpu_is_at91sam9g45() (0) #define cpu_is_at91sam9g45es() (0) +#define cpu_is_at91sam9m10() (0) +#define cpu_is_at91sam9g46() (0) +#define cpu_is_at91sam9m11() (0) +#define cpu_is_at91sam9x5() (0) +#define cpu_is_at91sam9g15() (0) +#define cpu_is_at91sam9g35() (0) +#define cpu_is_at91sam9x35() (0) +#define cpu_is_at91sam9g25() (0) +#define cpu_is_at91sam9x25() (0) #endif /* __ASM_ARCH_CPU_H */ From c162755491f7ca9853cb9f2aaa3ff3677c1bda78 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Mon, 6 Jun 2011 18:19:20 +0200 Subject: [PATCH 383/595] avr32: make intc_resume() return void to conform to syscore_ops This patch removes the unneeded, and now wrong, return 0 from intc_resume() and lets the function return void instead. This matches the resume callback in struct syscore_ops. Signed-off-by: Hans-Christian Egtvedt --- arch/avr32/mach-at32ap/intc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c index 3e3646186c9f..c9ac2f8e8f64 100644 --- a/arch/avr32/mach-at32ap/intc.c +++ b/arch/avr32/mach-at32ap/intc.c @@ -167,14 +167,12 @@ static int intc_suspend(void) return 0; } -static int intc_resume(void) +static void intc_resume(void) { int i; for (i = 0; i < 64; i++) intc_writel(&intc0, INTPR0 + 4 * i, intc0.saved_ipr[i]); - - return 0; } #else #define intc_suspend NULL From ff71db2f0784cfff38fa7b55908867a24ccc3216 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Fri, 10 Jun 2011 15:09:05 +0200 Subject: [PATCH 384/595] avr32, exec: remove redundant set_fs(USER_DS) The address limit is already set in flush_old_exec() so this set_fs(USER_DS) is redundant. Signed-off-by: Mathias Krause Signed-off-by: Hans-Christian Egtvedt --- arch/avr32/include/asm/processor.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/avr32/include/asm/processor.h b/arch/avr32/include/asm/processor.h index 49a88f5a9d2f..108502bc6770 100644 --- a/arch/avr32/include/asm/processor.h +++ b/arch/avr32/include/asm/processor.h @@ -131,7 +131,6 @@ struct thread_struct { */ #define start_thread(regs, new_pc, new_sp) \ do { \ - set_fs(USER_DS); \ memset(regs, 0, sizeof(*regs)); \ regs->sr = MODE_USER; \ regs->pc = new_pc & ~1; \ From e9e35c5a2b2c803b5e2f25906d8ffe110670ceb6 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 14 Jun 2011 05:53:18 -0700 Subject: [PATCH 385/595] OMAP1: PM: register notifiers with generic clock ops even when !PM_RUNTIME When runtime PM is disabled, device clocks need to be enabled on device add and disabled on device remove. This currently is not happening because in the !PM_RUNTIME case, no notifiers are registered for OMAP1 devices. Fix this by ensuring notifiers are registered, even in the !PM_RUNTIME case. Reported-by: Janusz Krzysztofik Tested-by: Janusz Krzysztofik Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/Makefile | 4 ++-- arch/arm/mach-omap1/pm_bus.c | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index af98117043d2..5b114d1558c8 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -4,14 +4,14 @@ # Common support obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o -obj-y += clock.o clock_data.o opp_data.o reset.o +obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o # Power Management -obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o +obj-$(CONFIG_PM) += pm.o sleep.o # DSP obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c index fe31d933f0ed..334fb8871bc3 100644 --- a/arch/arm/mach-omap1/pm_bus.c +++ b/arch/arm/mach-omap1/pm_bus.c @@ -56,9 +56,13 @@ static struct dev_power_domain default_power_domain = { USE_PLATFORM_PM_SLEEP_OPS }, }; +#define OMAP1_PWR_DOMAIN (&default_power_domain) +#else +#define OMAP1_PWR_DOMAIN NULL +#endif /* CONFIG_PM_RUNTIME */ static struct pm_clk_notifier_block platform_bus_notifier = { - .pwr_domain = &default_power_domain, + .pwr_domain = OMAP1_PWR_DOMAIN, .con_ids = { "ick", "fck", NULL, }, }; @@ -72,4 +76,4 @@ static int __init omap1_pm_runtime_init(void) return 0; } core_initcall(omap1_pm_runtime_init); -#endif /* CONFIG_PM_RUNTIME */ + From 040d15c86747cf44fcf6b8ee19d805d4ef20caf3 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 14 Jun 2011 15:51:18 +0000 Subject: [PATCH 386/595] [CIFS] trivial cleanup fscache cFYI and cERROR messages ... for uniformity and cleaner debug logs. Signed-off-by: Suresh Jayaraman Signed-off-by: Steve French --- fs/cifs/cache.c | 6 +++--- fs/cifs/fscache.c | 51 ++++++++++++++++++++++------------------------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c index dd8584d35a14..545509c3313b 100644 --- a/fs/cifs/cache.c +++ b/fs/cifs/cache.c @@ -92,7 +92,7 @@ static uint16_t cifs_server_get_key(const void *cookie_netfs_data, break; default: - cERROR(1, "CIFS: Unknown network family '%d'", sa->sa_family); + cERROR(1, "Unknown network family '%d'", sa->sa_family); key_len = 0; break; } @@ -152,7 +152,7 @@ static uint16_t cifs_super_get_key(const void *cookie_netfs_data, void *buffer, sharename = extract_sharename(tcon->treeName); if (IS_ERR(sharename)) { - cFYI(1, "CIFS: couldn't extract sharename\n"); + cFYI(1, "%s: couldn't extract sharename\n", __func__); sharename = NULL; return 0; } @@ -302,7 +302,7 @@ static void cifs_fscache_inode_now_uncached(void *cookie_netfs_data) pagevec_init(&pvec, 0); first = 0; - cFYI(1, "cifs inode 0x%p now uncached", cifsi); + cFYI(1, "%s: cifs inode 0x%p now uncached", __func__, cifsi); for (;;) { nr_pages = pagevec_lookup(&pvec, diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index d368a47ba5eb..816696621ec9 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c @@ -28,14 +28,14 @@ void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) server->fscache = fscache_acquire_cookie(cifs_fscache_netfs.primary_index, &cifs_fscache_server_index_def, server); - cFYI(1, "CIFS: get client cookie (0x%p/0x%p)", server, - server->fscache); + cFYI(1, "%s: (0x%p/0x%p)", __func__, server, + server->fscache); } void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) { - cFYI(1, "CIFS: release client cookie (0x%p/0x%p)", server, - server->fscache); + cFYI(1, "%s: (0x%p/0x%p)", __func__, server, + server->fscache); fscache_relinquish_cookie(server->fscache, 0); server->fscache = NULL; } @@ -47,13 +47,13 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) tcon->fscache = fscache_acquire_cookie(server->fscache, &cifs_fscache_super_index_def, tcon); - cFYI(1, "CIFS: get superblock cookie (0x%p/0x%p)", - server->fscache, tcon->fscache); + cFYI(1, "%s: (0x%p/0x%p)", __func__, server->fscache, + tcon->fscache); } void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) { - cFYI(1, "CIFS: releasing superblock cookie (0x%p)", tcon->fscache); + cFYI(1, "%s: (0x%p)", __func__, tcon->fscache); fscache_relinquish_cookie(tcon->fscache, 0); tcon->fscache = NULL; } @@ -70,8 +70,8 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) { cifsi->fscache = fscache_acquire_cookie(tcon->fscache, &cifs_fscache_inode_object_def, cifsi); - cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache, - cifsi->fscache); + cFYI(1, "%s: got FH cookie (0x%p/0x%p)", __func__, + tcon->fscache, cifsi->fscache); } } @@ -80,8 +80,7 @@ void cifs_fscache_release_inode_cookie(struct inode *inode) struct cifsInodeInfo *cifsi = CIFS_I(inode); if (cifsi->fscache) { - cFYI(1, "CIFS releasing inode cookie (0x%p)", - cifsi->fscache); + cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache); fscache_relinquish_cookie(cifsi->fscache, 0); cifsi->fscache = NULL; } @@ -92,8 +91,7 @@ static void cifs_fscache_disable_inode_cookie(struct inode *inode) struct cifsInodeInfo *cifsi = CIFS_I(inode); if (cifsi->fscache) { - cFYI(1, "CIFS disabling inode cookie (0x%p)", - cifsi->fscache); + cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache); fscache_relinquish_cookie(cifsi->fscache, 1); cifsi->fscache = NULL; } @@ -121,8 +119,8 @@ void cifs_fscache_reset_inode_cookie(struct inode *inode) cifs_sb_master_tcon(cifs_sb)->fscache, &cifs_fscache_inode_object_def, cifsi); - cFYI(1, "CIFS: new cookie 0x%p oldcookie 0x%p", - cifsi->fscache, old); + cFYI(1, "%s: new cookie 0x%p oldcookie 0x%p", + __func__, cifsi->fscache, old); } } @@ -132,8 +130,8 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp) struct inode *inode = page->mapping->host; struct cifsInodeInfo *cifsi = CIFS_I(inode); - cFYI(1, "CIFS: fscache release page (0x%p/0x%p)", - page, cifsi->fscache); + cFYI(1, "%s: (0x%p/0x%p)", __func__, page, + cifsi->fscache); if (!fscache_maybe_release_page(cifsi->fscache, page, gfp)) return 0; } @@ -144,8 +142,7 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp) static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx, int error) { - cFYI(1, "CFS: readpage_from_fscache_complete (0x%p/%d)", - page, error); + cFYI(1, "%s: (0x%p/%d)", __func__, page, error); if (!error) SetPageUptodate(page); unlock_page(page); @@ -158,7 +155,7 @@ int __cifs_readpage_from_fscache(struct inode *inode, struct page *page) { int ret; - cFYI(1, "CIFS: readpage_from_fscache(fsc:%p, p:%p, i:0x%p", + cFYI(1, "%s: (fsc:%p, p:%p, i:0x%p", __func__, CIFS_I(inode)->fscache, page, inode); ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page, cifs_readpage_from_fscache_complete, @@ -167,11 +164,11 @@ int __cifs_readpage_from_fscache(struct inode *inode, struct page *page) switch (ret) { case 0: /* page found in fscache, read submitted */ - cFYI(1, "CIFS: readpage_from_fscache: submitted"); + cFYI(1, "%s: submitted", __func__); return ret; case -ENOBUFS: /* page won't be cached */ case -ENODATA: /* page not in cache */ - cFYI(1, "CIFS: readpage_from_fscache %d", ret); + cFYI(1, "%s: %d", __func__, ret); return 1; default: @@ -190,7 +187,7 @@ int __cifs_readpages_from_fscache(struct inode *inode, { int ret; - cFYI(1, "CIFS: __cifs_readpages_from_fscache (0x%p/%u/0x%p)", + cFYI(1, "%s: (0x%p/%u/0x%p)", __func__, CIFS_I(inode)->fscache, *nr_pages, inode); ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping, pages, nr_pages, @@ -199,12 +196,12 @@ int __cifs_readpages_from_fscache(struct inode *inode, mapping_gfp_mask(mapping)); switch (ret) { case 0: /* read submitted to the cache for all pages */ - cFYI(1, "CIFS: readpages_from_fscache: submitted"); + cFYI(1, "%s: submitted", __func__); return ret; case -ENOBUFS: /* some pages are not cached and can't be */ case -ENODATA: /* some pages are not cached */ - cFYI(1, "CIFS: readpages_from_fscache: no page"); + cFYI(1, "%s: no page", __func__); return 1; default: @@ -218,7 +215,7 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page) { int ret; - cFYI(1, "CIFS: readpage_to_fscache(fsc: %p, p: %p, i: %p", + cFYI(1, "%s: (fsc: %p, p: %p, i: %p)", __func__, CIFS_I(inode)->fscache, page, inode); ret = fscache_write_page(CIFS_I(inode)->fscache, page, GFP_KERNEL); if (ret != 0) @@ -230,7 +227,7 @@ void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode) struct cifsInodeInfo *cifsi = CIFS_I(inode); struct fscache_cookie *cookie = cifsi->fscache; - cFYI(1, "CIFS: fscache invalidatepage (0x%p/0x%p)", page, cookie); + cFYI(1, "%s: (0x%p/0x%p)", __func__, page, cookie); fscache_wait_on_page_write(cookie, page); fscache_uncache_page(cookie, page); } From c46a131c0c0f4c2457e6b1e430c578a5cb057334 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 5 Jun 2011 11:12:31 +0000 Subject: [PATCH 387/595] xfs: fix ->mknod() return value on xfs_get_acl() failure ->mknod() should return negative on errors and PTR_ERR() gives already negative value... Signed-off-by: Al Viro Reviewed-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/linux-2.6/xfs_iops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index dd21784525a8..d44d92cd12b1 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -182,7 +182,7 @@ xfs_vn_mknod( if (IS_POSIXACL(dir)) { default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT); if (IS_ERR(default_acl)) - return -PTR_ERR(default_acl); + return PTR_ERR(default_acl); if (!default_acl) mode &= ~current_umask(); From 1252b3013b790c77e1c4f077a40542f86df37fb4 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 14 Jun 2011 16:19:54 +0000 Subject: [PATCH 388/595] [CIFS] update cifs version to 1.73 Signed-off-by: Steve French --- fs/cifs/cifsfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 64313f778ebf..0900e1658c96 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -129,5 +129,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); extern const struct export_operations cifs_export_ops; #endif /* CIFS_NFSD_EXPORT */ -#define CIFS_VERSION "1.72" +#define CIFS_VERSION "1.73" #endif /* _CIFSFS_H */ From ded509880f6a0213b09f8ae7bef84acb16eaccbf Mon Sep 17 00:00:00 2001 From: "Roy.Li" Date: Fri, 20 May 2011 10:38:06 +0800 Subject: [PATCH 389/595] SELinux: skip file_name_trans_write() when policy downgraded. When policy version is less than POLICYDB_VERSION_FILENAME_TRANS, skip file_name_trans_write(). Signed-off-by: Roy.Li Signed-off-by: Eric Paris --- security/selinux/ss/policydb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 102e9ec1b77a..d246aca3f4fb 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -3222,6 +3222,9 @@ static int filename_trans_write(struct policydb *p, void *fp) __le32 buf[1]; int rc; + if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS) + return 0; + nel = 0; rc = hashtab_map(p->filename_trans, hashtab_cnt, &nel); if (rc) From 60b8b1de0dd2bf246f0e074d287bb3f0bc42a755 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Tue, 14 Jun 2011 12:45:10 -0700 Subject: [PATCH 390/595] x86 idle: APM requires pm_idle/default_idle unconditionally when a module [ Also from Ben Hutchings and Vitaliy Ivanov ] Commit 06ae40ce073d ("x86 idle: EXPORT_SYMBOL(default_idle, pm_idle) only when APM demands it") removed the export for pm_idle/default_idle unless the apm module was modularised and CONFIG_APM_CPU_IDLE was set. But the apm module uses pm_idle/default_idle unconditionally, CONFIG_APM_CPU_IDLE only affects the bios idle threshold. Adjust the export accordingly. [ Used #ifdef instead of #if defined() as it's shorter, and what both Ben and Vitaliy used.. Andy, you're out-voted ;) - Linus ] Reported-by: Randy Dunlap Acked-by: Jiri Kosina Acked-by: Ingo Molnar Acked-by: Len Brown Signed-off-by: Andy Whitcroft Signed-off-by: Vitaliy Ivanov Signed-off-by: Ben Hutchings Signed-off-by: Linus Torvalds --- arch/x86/kernel/process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 2e4928d45a2d..e1ba8cb24e4e 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -337,7 +337,7 @@ EXPORT_SYMBOL(boot_option_idle_override); * Powermanagement idle function, if any.. */ void (*pm_idle)(void); -#if defined(CONFIG_APM_MODULE) && defined(CONFIG_APM_CPU_IDLE) +#ifdef CONFIG_APM_MODULE EXPORT_SYMBOL(pm_idle); #endif @@ -399,7 +399,7 @@ void default_idle(void) cpu_relax(); } } -#if defined(CONFIG_APM_MODULE) && defined(CONFIG_APM_CPU_IDLE) +#ifdef CONFIG_APM_MODULE EXPORT_SYMBOL(default_idle); #endif From 9a432736904d386cda28b987b38ba14dae960ecc Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 30 May 2011 20:38:55 -0700 Subject: [PATCH 391/595] rcu: Simplify curing of load woes Make the functions creating the kthreads wake them up. Leverage the fact that the per-node and boost kthreads can run anywhere, thus dispensing with the need to wake them up once the incoming CPU has gone fully online. Signed-off-by: Paul E. McKenney Tested-by: Daniel J Blueman --- kernel/rcutree.c | 65 +++++++++++++---------------------------- kernel/rcutree_plugin.h | 11 +------ 2 files changed, 22 insertions(+), 54 deletions(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 89419ff92e99..0a8ec5b2e208 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1635,6 +1635,20 @@ static int rcu_cpu_kthread(void *arg) * to manipulate rcu_cpu_kthread_task. There might be another CPU * attempting to access it during boot, but the locking in kthread_bind() * will enforce sufficient ordering. + * + * Please note that we cannot simply refuse to wake up the per-CPU + * kthread because kthreads are created in TASK_UNINTERRUPTIBLE state, + * which can result in softlockup complaints if the task ends up being + * idle for more than a couple of minutes. + * + * However, please note also that we cannot bind the per-CPU kthread to its + * CPU until that CPU is fully online. We also cannot wait until the + * CPU is fully online before we create its per-CPU kthread, as this would + * deadlock the system when CPU notifiers tried waiting for grace + * periods. So we bind the per-CPU kthread to its CPU only if the CPU + * is online. If its CPU is not yet fully online, then the code in + * rcu_cpu_kthread() will wait until it is fully online, and then do + * the binding. */ static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu) { @@ -1647,12 +1661,14 @@ static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu) t = kthread_create(rcu_cpu_kthread, (void *)(long)cpu, "rcuc%d", cpu); if (IS_ERR(t)) return PTR_ERR(t); - kthread_bind(t, cpu); + if (cpu_online(cpu)) + kthread_bind(t, cpu); per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu; WARN_ON_ONCE(per_cpu(rcu_cpu_kthread_task, cpu) != NULL); - per_cpu(rcu_cpu_kthread_task, cpu) = t; sp.sched_priority = RCU_KTHREAD_PRIO; sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + per_cpu(rcu_cpu_kthread_task, cpu) = t; + wake_up_process(t); /* Get to TASK_INTERRUPTIBLE quickly. */ return 0; } @@ -1759,12 +1775,11 @@ static int __cpuinit rcu_spawn_one_node_kthread(struct rcu_state *rsp, raw_spin_unlock_irqrestore(&rnp->lock, flags); sp.sched_priority = 99; sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */ } return rcu_spawn_one_boost_kthread(rsp, rnp, rnp_index); } -static void rcu_wake_one_boost_kthread(struct rcu_node *rnp); - /* * Spawn all kthreads -- called as soon as the scheduler is running. */ @@ -1772,30 +1787,18 @@ static int __init rcu_spawn_kthreads(void) { int cpu; struct rcu_node *rnp; - struct task_struct *t; rcu_kthreads_spawnable = 1; for_each_possible_cpu(cpu) { per_cpu(rcu_cpu_has_work, cpu) = 0; - if (cpu_online(cpu)) { + if (cpu_online(cpu)) (void)rcu_spawn_one_cpu_kthread(cpu); - t = per_cpu(rcu_cpu_kthread_task, cpu); - if (t) - wake_up_process(t); - } } rnp = rcu_get_root(rcu_state); (void)rcu_spawn_one_node_kthread(rcu_state, rnp); - if (rnp->node_kthread_task) - wake_up_process(rnp->node_kthread_task); if (NUM_RCU_NODES > 1) { - rcu_for_each_leaf_node(rcu_state, rnp) { + rcu_for_each_leaf_node(rcu_state, rnp) (void)rcu_spawn_one_node_kthread(rcu_state, rnp); - t = rnp->node_kthread_task; - if (t) - wake_up_process(t); - rcu_wake_one_boost_kthread(rnp); - } } return 0; } @@ -2220,31 +2223,6 @@ static void __cpuinit rcu_prepare_kthreads(int cpu) } } -/* - * kthread_create() creates threads in TASK_UNINTERRUPTIBLE state, - * but the RCU threads are woken on demand, and if demand is low this - * could be a while triggering the hung task watchdog. - * - * In order to avoid this, poke all tasks once the CPU is fully - * up and running. - */ -static void __cpuinit rcu_online_kthreads(int cpu) -{ - struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu); - struct rcu_node *rnp = rdp->mynode; - struct task_struct *t; - - t = per_cpu(rcu_cpu_kthread_task, cpu); - if (t) - wake_up_process(t); - - t = rnp->node_kthread_task; - if (t) - wake_up_process(t); - - rcu_wake_one_boost_kthread(rnp); -} - /* * Handle CPU online/offline notification events. */ @@ -2262,7 +2240,6 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self, rcu_prepare_kthreads(cpu); break; case CPU_ONLINE: - rcu_online_kthreads(cpu); case CPU_DOWN_FAILED: rcu_node_kthread_setaffinity(rnp, -1); rcu_cpu_kthread_setrt(cpu, 1); diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index c8bff3099a89..ea2e2fb79e81 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -1299,15 +1299,10 @@ static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, raw_spin_unlock_irqrestore(&rnp->lock, flags); sp.sched_priority = RCU_KTHREAD_PRIO; sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */ return 0; } -static void __cpuinit rcu_wake_one_boost_kthread(struct rcu_node *rnp) -{ - if (rnp->boost_kthread_task) - wake_up_process(rnp->boost_kthread_task); -} - #else /* #ifdef CONFIG_RCU_BOOST */ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) @@ -1331,10 +1326,6 @@ static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, return 0; } -static void __cpuinit rcu_wake_one_boost_kthread(struct rcu_node *rnp) -{ -} - #endif /* #else #ifdef CONFIG_RCU_BOOST */ #ifndef CONFIG_SMP From 09223371deac67d08ca0b70bd18787920284c967 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 14 Jun 2011 13:26:25 +0800 Subject: [PATCH 392/595] rcu: Use softirq to address performance regression Commit a26ac2455ffcf3(rcu: move TREE_RCU from softirq to kthread) introduced performance regression. In an AIM7 test, this commit degraded performance by about 40%. The commit runs rcu callbacks in a kthread instead of softirq. We observed high rate of context switch which is caused by this. Out test system has 64 CPUs and HZ is 1000, so we saw more than 64k context switch per second which is caused by RCU's per-CPU kthread. A trace showed that most of the time the RCU per-CPU kthread doesn't actually handle any callbacks, but instead just does a very small amount of work handling grace periods. This means that RCU's per-CPU kthreads are making the scheduler do quite a bit of work in order to allow a very small amount of RCU-related processing to be done. Alex Shi's analysis determined that this slowdown is due to lock contention within the scheduler. Unfortunately, as Peter Zijlstra points out, the scheduler's real-time semantics require global action, which means that this contention is inherent in real-time scheduling. (Yes, perhaps someone will come up with a workaround -- otherwise, -rt is not going to do well on large SMP systems -- but this patch will work around this issue in the meantime. And "the meantime" might well be forever.) This patch therefore re-introduces softirq processing to RCU, but only for core RCU work. RCU callbacks are still executed in kthread context, so that only a small amount of RCU work runs in softirq context in the common case. This should minimize ksoftirqd execution, allowing us to skip boosting of ksoftirqd for CONFIG_RCU_BOOST=y kernels. Signed-off-by: Shaohua Li Tested-by: "Alex,Shi" Signed-off-by: Paul E. McKenney --- Documentation/filesystems/proc.txt | 1 + include/linux/interrupt.h | 1 + include/trace/events/irq.h | 3 ++- kernel/rcutree.c | 23 +++++++++++++++++++---- kernel/rcutree.h | 1 + kernel/rcutree_plugin.h | 9 +++++++++ kernel/softirq.c | 2 +- tools/perf/util/trace-event-parse.c | 1 + 8 files changed, 35 insertions(+), 6 deletions(-) diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index f48178024067..db3b1aba32a3 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -843,6 +843,7 @@ Provides counts of softirq handlers serviced since boot time, for each cpu. TASKLET: 0 0 0 290 SCHED: 27035 26983 26971 26746 HRTIMER: 0 0 0 0 + RCU: 1678 1769 2178 2250 1.3 IDE devices in /proc/ide diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 6c12989839d9..f6efed0039ed 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -414,6 +414,7 @@ enum TASKLET_SOFTIRQ, SCHED_SOFTIRQ, HRTIMER_SOFTIRQ, + RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ NR_SOFTIRQS }; diff --git a/include/trace/events/irq.h b/include/trace/events/irq.h index ae045ca7d356..1c09820df585 100644 --- a/include/trace/events/irq.h +++ b/include/trace/events/irq.h @@ -20,7 +20,8 @@ struct softirq_action; softirq_name(BLOCK_IOPOLL), \ softirq_name(TASKLET), \ softirq_name(SCHED), \ - softirq_name(HRTIMER)) + softirq_name(HRTIMER), \ + softirq_name(RCU)) /** * irq_handler_entry - called immediately before the irq action handler diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 0a8ec5b2e208..ae5c9ea68662 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -100,6 +100,7 @@ static char rcu_kthreads_spawnable; static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu); static void invoke_rcu_cpu_kthread(void); +static void __invoke_rcu_cpu_kthread(void); #define RCU_KTHREAD_PRIO 1 /* RT priority for per-CPU kthreads. */ @@ -1442,13 +1443,21 @@ __rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp) } /* If there are callbacks ready, invoke them. */ - rcu_do_batch(rsp, rdp); + if (cpu_has_callbacks_ready_to_invoke(rdp)) + __invoke_rcu_cpu_kthread(); +} + +static void rcu_kthread_do_work(void) +{ + rcu_do_batch(&rcu_sched_state, &__get_cpu_var(rcu_sched_data)); + rcu_do_batch(&rcu_bh_state, &__get_cpu_var(rcu_bh_data)); + rcu_preempt_do_callbacks(); } /* * Do softirq processing for the current CPU. */ -static void rcu_process_callbacks(void) +static void rcu_process_callbacks(struct softirq_action *unused) { __rcu_process_callbacks(&rcu_sched_state, &__get_cpu_var(rcu_sched_data)); @@ -1465,7 +1474,7 @@ static void rcu_process_callbacks(void) * the current CPU with interrupts disabled, the rcu_cpu_kthread_task * cannot disappear out from under us. */ -static void invoke_rcu_cpu_kthread(void) +static void __invoke_rcu_cpu_kthread(void) { unsigned long flags; @@ -1479,6 +1488,11 @@ static void invoke_rcu_cpu_kthread(void) local_irq_restore(flags); } +static void invoke_rcu_cpu_kthread(void) +{ + raise_softirq(RCU_SOFTIRQ); +} + /* * Wake up the specified per-rcu_node-structure kthread. * Because the per-rcu_node kthreads are immortal, we don't need @@ -1613,7 +1627,7 @@ static int rcu_cpu_kthread(void *arg) *workp = 0; local_irq_restore(flags); if (work) - rcu_process_callbacks(); + rcu_kthread_do_work(); local_bh_enable(); if (*workp != 0) spincnt++; @@ -2387,6 +2401,7 @@ void __init rcu_init(void) rcu_init_one(&rcu_sched_state, &rcu_sched_data); rcu_init_one(&rcu_bh_state, &rcu_bh_data); __rcu_init_preempt(); + open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); /* * We don't need protection against CPU-hotplug here because diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 7b9a08b4aaea..0fed6b934d2a 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -439,6 +439,7 @@ static void rcu_preempt_offline_cpu(int cpu); #endif /* #ifdef CONFIG_HOTPLUG_CPU */ static void rcu_preempt_check_callbacks(int cpu); static void rcu_preempt_process_callbacks(void); +static void rcu_preempt_do_callbacks(void); void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU) static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp); diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index ea2e2fb79e81..38d09c5f2b41 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -602,6 +602,11 @@ static void rcu_preempt_process_callbacks(void) &__get_cpu_var(rcu_preempt_data)); } +static void rcu_preempt_do_callbacks(void) +{ + rcu_do_batch(&rcu_preempt_state, &__get_cpu_var(rcu_preempt_data)); +} + /* * Queue a preemptible-RCU callback for invocation after a grace period. */ @@ -997,6 +1002,10 @@ static void rcu_preempt_process_callbacks(void) { } +static void rcu_preempt_do_callbacks(void) +{ +} + /* * Wait for an rcu-preempt grace period, but make it happen quickly. * But because preemptible RCU does not exist, map to rcu-sched. diff --git a/kernel/softirq.c b/kernel/softirq.c index 13960170cad4..40cf63ddd4b3 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -58,7 +58,7 @@ DEFINE_PER_CPU(struct task_struct *, ksoftirqd); char *softirq_to_name[NR_SOFTIRQS] = { "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL", - "TASKLET", "SCHED", "HRTIMER" + "TASKLET", "SCHED", "HRTIMER", "RCU" }; /* diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 1e88485c16a0..0a7ed5b5e281 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -2187,6 +2187,7 @@ static const struct flag flags[] = { { "TASKLET_SOFTIRQ", 6 }, { "SCHED_SOFTIRQ", 7 }, { "HRTIMER_SOFTIRQ", 8 }, + { "RCU_SOFTIRQ", 9 }, { "HRTIMER_NORESTART", 0 }, { "HRTIMER_RESTART", 1 }, From ada9c93312f7ec49514c68c211595ce2601cebae Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 14 Jun 2011 15:50:11 -0700 Subject: [PATCH 393/595] signal.c: fix kernel-doc notation Fix kernel-doc warnings in signal.c: Warning(kernel/signal.c:2374): No description found for parameter 'nset' Warning(kernel/signal.c:2374): Excess function parameter 'set' description in 'sys_rt_sigprocmask' Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- kernel/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/signal.c b/kernel/signal.c index 86c32b884f8e..ff7678603328 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2365,7 +2365,7 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset) /** * sys_rt_sigprocmask - change the list of currently blocked signals * @how: whether to add, remove, or set signals - * @set: stores pending signals + * @nset: stores pending signals * @oset: previous value of signal mask if non-null * @sigsetsize: size of sigset_t type */ From d521dd944e461371cb309c7c3568483cd2b6f5f2 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 14 Jun 2011 14:27:22 +0000 Subject: [PATCH 394/595] fbdev: sh_mobile_hdmi: fix regression: statically enable RTPM A recent modification to the runtime PM code on mach-shmobile made a wrong RTPM implementation in the sh_mobile_hdmi driver apparent, which broke HDMI hotplug detection support on ap4evb. This patch does not implement a proper dynamic RTPM support for sh_mobile_hdmi, instead it restores the previous working state by statically enabling it. A more power-efficient solution should be implemented for the next kernel version. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- drivers/video/sh_mobile_hdmi.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index 6ae40b630dc9..7d54e2c612f7 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c @@ -1127,23 +1127,16 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) struct fb_info *info = hdmi->info; unsigned long parent_rate = 0, hdmi_rate; - /* A device has been plugged in */ - pm_runtime_get_sync(hdmi->dev); - ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate); - if (ret < 0) { - pm_runtime_put(hdmi->dev); + if (ret < 0) goto out; - } hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE; /* Reconfigure the clock */ ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate); - if (ret < 0) { - pm_runtime_put(hdmi->dev); + if (ret < 0) goto out; - } msleep(10); sh_hdmi_configure(hdmi); @@ -1191,7 +1184,6 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) fb_set_suspend(hdmi->info, 1); console_unlock(); - pm_runtime_put(hdmi->dev); } out: @@ -1312,7 +1304,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn); pm_runtime_enable(&pdev->dev); - pm_runtime_resume(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); /* Product and revision IDs are 0 in sh-mobile version */ dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", @@ -1340,7 +1332,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) ecodec: free_irq(irq, hdmi); ereqirq: - pm_runtime_suspend(&pdev->dev); + pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); iounmap(hdmi->base); emap: @@ -1377,7 +1369,7 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev) free_irq(irq, hdmi); /* Wait for already scheduled work */ cancel_delayed_work_sync(&hdmi->edid_work); - pm_runtime_suspend(&pdev->dev); + pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); clk_disable(hdmi->hdmi_clk); clk_put(hdmi->hdmi_clk); From 05a7929f31a0d516a9c19012bf27a1ea5058dc7a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 15 Jun 2011 06:16:35 +0000 Subject: [PATCH 395/595] ARM: mach-shmobile: mackerel: tidyup usbhs driver settings - usb0 pipe is same as default. own pipe config is not needed - usb1 lost get_id function Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-mackerel.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 1037bd2ffdb9..7e1d37584321 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -629,19 +629,6 @@ static void usbhs0_hardware_exit(struct platform_device *pdev) cancel_delayed_work_sync(&priv->work); } -static u32 usbhs0_pipe_cfg[] = { - USB_ENDPOINT_XFER_CONTROL, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_BULK, -}; - static struct usbhs_private usbhs0_private = { .usbcrcaddr = 0xe605810c, /* USBCR2 */ .info = { @@ -654,8 +641,6 @@ static struct usbhs_private usbhs0_private = { }, .driver_param = { .buswait_bwait = 4, - .pipe_type = usbhs0_pipe_cfg, - .pipe_size = ARRAY_SIZE(usbhs0_pipe_cfg), }, }, }; @@ -786,6 +771,11 @@ static void usbhs1_hardware_exit(struct platform_device *pdev) free_irq(IRQ8, pdev); } +static int usbhs1_get_id(struct platform_device *pdev) +{ + return USBHS_GADGET; +} + static u32 usbhs1_pipe_cfg[] = { USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_ISOC, @@ -812,6 +802,7 @@ static struct usbhs_private usbhs1_private = { .platform_callback = { .hardware_init = usbhs1_hardware_init, .hardware_exit = usbhs1_hardware_exit, + .get_id = usbhs1_get_id, .phy_reset = usbhs_phy_reset, .get_vbus = usbhs_get_vbus, }, From 8dd0de8be31b4b966d17750a0b10df2f575c91ac Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Tue, 14 Jun 2011 18:36:24 -0400 Subject: [PATCH 396/595] sched: Fix need_resched() when checking peempt The RT preempt check tests the wrong task if NEED_RESCHED is set. It currently checks the local CPU task. It is supposed to check the task that is running on the runqueue we are about to wake another task on. Signed-off-by: Hillf Danton Reviewed-by: Yong Zhang Signed-off-by: Steven Rostedt Link: http://lkml.kernel.org/r/20110614223657.450239027@goodmis.org Signed-off-by: Ingo Molnar --- 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 88725c939e0b..9b8d5dce946e 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -1096,7 +1096,7 @@ static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flag * to move current somewhere else, making room for our non-migratable * task. */ - if (p->prio == rq->curr->prio && !need_resched()) + if (p->prio == rq->curr->prio && !test_tsk_need_resched(rq->curr)) check_preempt_equal_prio(rq, p); #endif } From 0da938c44921cfb690283d3b0c9c48a10375db2c Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 14 Jun 2011 18:36:25 -0400 Subject: [PATCH 397/595] sched: Check if lowest_mask is initialized in find_lowest_rq() On system boot up, the lowest_mask is initialized with an early_initcall(). But RT tasks may wake up on other early_initcall() callers before the lowest_mask is initialized, causing a system crash. Commit "d72bce0e67 rcu: Cure load woes" was the first commit to wake up RT tasks in early init. Before this commit this bug should not happen. Reported-by: Andrew Theurer Tested-by: Andrew Theurer Tested-by: Paul E. McKenney Signed-off-by: Steven Rostedt Acked-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20110614223657.824872966@goodmis.org Signed-off-by: Ingo Molnar --- kernel/sched_rt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 9b8d5dce946e..10d018212bab 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -1239,6 +1239,10 @@ static int find_lowest_rq(struct task_struct *task) int this_cpu = smp_processor_id(); int cpu = task_cpu(task); + /* Make sure the mask is initialized first */ + if (unlikely(!lowest_mask)) + return -1; + if (task->rt.nr_cpus_allowed == 1) return -1; /* No other targets possible */ From a7b21165c06f28230768d203285d06cac4f18f0b Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Mon, 13 Jun 2011 09:49:27 +0530 Subject: [PATCH 398/595] mwifiex: Fixing NULL pointer dereference Following OOPS was seen when booting with card inserted BUG: unable to handle kernel NULL pointer dereference at 0000004c IP: [] cfg80211_get_drvinfo+0x21/0x115 [cfg80211] *pde = 00000000 Oops: 0000 [#1] SMP Modules linked in: iwl3945 iwl_legacy mwifiex_sdio mac80211 11 sdhci_pci sdhci pl2303 'ethtool' on the mwifiex device returned this OOPS as wiphy_dev() returned NULL. Adding missing set_wiphy_dev() call to fix the problem. Signed-off-by: Yogesh Ashok Powar Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 660831ce293c..687c1f223497 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1288,6 +1288,8 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, *(unsigned long *) wdev_priv = (unsigned long) priv; + set_wiphy_dev(wdev->wiphy, (struct device *) priv->adapter->dev); + ret = wiphy_register(wdev->wiphy); if (ret < 0) { dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", From 3373b28e5af4a0b3c6cb39372581dcc1e41322ff Mon Sep 17 00:00:00 2001 From: Nishant Sarmukadam Date: Mon, 13 Jun 2011 16:26:15 +0530 Subject: [PATCH 399/595] mwl8k: Tell firmware to generate CCMP header Post commit e4eefec73ea0a740bfe8736e3ac30dfe92fe392b, the stack is not generating the CCMP header for us anymore. This broke the CCMP functionality since firmware was not doing this either. Set a flag to tell the firmware to generate the CCMP header Signed-off-by: Nishant Sarmukadam Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 32261189bcef..aeac3cc4dbe4 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2474,6 +2474,7 @@ struct mwl8k_cmd_set_hw_spec { * faster client. */ #define MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY 0x00000400 +#define MWL8K_SET_HW_SPEC_FLAG_GENERATE_CCMP_HDR 0x00000200 #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010 @@ -2510,7 +2511,8 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT | MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP | MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON | - MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY); + MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY | + MWL8K_SET_HW_SPEC_FLAG_GENERATE_CCMP_HDR); cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); From e72888e91cc902ccdc089f237b6eed7587e2b4df Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 15 Jun 2011 15:14:49 +0200 Subject: [PATCH 400/595] ALSA: lola - Fix section mismatch Add missing __devinit. Signed-off-by: Takashi Iwai --- sound/pci/lola/lola.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c index 34b24286d279..2692e5ae5f2d 100644 --- a/sound/pci/lola/lola.c +++ b/sound/pci/lola/lola.c @@ -445,7 +445,7 @@ static void lola_reset_setups(struct lola *chip) lola_setup_all_analog_gains(chip, PLAY, false); /* output, update */ } -static int lola_parse_tree(struct lola *chip) +static int __devinit lola_parse_tree(struct lola *chip) { unsigned int val; int nid, err; From 71d7aed014457147e8f71a843d5fbf03235e4a85 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 14 Jun 2011 14:24:32 -0400 Subject: [PATCH 401/595] Btrfs: fix path leakage on subvol deletion The delayed ref patch accidently removed the btrfs_free_path in btrfs_unlink_subvol, this puts it back and means we don't leak a path. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c15636b17874..5813dec5101c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3076,6 +3076,7 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, ret = btrfs_update_inode(trans, root, dir); BUG_ON(ret); + btrfs_free_path(path); return 0; } From 8351583e3f6e430ce8f71913909a96ad5cc6a2f6 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 14 Jun 2011 15:16:14 -0400 Subject: [PATCH 402/595] Btrfs: protect the pending_snapshots list with trans_lock Currently there is nothing protecting the pending_snapshots list on the transaction. We only hold the directory mutex that we are snapshotting and a read lock on the subvol_sem, so we could race with somebody else creating a snapshot in a different directory and end up with list corruption. So protect this list with the trans_lock. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ioctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index b793d112d1f6..a3c4751e07db 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -482,8 +482,10 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, ret = btrfs_snap_reserve_metadata(trans, pending_snapshot); BUG_ON(ret); + spin_lock(&root->fs_info->trans_lock); list_add(&pending_snapshot->list, &trans->transaction->pending_snapshots); + spin_unlock(&root->fs_info->trans_lock); if (async_transid) { *async_transid = trans->transid; ret = btrfs_commit_transaction_async(trans, From ed0ca14021e5ae3147602128641aa7f742ab227c Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 14 Jun 2011 16:22:15 -0400 Subject: [PATCH 403/595] Btrfs: set no_trans_join after trying to expand the transaction We can lockup if we try to allow new writers join the transaction and we have flushoncommit set or have a pending snapshot. This is because we set no_trans_join and then loop around and try to wait for ordered extents again. The problem is the ordered endio stuff needs to join the transaction, which it can't do because no_trans_join is set. So instead wait until after this loop to set no_trans_join and then make sure to wait for num_writers == 1 in case anybody got started in between us exiting the loop and setting no_trans_join. This could easily be reproduced by mounting -o flushoncommit and running xfstest 13. It cannot be reproduced with this patch. Thanks, Reported-by: Jim Schutt Signed-off-by: Josef Bacik --- fs/btrfs/transaction.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 2b3590b9fe98..56695595e036 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1241,12 +1241,20 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, schedule_timeout(1); finish_wait(&cur_trans->writer_wait, &wait); - spin_lock(&root->fs_info->trans_lock); - root->fs_info->trans_no_join = 1; - spin_unlock(&root->fs_info->trans_lock); } while (atomic_read(&cur_trans->num_writers) > 1 || (should_grow && cur_trans->num_joined != joined)); + /* + * Ok now we need to make sure to block out any other joins while we + * commit the transaction. We could have started a join before setting + * no_join so make sure to wait for num_writers to == 1 again. + */ + spin_lock(&root->fs_info->trans_lock); + root->fs_info->trans_no_join = 1; + spin_unlock(&root->fs_info->trans_lock); + wait_event(cur_trans->writer_wait, + atomic_read(&cur_trans->num_writers) == 1); + ret = create_pending_snapshots(trans, root->fs_info); BUG_ON(ret); From 900cba8881b39dfbc7c8062098504ab93f5387a8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 18 Dec 2009 10:31:31 +0100 Subject: [PATCH 404/595] xen: support CONFIG_MAXSMP The MAXSMP config option requires CPUMASK_OFFSTACK, which in turn requires we init the memory for the maps while we bring up the cpus. MAXSMP also increases NR_CPUS to 4096. This increase in size exposed an issue in the argument construction for multicalls from xen_flush_tlb_others. The args should only need space for the actual number of cpus. Also in 2.6.39 it exposes a bootup problem. BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] set_cpu_sibling_map+0x123/0x30d ... Call Trace: [] ? xen_restore_fl_direct_reloc+0x4/0x4 [] xen_smp_prepare_cpus+0x36/0x135 .. CC: stable@kernel.org Signed-off-by: Andrew Jones [v2: Updated to compile on 3.0] [v3: Updated to compile when CONFIG_SMP is not defined] Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/mmu.c | 3 ++- arch/x86/xen/smp.c | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index afe1d54f980c..673e968df3cf 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include @@ -1231,7 +1232,7 @@ static void xen_flush_tlb_others(const struct cpumask *cpus, { struct { struct mmuext_op op; - DECLARE_BITMAP(mask, NR_CPUS); + DECLARE_BITMAP(mask, num_processors); } *args; struct multicall_space mcs; diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 41038c01de40..b4533a86d7e4 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -205,11 +205,18 @@ static void __init xen_smp_prepare_boot_cpu(void) static void __init xen_smp_prepare_cpus(unsigned int max_cpus) { unsigned cpu; + unsigned int i; xen_init_lock_cpu(0); smp_store_cpu_info(0); cpu_data(0).x86_max_cores = 1; + + for_each_possible_cpu(i) { + zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL); + zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL); + zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL); + } set_cpu_sibling_map(0); if (xen_smp_intr_init(0)) From b5328cd14557880e9eb757a8a9c8a88f1b23533a Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 15 Jun 2011 14:24:29 -0400 Subject: [PATCH 405/595] xen: Fix compile warning when CONFIG_SMP is not defined. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .. which is quite benign. drivers/xen/events.c:398: warning: unused variable ‘desc’ Signed-off-by: Konrad Rzeszutek Wilk --- 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 553da68bd510..30df85d8fca8 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -395,9 +395,9 @@ static void unmask_evtchn(int port) static void xen_irq_init(unsigned irq) { struct irq_info *info; +#ifdef CONFIG_SMP struct irq_desc *desc = irq_to_desc(irq); -#ifdef CONFIG_SMP /* By default all event channels notify CPU#0. */ cpumask_copy(desc->irq_data.affinity, cpumask_of(0)); #endif From 37aa9a2eb4d9b1a4aec1fd18bb2bb6bca029de27 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Wed, 15 Jun 2011 14:35:00 +0100 Subject: [PATCH 406/595] perf: clear out make flags when calling kernel make kernelver When generating the perf version from the kernel version using 'make kernelver' it is necessary to clear out any MAKEFLAGS otherwise they may trigger additional output which pollute the contents. Signed-off-by: Andy Whitcroft Signed-off-by: Michal Marek --- tools/perf/util/PERF-VERSION-GEN | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN index 9c5fb4d93824..ad73300f7bac 100755 --- a/tools/perf/util/PERF-VERSION-GEN +++ b/tools/perf/util/PERF-VERSION-GEN @@ -23,7 +23,7 @@ if test -d ../../.git -o -f ../../.git && then VN=$(echo "$VN" | sed -e 's/-/./g'); else - VN=$(make -sC ../.. kernelversion) + VN=$(MAKEFLAGS= make -sC ../.. kernelversion) fi VN=$(expr "$VN" : v*'\(.*\)') From 569658dddf276ceb0780776e7f5d61d9f8d8cb88 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Wed, 15 Jun 2011 22:15:47 +0200 Subject: [PATCH 407/595] kbuild: Call depmod.sh via shell The script has the executable bit in git, but plain old patch(1) can't create executable files. Reported-by: Tetsuo Handa Signed-off-by: Michal Marek --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 43509373f37a..67640639d8f3 100644 --- a/Makefile +++ b/Makefile @@ -1526,7 +1526,8 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files)) # Run depmod only if we have System.map and depmod is executable quiet_cmd_depmod = DEPMOD $(KERNELRELEASE) - cmd_depmod = $(srctree)/scripts/depmod.sh $(DEPMOD) $(KERNELRELEASE) + cmd_depmod = $(CONFIG_SHELL) $(srctree)/scripts/depmod.sh $(DEPMOD) \ + $(KERNELRELEASE) # Create temporary dir for module support files # clean it up only when building all modules From b2abe50688dcb470e2e46109da7e7e02245ed59b Mon Sep 17 00:00:00 2001 From: Tom Goetz Date: Mon, 16 May 2011 15:06:26 -0400 Subject: [PATCH 408/595] xen: When calling power_off, don't call the halt function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .. As it won't actually power off the machine. Reported-by: Sven Köhler Tested-by: Sven Köhler Signed-off-by: Tom Goetz Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/enlighten.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index dd7b88f2ec7a..5525163a0398 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1033,6 +1033,13 @@ static void xen_machine_halt(void) xen_reboot(SHUTDOWN_poweroff); } +static void xen_machine_power_off(void) +{ + if (pm_power_off) + pm_power_off(); + xen_reboot(SHUTDOWN_poweroff); +} + static void xen_crash_shutdown(struct pt_regs *regs) { xen_reboot(SHUTDOWN_crash); @@ -1058,7 +1065,7 @@ int xen_panic_handler_init(void) static const struct machine_ops xen_machine_ops __initconst = { .restart = xen_restart, .halt = xen_machine_halt, - .power_off = xen_machine_halt, + .power_off = xen_machine_power_off, .shutdown = xen_machine_halt, .crash_shutdown = xen_crash_shutdown, .emergency_restart = xen_emergency_restart, From 793925334f32e9026c22baee5c3c340f47d4ef7e Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 15 Jun 2011 12:47:04 -0700 Subject: [PATCH 409/595] proc: Fix Oops on stat of /proc//ns/net Don't call iput with the inode half setup to be a namespace filedescriptor. Instead rearrange the code so that we don't initialize ei->ns_ops until after I ns_ops->get succeeds, preventing us from invoking ns_ops->put when ns_ops->get failed. Reported-by: Ingo Saitz Signed-off-by: Eric W. Biederman --- fs/proc/namespaces.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c index 781dec5bd682..be177f702acb 100644 --- a/fs/proc/namespaces.c +++ b/fs/proc/namespaces.c @@ -38,18 +38,21 @@ static struct dentry *proc_ns_instantiate(struct inode *dir, struct inode *inode; struct proc_inode *ei; struct dentry *error = ERR_PTR(-ENOENT); + void *ns; inode = proc_pid_make_inode(dir->i_sb, task); if (!inode) goto out; + ns = ns_ops->get(task); + if (!ns) + goto out_iput; + ei = PROC_I(inode); inode->i_mode = S_IFREG|S_IRUSR; inode->i_fop = &ns_file_operations; ei->ns_ops = ns_ops; - ei->ns = ns_ops->get(task); - if (!ei->ns) - goto out_iput; + ei->ns = ns; dentry->d_op = &pid_dentry_operations; d_add(dentry, inode); From f300ea499721ca208fc4714b9105bfd7e9f75be0 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Wed, 15 Jun 2011 15:08:08 -0700 Subject: [PATCH 410/595] mm: remove khugepaged double thp vmstat update with CONFIG_NUMA=n Johannes noticed the vmstat update is already taken care of by khugepaged_alloc_hugepage() internally. The only places that are required to update the vmstat are the callers of alloc_hugepage (callers of khugepaged_alloc_hugepage aren't). Signed-off-by: Andrea Arcangeli Reported-by: Johannes Weiner Acked-by: Rik van Riel Reviewed-by: Minchan Kim Acked-by: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/huge_memory.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 615d9743a3cb..81532f297fd2 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2234,11 +2234,8 @@ static void khugepaged_loop(void) while (likely(khugepaged_enabled())) { #ifndef CONFIG_NUMA hpage = khugepaged_alloc_hugepage(); - if (unlikely(!hpage)) { - count_vm_event(THP_COLLAPSE_ALLOC_FAILED); + if (unlikely(!hpage)) break; - } - count_vm_event(THP_COLLAPSE_ALLOC); #else if (IS_ERR(hpage)) { khugepaged_alloc_sleep(); From 0164f69d0cf1a6abbc936851f5b72ece92187cda Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 15 Jun 2011 15:08:09 -0700 Subject: [PATCH 411/595] mm/memory.c: fix kernel-doc notation Fix new kernel-doc warnings in mm/memory.c: Warning(mm/memory.c:1327): No description found for parameter 'tlb' Warning(mm/memory.c:1327): Excess function parameter 'tlbp' description in 'unmap_vmas' Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memory.c b/mm/memory.c index 6953d3926e01..b13e7dbc399b 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1296,7 +1296,7 @@ static unsigned long unmap_page_range(struct mmu_gather *tlb, /** * unmap_vmas - unmap a range of memory covered by a list of vma's - * @tlbp: address of the caller's struct mmu_gather + * @tlb: address of the caller's struct mmu_gather * @vma: the starting vma * @start_addr: virtual address at which to start unmapping * @end_addr: virtual address at which to end unmapping From b0825ee3a8c570df4873ee397fa453e67fdad5d7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 15 Jun 2011 15:08:10 -0700 Subject: [PATCH 412/595] lib/bitmap.c: fix kernel-doc notation Fix new kernel-doc warnings in lib/bitmap.c: Warning(lib/bitmap.c:596): No description found for parameter 'buf' Warning(lib/bitmap.c:596): Excess function parameter 'bp' description in '__bitmap_parselist' Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bitmap.c b/lib/bitmap.c index 41baf02924e6..3f3b68199d74 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -572,7 +572,7 @@ EXPORT_SYMBOL(bitmap_scnlistprintf); /** * __bitmap_parselist - convert list format ASCII string to bitmap - * @bp: read nul-terminated user string from this buffer + * @buf: read nul-terminated user string from this buffer * @buflen: buffer size in bytes. If string is smaller than this * then it must be terminated with a \0. * @is_user: location of buffer, 0 indicates kernel space From 7f81c8890c15a10f5220bebae3b6dfae4961962a Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Wed, 15 Jun 2011 15:08:11 -0700 Subject: [PATCH 413/595] fs/exec.c: use BUILD_BUG_ON for VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP Commit a8bef8ff6ea1 ("mm: migration: avoid race between shift_arg_pages() and rmap_walk() during migration by not migrating temporary stacks") introduced a BUG_ON() to ensure that VM_STACK_FLAGS and VM_STACK_INCOMPLETE_SETUP do not overlap. The check is a compile time one, so BUILD_BUG_ON is more appropriate. Signed-off-by: Michal Hocko Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/exec.c b/fs/exec.c index 97e0d52d72fd..b54f74f3cd80 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -277,7 +277,7 @@ static int __bprm_mm_init(struct linux_binprm *bprm) * use STACK_TOP because that can depend on attributes which aren't * configured yet. */ - BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP); + BUILD_BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP); vma->vm_end = STACK_TOP_MAX; vma->vm_start = vma->vm_end - PAGE_SIZE; vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP; From a59ec1e7ff98cc4365d5b1bff4e7102e86b5716b Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 15 Jun 2011 15:08:11 -0700 Subject: [PATCH 414/595] backlight: new driver for the ADP8870 backlight devices Signed-off-by: Michael Hennerich Signed-off-by: Mike Frysinger Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- .../sysfs-class-backlight-driver-adp8870 | 56 + drivers/video/backlight/Kconfig | 12 + drivers/video/backlight/Makefile | 1 + drivers/video/backlight/adp8870_bl.c | 1011 +++++++++++++++++ include/linux/i2c/adp8870.h | 153 +++ 5 files changed, 1233 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 create mode 100644 drivers/video/backlight/adp8870_bl.c create mode 100644 include/linux/i2c/adp8870.h diff --git a/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 b/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 new file mode 100644 index 000000000000..aa11dbdd794b --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 @@ -0,0 +1,56 @@ +What: /sys/class/backlight//_max +What: /sys/class/backlight//l1_daylight_max +What: /sys/class/backlight//l2_bright_max +What: /sys/class/backlight//l3_office_max +What: /sys/class/backlight//l4_indoor_max +What: /sys/class/backlight//l5_dark_max +Date: Mai 2011 +KernelVersion: 2.6.40 +Contact: device-drivers-devel@blackfin.uclinux.org +Description: + Control the maximum brightness for + on this . Values are between 0 and 127. This file + will also show the brightness level stored for this + . + +What: /sys/class/backlight//_dim +What: /sys/class/backlight//l2_bright_dim +What: /sys/class/backlight//l3_office_dim +What: /sys/class/backlight//l4_indoor_dim +What: /sys/class/backlight//l5_dark_dim +Date: Mai 2011 +KernelVersion: 2.6.40 +Contact: device-drivers-devel@blackfin.uclinux.org +Description: + Control the dim brightness for + on this . Values are between 0 and 127, typically + set to 0. Full off when the backlight is disabled. + This file will also show the dim brightness level stored for + this . + +What: /sys/class/backlight//ambient_light_level +Date: Mai 2011 +KernelVersion: 2.6.40 +Contact: device-drivers-devel@blackfin.uclinux.org +Description: + Get conversion value of the light sensor. + This value is updated every 80 ms (when the light sensor + is enabled). Returns integer between 0 (dark) and + 8000 (max ambient brightness) + +What: /sys/class/backlight//ambient_light_zone +Date: Mai 2011 +KernelVersion: 2.6.40 +Contact: device-drivers-devel@blackfin.uclinux.org +Description: + Get/Set current ambient light zone. Reading returns + integer between 1..5 (1 = daylight, 2 = bright, ..., 5 = dark). + Writing a value between 1..5 forces the backlight controller + to enter the corresponding ambient light zone. + Writing 0 returns to normal/automatic ambient light level + operation. The ambient light sensing feature on these devices + is an extension to the API documented in + Documentation/ABI/stable/sysfs-class-backlight. + It can be enabled by writing the value stored in + /sys/class/backlight//max_brightness to + /sys/class/backlight//brightness. \ No newline at end of file diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 0c9373bedd1f..2d93c8d61ad5 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -302,6 +302,18 @@ config BACKLIGHT_ADP8860 To compile this driver as a module, choose M here: the module will be called adp8860_bl. +config BACKLIGHT_ADP8870 + tristate "Backlight Driver for ADP8870 using WLED" + depends on BACKLIGHT_CLASS_DEVICE && I2C + select NEW_LEDS + select LEDS_CLASS + help + If you have a LCD backlight connected to the ADP8870, + say Y here to enable this driver. + + To compile this driver as a module, choose M here: the module will + be called adp8870_bl. + config BACKLIGHT_88PM860X tristate "Backlight Driver for 88PM8606 using WLED" depends on MFD_88PM860X diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index b9ca8490df87..ee72adb8786e 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o +obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c new file mode 100644 index 000000000000..e320b62576e2 --- /dev/null +++ b/drivers/video/backlight/adp8870_bl.c @@ -0,0 +1,1011 @@ +/* + * Backlight driver for Analog Devices ADP8870 Backlight Devices + * + * Copyright 2009-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#define ADP8870_EXT_FEATURES +#define ADP8870_USE_LEDS + + +#define ADP8870_MFDVID 0x00 /* Manufacturer and device ID */ +#define ADP8870_MDCR 0x01 /* Device mode and status */ +#define ADP8870_INT_STAT 0x02 /* Interrupts status */ +#define ADP8870_INT_EN 0x03 /* Interrupts enable */ +#define ADP8870_CFGR 0x04 /* Configuration register */ +#define ADP8870_BLSEL 0x05 /* Sink enable backlight or independent */ +#define ADP8870_PWMLED 0x06 /* PWM Enable Selection Register */ +#define ADP8870_BLOFF 0x07 /* Backlight off timeout */ +#define ADP8870_BLDIM 0x08 /* Backlight dim timeout */ +#define ADP8870_BLFR 0x09 /* Backlight fade in and out rates */ +#define ADP8870_BLMX1 0x0A /* Backlight (Brightness Level 1-daylight) maximum current */ +#define ADP8870_BLDM1 0x0B /* Backlight (Brightness Level 1-daylight) dim current */ +#define ADP8870_BLMX2 0x0C /* Backlight (Brightness Level 2-bright) maximum current */ +#define ADP8870_BLDM2 0x0D /* Backlight (Brightness Level 2-bright) dim current */ +#define ADP8870_BLMX3 0x0E /* Backlight (Brightness Level 3-office) maximum current */ +#define ADP8870_BLDM3 0x0F /* Backlight (Brightness Level 3-office) dim current */ +#define ADP8870_BLMX4 0x10 /* Backlight (Brightness Level 4-indoor) maximum current */ +#define ADP8870_BLDM4 0x11 /* Backlight (Brightness Level 4-indoor) dim current */ +#define ADP8870_BLMX5 0x12 /* Backlight (Brightness Level 5-dark) maximum current */ +#define ADP8870_BLDM5 0x13 /* Backlight (Brightness Level 5-dark) dim current */ +#define ADP8870_ISCLAW 0x1A /* Independent sink current fade law register */ +#define ADP8870_ISCC 0x1B /* Independent sink current control register */ +#define ADP8870_ISCT1 0x1C /* Independent Sink Current Timer Register LED[7:5] */ +#define ADP8870_ISCT2 0x1D /* Independent Sink Current Timer Register LED[4:1] */ +#define ADP8870_ISCF 0x1E /* Independent sink current fade register */ +#define ADP8870_ISC1 0x1F /* Independent Sink Current LED1 */ +#define ADP8870_ISC2 0x20 /* Independent Sink Current LED2 */ +#define ADP8870_ISC3 0x21 /* Independent Sink Current LED3 */ +#define ADP8870_ISC4 0x22 /* Independent Sink Current LED4 */ +#define ADP8870_ISC5 0x23 /* Independent Sink Current LED5 */ +#define ADP8870_ISC6 0x24 /* Independent Sink Current LED6 */ +#define ADP8870_ISC7 0x25 /* Independent Sink Current LED7 (Brightness Level 1-daylight) */ +#define ADP8870_ISC7_L2 0x26 /* Independent Sink Current LED7 (Brightness Level 2-bright) */ +#define ADP8870_ISC7_L3 0x27 /* Independent Sink Current LED7 (Brightness Level 3-office) */ +#define ADP8870_ISC7_L4 0x28 /* Independent Sink Current LED7 (Brightness Level 4-indoor) */ +#define ADP8870_ISC7_L5 0x29 /* Independent Sink Current LED7 (Brightness Level 5-dark) */ +#define ADP8870_CMP_CTL 0x2D /* ALS Comparator Control Register */ +#define ADP8870_ALS1_EN 0x2E /* Main ALS comparator level enable */ +#define ADP8870_ALS2_EN 0x2F /* Second ALS comparator level enable */ +#define ADP8870_ALS1_STAT 0x30 /* Main ALS Comparator Status Register */ +#define ADP8870_ALS2_STAT 0x31 /* Second ALS Comparator Status Register */ +#define ADP8870_L2TRP 0x32 /* L2 comparator reference */ +#define ADP8870_L2HYS 0x33 /* L2 hysteresis */ +#define ADP8870_L3TRP 0x34 /* L3 comparator reference */ +#define ADP8870_L3HYS 0x35 /* L3 hysteresis */ +#define ADP8870_L4TRP 0x36 /* L4 comparator reference */ +#define ADP8870_L4HYS 0x37 /* L4 hysteresis */ +#define ADP8870_L5TRP 0x38 /* L5 comparator reference */ +#define ADP8870_L5HYS 0x39 /* L5 hysteresis */ +#define ADP8870_PH1LEVL 0x40 /* First phototransistor ambient light level-low byte register */ +#define ADP8870_PH1LEVH 0x41 /* First phototransistor ambient light level-high byte register */ +#define ADP8870_PH2LEVL 0x42 /* Second phototransistor ambient light level-low byte register */ +#define ADP8870_PH2LEVH 0x43 /* Second phototransistor ambient light level-high byte register */ + +#define ADP8870_MANUFID 0x3 /* Analog Devices AD8870 Manufacturer and device ID */ +#define ADP8870_DEVID(x) ((x) & 0xF) +#define ADP8870_MANID(x) ((x) >> 4) + +/* MDCR Device mode and status */ +#define D7ALSEN (1 << 7) +#define INT_CFG (1 << 6) +#define NSTBY (1 << 5) +#define DIM_EN (1 << 4) +#define GDWN_DIS (1 << 3) +#define SIS_EN (1 << 2) +#define CMP_AUTOEN (1 << 1) +#define BLEN (1 << 0) + +/* ADP8870_ALS1_EN Main ALS comparator level enable */ +#define L5_EN (1 << 3) +#define L4_EN (1 << 2) +#define L3_EN (1 << 1) +#define L2_EN (1 << 0) + +#define CFGR_BLV_SHIFT 3 +#define CFGR_BLV_MASK 0x7 +#define ADP8870_FLAG_LED_MASK 0xFF + +#define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4)) +#define BL_CFGR_VAL(law, blv) ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1)) +#define ALS_CMPR_CFG_VAL(filt) ((0x7 & (filt)) << 1) + +struct adp8870_bl { + struct i2c_client *client; + struct backlight_device *bl; + struct adp8870_led *led; + struct adp8870_backlight_platform_data *pdata; + struct mutex lock; + unsigned long cached_daylight_max; + int id; + int revid; + int current_brightness; +}; + +struct adp8870_led { + struct led_classdev cdev; + struct work_struct work; + struct i2c_client *client; + enum led_brightness new_brightness; + int id; + int flags; +}; + +static int adp8870_read(struct i2c_client *client, int reg, uint8_t *val) +{ + int ret; + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret < 0) { + dev_err(&client->dev, "failed reading at 0x%02x\n", reg); + return ret; + } + + *val = ret; + return 0; +} + + +static int adp8870_write(struct i2c_client *client, u8 reg, u8 val) +{ + int ret = i2c_smbus_write_byte_data(client, reg, val); + if (ret) + dev_err(&client->dev, "failed to write\n"); + + return ret; +} + +static int adp8870_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask) +{ + struct adp8870_bl *data = i2c_get_clientdata(client); + uint8_t reg_val; + int ret; + + mutex_lock(&data->lock); + + ret = adp8870_read(client, reg, ®_val); + + if (!ret && ((reg_val & bit_mask) == 0)) { + reg_val |= bit_mask; + ret = adp8870_write(client, reg, reg_val); + } + + mutex_unlock(&data->lock); + return ret; +} + +static int adp8870_clr_bits(struct i2c_client *client, int reg, uint8_t bit_mask) +{ + struct adp8870_bl *data = i2c_get_clientdata(client); + uint8_t reg_val; + int ret; + + mutex_lock(&data->lock); + + ret = adp8870_read(client, reg, ®_val); + + if (!ret && (reg_val & bit_mask)) { + reg_val &= ~bit_mask; + ret = adp8870_write(client, reg, reg_val); + } + + mutex_unlock(&data->lock); + return ret; +} + +/* + * Independent sink / LED + */ +#if defined(ADP8870_USE_LEDS) +static void adp8870_led_work(struct work_struct *work) +{ + struct adp8870_led *led = container_of(work, struct adp8870_led, work); + adp8870_write(led->client, ADP8870_ISC1 + led->id - 1, + led->new_brightness >> 1); +} + +static void adp8870_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct adp8870_led *led; + + led = container_of(led_cdev, struct adp8870_led, cdev); + led->new_brightness = value; + /* + * Use workqueue for IO since I2C operations can sleep. + */ + schedule_work(&led->work); +} + +static int adp8870_led_setup(struct adp8870_led *led) +{ + struct i2c_client *client = led->client; + int ret = 0; + + ret = adp8870_write(client, ADP8870_ISC1 + led->id - 1, 0); + if (ret) + return ret; + + ret = adp8870_set_bits(client, ADP8870_ISCC, 1 << (led->id - 1)); + if (ret) + return ret; + + if (led->id > 4) + ret = adp8870_set_bits(client, ADP8870_ISCT1, + (led->flags & 0x3) << ((led->id - 5) * 2)); + else + ret = adp8870_set_bits(client, ADP8870_ISCT2, + (led->flags & 0x3) << ((led->id - 1) * 2)); + + return ret; +} + +static int __devinit adp8870_led_probe(struct i2c_client *client) +{ + struct adp8870_backlight_platform_data *pdata = + client->dev.platform_data; + struct adp8870_bl *data = i2c_get_clientdata(client); + struct adp8870_led *led, *led_dat; + struct led_info *cur_led; + int ret, i; + + + led = kcalloc(pdata->num_leds, sizeof(*led), GFP_KERNEL); + if (led == NULL) { + dev_err(&client->dev, "failed to alloc memory\n"); + return -ENOMEM; + } + + ret = adp8870_write(client, ADP8870_ISCLAW, pdata->led_fade_law); + if (ret) + goto err_free; + + ret = adp8870_write(client, ADP8870_ISCT1, + (pdata->led_on_time & 0x3) << 6); + if (ret) + goto err_free; + + ret = adp8870_write(client, ADP8870_ISCF, + FADE_VAL(pdata->led_fade_in, pdata->led_fade_out)); + if (ret) + goto err_free; + + for (i = 0; i < pdata->num_leds; ++i) { + cur_led = &pdata->leds[i]; + led_dat = &led[i]; + + led_dat->id = cur_led->flags & ADP8870_FLAG_LED_MASK; + + if (led_dat->id > 7 || led_dat->id < 1) { + dev_err(&client->dev, "Invalid LED ID %d\n", + led_dat->id); + goto err; + } + + if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) { + dev_err(&client->dev, "LED %d used by Backlight\n", + led_dat->id); + goto err; + } + + led_dat->cdev.name = cur_led->name; + led_dat->cdev.default_trigger = cur_led->default_trigger; + led_dat->cdev.brightness_set = adp8870_led_set; + led_dat->cdev.brightness = LED_OFF; + led_dat->flags = cur_led->flags >> FLAG_OFFT_SHIFT; + led_dat->client = client; + led_dat->new_brightness = LED_OFF; + INIT_WORK(&led_dat->work, adp8870_led_work); + + ret = led_classdev_register(&client->dev, &led_dat->cdev); + if (ret) { + dev_err(&client->dev, "failed to register LED %d\n", + led_dat->id); + goto err; + } + + ret = adp8870_led_setup(led_dat); + if (ret) { + dev_err(&client->dev, "failed to write\n"); + i++; + goto err; + } + } + + data->led = led; + + return 0; + + err: + for (i = i - 1; i >= 0; --i) { + led_classdev_unregister(&led[i].cdev); + cancel_work_sync(&led[i].work); + } + + err_free: + kfree(led); + + return ret; +} + +static int __devexit adp8870_led_remove(struct i2c_client *client) +{ + struct adp8870_backlight_platform_data *pdata = + client->dev.platform_data; + struct adp8870_bl *data = i2c_get_clientdata(client); + int i; + + for (i = 0; i < pdata->num_leds; i++) { + led_classdev_unregister(&data->led[i].cdev); + cancel_work_sync(&data->led[i].work); + } + + kfree(data->led); + return 0; +} +#else +static int __devinit adp8870_led_probe(struct i2c_client *client) +{ + return 0; +} + +static int __devexit adp8870_led_remove(struct i2c_client *client) +{ + return 0; +} +#endif + +static int adp8870_bl_set(struct backlight_device *bl, int brightness) +{ + struct adp8870_bl *data = bl_get_data(bl); + struct i2c_client *client = data->client; + int ret = 0; + + if (data->pdata->en_ambl_sens) { + if ((brightness > 0) && (brightness < ADP8870_MAX_BRIGHTNESS)) { + /* Disable Ambient Light auto adjust */ + ret = adp8870_clr_bits(client, ADP8870_MDCR, + CMP_AUTOEN); + if (ret) + return ret; + ret = adp8870_write(client, ADP8870_BLMX1, brightness); + if (ret) + return ret; + } else { + /* + * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust + * restore daylight l1 sysfs brightness + */ + ret = adp8870_write(client, ADP8870_BLMX1, + data->cached_daylight_max); + if (ret) + return ret; + + ret = adp8870_set_bits(client, ADP8870_MDCR, + CMP_AUTOEN); + if (ret) + return ret; + } + } else { + ret = adp8870_write(client, ADP8870_BLMX1, brightness); + if (ret) + return ret; + } + + if (data->current_brightness && brightness == 0) + ret = adp8870_set_bits(client, + ADP8870_MDCR, DIM_EN); + else if (data->current_brightness == 0 && brightness) + ret = adp8870_clr_bits(client, + ADP8870_MDCR, DIM_EN); + + if (!ret) + data->current_brightness = brightness; + + return ret; +} + +static int adp8870_bl_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + if (bl->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + return adp8870_bl_set(bl, brightness); +} + +static int adp8870_bl_get_brightness(struct backlight_device *bl) +{ + struct adp8870_bl *data = bl_get_data(bl); + + return data->current_brightness; +} + +static const struct backlight_ops adp8870_bl_ops = { + .update_status = adp8870_bl_update_status, + .get_brightness = adp8870_bl_get_brightness, +}; + +static int adp8870_bl_setup(struct backlight_device *bl) +{ + struct adp8870_bl *data = bl_get_data(bl); + struct i2c_client *client = data->client; + struct adp8870_backlight_platform_data *pdata = data->pdata; + int ret = 0; + + ret = adp8870_write(client, ADP8870_BLSEL, ~pdata->bl_led_assign); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_PWMLED, pdata->pwm_assign); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLMX1, pdata->l1_daylight_max); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLDM1, pdata->l1_daylight_dim); + if (ret) + return ret; + + if (pdata->en_ambl_sens) { + data->cached_daylight_max = pdata->l1_daylight_max; + ret = adp8870_write(client, ADP8870_BLMX2, + pdata->l2_bright_max); + if (ret) + return ret; + ret = adp8870_write(client, ADP8870_BLDM2, + pdata->l2_bright_dim); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLMX3, + pdata->l3_office_max); + if (ret) + return ret; + ret = adp8870_write(client, ADP8870_BLDM3, + pdata->l3_office_dim); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLMX4, + pdata->l4_indoor_max); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLDM4, + pdata->l4_indor_dim); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLMX5, + pdata->l5_dark_max); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLDM5, + pdata->l5_dark_dim); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L2TRP, pdata->l2_trip); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L2HYS, pdata->l2_hyst); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L3TRP, pdata->l3_trip); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L3HYS, pdata->l3_hyst); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L4TRP, pdata->l4_trip); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L4HYS, pdata->l4_hyst); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L5TRP, pdata->l5_trip); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L5HYS, pdata->l5_hyst); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_ALS1_EN, L5_EN | L4_EN | + L3_EN | L2_EN); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_CMP_CTL, + ALS_CMPR_CFG_VAL(pdata->abml_filt)); + if (ret) + return ret; + } + + ret = adp8870_write(client, ADP8870_CFGR, + BL_CFGR_VAL(pdata->bl_fade_law, 0)); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLFR, FADE_VAL(pdata->bl_fade_in, + pdata->bl_fade_out)); + if (ret) + return ret; + /* + * ADP8870 Rev0 requires GDWN_DIS bit set + */ + + ret = adp8870_set_bits(client, ADP8870_MDCR, BLEN | DIM_EN | NSTBY | + (data->revid == 0 ? GDWN_DIS : 0)); + + return ret; +} + +static ssize_t adp8870_show(struct device *dev, char *buf, int reg) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + int error; + uint8_t reg_val; + + mutex_lock(&data->lock); + error = adp8870_read(data->client, reg, ®_val); + mutex_unlock(&data->lock); + + if (error < 0) + return error; + + return sprintf(buf, "%u\n", reg_val); +} + +static ssize_t adp8870_store(struct device *dev, const char *buf, + size_t count, int reg) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + unsigned long val; + int ret; + + ret = strict_strtoul(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&data->lock); + adp8870_write(data->client, reg, val); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t adp8870_bl_l5_dark_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX5); +} + +static ssize_t adp8870_bl_l5_dark_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLMX5); +} +static DEVICE_ATTR(l5_dark_max, 0664, adp8870_bl_l5_dark_max_show, + adp8870_bl_l5_dark_max_store); + + +static ssize_t adp8870_bl_l4_indoor_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX4); +} + +static ssize_t adp8870_bl_l4_indoor_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLMX4); +} +static DEVICE_ATTR(l4_indoor_max, 0664, adp8870_bl_l4_indoor_max_show, + adp8870_bl_l4_indoor_max_store); + + +static ssize_t adp8870_bl_l3_office_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX3); +} + +static ssize_t adp8870_bl_l3_office_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLMX3); +} + +static DEVICE_ATTR(l3_office_max, 0664, adp8870_bl_l3_office_max_show, + adp8870_bl_l3_office_max_store); + +static ssize_t adp8870_bl_l2_bright_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX2); +} + +static ssize_t adp8870_bl_l2_bright_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLMX2); +} +static DEVICE_ATTR(l2_bright_max, 0664, adp8870_bl_l2_bright_max_show, + adp8870_bl_l2_bright_max_store); + +static ssize_t adp8870_bl_l1_daylight_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX1); +} + +static ssize_t adp8870_bl_l1_daylight_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + int ret = strict_strtoul(buf, 10, &data->cached_daylight_max); + if (ret) + return ret; + + return adp8870_store(dev, buf, count, ADP8870_BLMX1); +} +static DEVICE_ATTR(l1_daylight_max, 0664, adp8870_bl_l1_daylight_max_show, + adp8870_bl_l1_daylight_max_store); + +static ssize_t adp8870_bl_l5_dark_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM5); +} + +static ssize_t adp8870_bl_l5_dark_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM5); +} +static DEVICE_ATTR(l5_dark_dim, 0664, adp8870_bl_l5_dark_dim_show, + adp8870_bl_l5_dark_dim_store); + +static ssize_t adp8870_bl_l4_indoor_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM4); +} + +static ssize_t adp8870_bl_l4_indoor_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM4); +} +static DEVICE_ATTR(l4_indoor_dim, 0664, adp8870_bl_l4_indoor_dim_show, + adp8870_bl_l4_indoor_dim_store); + + +static ssize_t adp8870_bl_l3_office_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM3); +} + +static ssize_t adp8870_bl_l3_office_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM3); +} +static DEVICE_ATTR(l3_office_dim, 0664, adp8870_bl_l3_office_dim_show, + adp8870_bl_l3_office_dim_store); + +static ssize_t adp8870_bl_l2_bright_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM2); +} + +static ssize_t adp8870_bl_l2_bright_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM2); +} +static DEVICE_ATTR(l2_bright_dim, 0664, adp8870_bl_l2_bright_dim_show, + adp8870_bl_l2_bright_dim_store); + +static ssize_t adp8870_bl_l1_daylight_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM1); +} + +static ssize_t adp8870_bl_l1_daylight_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM1); +} +static DEVICE_ATTR(l1_daylight_dim, 0664, adp8870_bl_l1_daylight_dim_show, + adp8870_bl_l1_daylight_dim_store); + +#ifdef ADP8870_EXT_FEATURES +static ssize_t adp8870_bl_ambient_light_level_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + int error; + uint8_t reg_val; + uint16_t ret_val; + + mutex_lock(&data->lock); + error = adp8870_read(data->client, ADP8870_PH1LEVL, ®_val); + if (error < 0) { + mutex_unlock(&data->lock); + return error; + } + ret_val = reg_val; + error = adp8870_read(data->client, ADP8870_PH1LEVH, ®_val); + mutex_unlock(&data->lock); + + if (error < 0) + return error; + + /* Return 13-bit conversion value for the first light sensor */ + ret_val += (reg_val & 0x1F) << 8; + + return sprintf(buf, "%u\n", ret_val); +} +static DEVICE_ATTR(ambient_light_level, 0444, + adp8870_bl_ambient_light_level_show, NULL); + +static ssize_t adp8870_bl_ambient_light_zone_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + int error; + uint8_t reg_val; + + mutex_lock(&data->lock); + error = adp8870_read(data->client, ADP8870_CFGR, ®_val); + mutex_unlock(&data->lock); + + if (error < 0) + return error; + + return sprintf(buf, "%u\n", + ((reg_val >> CFGR_BLV_SHIFT) & CFGR_BLV_MASK) + 1); +} + +static ssize_t adp8870_bl_ambient_light_zone_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + unsigned long val; + uint8_t reg_val; + int ret; + + ret = strict_strtoul(buf, 10, &val); + if (ret) + return ret; + + if (val == 0) { + /* Enable automatic ambient light sensing */ + adp8870_set_bits(data->client, ADP8870_MDCR, CMP_AUTOEN); + } else if ((val > 0) && (val < 6)) { + /* Disable automatic ambient light sensing */ + adp8870_clr_bits(data->client, ADP8870_MDCR, CMP_AUTOEN); + + /* Set user supplied ambient light zone */ + mutex_lock(&data->lock); + adp8870_read(data->client, ADP8870_CFGR, ®_val); + reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT); + reg_val |= (val - 1) << CFGR_BLV_SHIFT; + adp8870_write(data->client, ADP8870_CFGR, reg_val); + mutex_unlock(&data->lock); + } + + return count; +} +static DEVICE_ATTR(ambient_light_zone, 0664, + adp8870_bl_ambient_light_zone_show, + adp8870_bl_ambient_light_zone_store); +#endif + +static struct attribute *adp8870_bl_attributes[] = { + &dev_attr_l5_dark_max.attr, + &dev_attr_l5_dark_dim.attr, + &dev_attr_l4_indoor_max.attr, + &dev_attr_l4_indoor_dim.attr, + &dev_attr_l3_office_max.attr, + &dev_attr_l3_office_dim.attr, + &dev_attr_l2_bright_max.attr, + &dev_attr_l2_bright_dim.attr, + &dev_attr_l1_daylight_max.attr, + &dev_attr_l1_daylight_dim.attr, +#ifdef ADP8870_EXT_FEATURES + &dev_attr_ambient_light_level.attr, + &dev_attr_ambient_light_zone.attr, +#endif + NULL +}; + +static const struct attribute_group adp8870_bl_attr_group = { + .attrs = adp8870_bl_attributes, +}; + +static int __devinit adp8870_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct backlight_properties props; + struct backlight_device *bl; + struct adp8870_bl *data; + struct adp8870_backlight_platform_data *pdata = + client->dev.platform_data; + uint8_t reg_val; + int ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); + return -EIO; + } + + if (!pdata) { + dev_err(&client->dev, "no platform data?\n"); + return -EINVAL; + } + + ret = adp8870_read(client, ADP8870_MFDVID, ®_val); + if (ret < 0) + return -EIO; + + if (ADP8870_MANID(reg_val) != ADP8870_MANUFID) { + dev_err(&client->dev, "failed to probe\n"); + return -ENODEV; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + data->revid = ADP8870_DEVID(reg_val); + data->client = client; + data->pdata = pdata; + data->id = id->driver_data; + data->current_brightness = 0; + i2c_set_clientdata(client, data); + + mutex_init(&data->lock); + + memset(&props, 0, sizeof(props)); + props.max_brightness = props.brightness = ADP8870_MAX_BRIGHTNESS; + bl = backlight_device_register(dev_driver_string(&client->dev), + &client->dev, data, &adp8870_bl_ops, &props); + if (IS_ERR(bl)) { + dev_err(&client->dev, "failed to register backlight\n"); + ret = PTR_ERR(bl); + goto out2; + } + + data->bl = bl; + + if (pdata->en_ambl_sens) + ret = sysfs_create_group(&bl->dev.kobj, + &adp8870_bl_attr_group); + + if (ret) { + dev_err(&client->dev, "failed to register sysfs\n"); + goto out1; + } + + ret = adp8870_bl_setup(bl); + if (ret) { + ret = -EIO; + goto out; + } + + backlight_update_status(bl); + + dev_info(&client->dev, "Rev.%d Backlight\n", data->revid); + + if (pdata->num_leds) + adp8870_led_probe(client); + + return 0; + +out: + if (data->pdata->en_ambl_sens) + sysfs_remove_group(&data->bl->dev.kobj, + &adp8870_bl_attr_group); +out1: + backlight_device_unregister(bl); +out2: + i2c_set_clientdata(client, NULL); + kfree(data); + + return ret; +} + +static int __devexit adp8870_remove(struct i2c_client *client) +{ + struct adp8870_bl *data = i2c_get_clientdata(client); + + adp8870_clr_bits(client, ADP8870_MDCR, NSTBY); + + if (data->led) + adp8870_led_remove(client); + + if (data->pdata->en_ambl_sens) + sysfs_remove_group(&data->bl->dev.kobj, + &adp8870_bl_attr_group); + + backlight_device_unregister(data->bl); + i2c_set_clientdata(client, NULL); + kfree(data); + + return 0; +} + +#ifdef CONFIG_PM +static int adp8870_i2c_suspend(struct i2c_client *client, pm_message_t message) +{ + adp8870_clr_bits(client, ADP8870_MDCR, NSTBY); + + return 0; +} + +static int adp8870_i2c_resume(struct i2c_client *client) +{ + adp8870_set_bits(client, ADP8870_MDCR, NSTBY); + + return 0; +} +#else +#define adp8870_i2c_suspend NULL +#define adp8870_i2c_resume NULL +#endif + +static const struct i2c_device_id adp8870_id[] = { + { "adp8870", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adp8870_id); + +static struct i2c_driver adp8870_driver = { + .driver = { + .name = KBUILD_MODNAME, + }, + .probe = adp8870_probe, + .remove = __devexit_p(adp8870_remove), + .suspend = adp8870_i2c_suspend, + .resume = adp8870_i2c_resume, + .id_table = adp8870_id, +}; + +static int __init adp8870_init(void) +{ + return i2c_add_driver(&adp8870_driver); +} +module_init(adp8870_init); + +static void __exit adp8870_exit(void) +{ + i2c_del_driver(&adp8870_driver); +} +module_exit(adp8870_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("ADP8870 Backlight driver"); +MODULE_ALIAS("platform:adp8870-backlight"); diff --git a/include/linux/i2c/adp8870.h b/include/linux/i2c/adp8870.h new file mode 100644 index 000000000000..624dceccbd5b --- /dev/null +++ b/include/linux/i2c/adp8870.h @@ -0,0 +1,153 @@ +/* + * Definitions and platform data for Analog Devices + * Backlight drivers ADP8870 + * + * Copyright 2009-2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __LINUX_I2C_ADP8870_H +#define __LINUX_I2C_ADP8870_H + +#define ID_ADP8870 8870 + +#define ADP8870_MAX_BRIGHTNESS 0x7F +#define FLAG_OFFT_SHIFT 8 + +/* + * LEDs subdevice platform data + */ + +#define ADP8870_LED_DIS_BLINK (0 << FLAG_OFFT_SHIFT) +#define ADP8870_LED_OFFT_600ms (1 << FLAG_OFFT_SHIFT) +#define ADP8870_LED_OFFT_1200ms (2 << FLAG_OFFT_SHIFT) +#define ADP8870_LED_OFFT_1800ms (3 << FLAG_OFFT_SHIFT) + +#define ADP8870_LED_ONT_200ms 0 +#define ADP8870_LED_ONT_600ms 1 +#define ADP8870_LED_ONT_800ms 2 +#define ADP8870_LED_ONT_1200ms 3 + +#define ADP8870_LED_D7 (7) +#define ADP8870_LED_D6 (6) +#define ADP8870_LED_D5 (5) +#define ADP8870_LED_D4 (4) +#define ADP8870_LED_D3 (3) +#define ADP8870_LED_D2 (2) +#define ADP8870_LED_D1 (1) + +/* + * Backlight subdevice platform data + */ + +#define ADP8870_BL_D7 (1 << 6) +#define ADP8870_BL_D6 (1 << 5) +#define ADP8870_BL_D5 (1 << 4) +#define ADP8870_BL_D4 (1 << 3) +#define ADP8870_BL_D3 (1 << 2) +#define ADP8870_BL_D2 (1 << 1) +#define ADP8870_BL_D1 (1 << 0) + +#define ADP8870_FADE_T_DIS 0 /* Fade Timer Disabled */ +#define ADP8870_FADE_T_300ms 1 /* 0.3 Sec */ +#define ADP8870_FADE_T_600ms 2 +#define ADP8870_FADE_T_900ms 3 +#define ADP8870_FADE_T_1200ms 4 +#define ADP8870_FADE_T_1500ms 5 +#define ADP8870_FADE_T_1800ms 6 +#define ADP8870_FADE_T_2100ms 7 +#define ADP8870_FADE_T_2400ms 8 +#define ADP8870_FADE_T_2700ms 9 +#define ADP8870_FADE_T_3000ms 10 +#define ADP8870_FADE_T_3500ms 11 +#define ADP8870_FADE_T_4000ms 12 +#define ADP8870_FADE_T_4500ms 13 +#define ADP8870_FADE_T_5000ms 14 +#define ADP8870_FADE_T_5500ms 15 /* 5.5 Sec */ + +#define ADP8870_FADE_LAW_LINEAR 0 +#define ADP8870_FADE_LAW_SQUARE 1 +#define ADP8870_FADE_LAW_CUBIC1 2 +#define ADP8870_FADE_LAW_CUBIC2 3 + +#define ADP8870_BL_AMBL_FILT_80ms 0 /* Light sensor filter time */ +#define ADP8870_BL_AMBL_FILT_160ms 1 +#define ADP8870_BL_AMBL_FILT_320ms 2 +#define ADP8870_BL_AMBL_FILT_640ms 3 +#define ADP8870_BL_AMBL_FILT_1280ms 4 +#define ADP8870_BL_AMBL_FILT_2560ms 5 +#define ADP8870_BL_AMBL_FILT_5120ms 6 +#define ADP8870_BL_AMBL_FILT_10240ms 7 /* 10.24 sec */ + +/* + * Blacklight current 0..30mA + */ +#define ADP8870_BL_CUR_mA(I) ((I * 127) / 30) + +/* + * L2 comparator current 0..1106uA + */ +#define ADP8870_L2_COMP_CURR_uA(I) ((I * 255) / 1106) + +/* + * L3 comparator current 0..551uA + */ +#define ADP8870_L3_COMP_CURR_uA(I) ((I * 255) / 551) + +/* + * L4 comparator current 0..275uA + */ +#define ADP8870_L4_COMP_CURR_uA(I) ((I * 255) / 275) + +/* + * L5 comparator current 0..138uA + */ +#define ADP8870_L5_COMP_CURR_uA(I) ((I * 255) / 138) + +struct adp8870_backlight_platform_data { + u8 bl_led_assign; /* 1 = Backlight 0 = Individual LED */ + u8 pwm_assign; /* 1 = Enables PWM mode */ + + u8 bl_fade_in; /* Backlight Fade-In Timer */ + u8 bl_fade_out; /* Backlight Fade-Out Timer */ + u8 bl_fade_law; /* fade-on/fade-off transfer characteristic */ + + u8 en_ambl_sens; /* 1 = enable ambient light sensor */ + u8 abml_filt; /* Light sensor filter time */ + + u8 l1_daylight_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l1_daylight_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l2_bright_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l2_bright_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l3_office_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l3_office_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l4_indoor_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l4_indor_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l5_dark_max; /* use BL_CUR_mA(I) 0 <= I <= 30 mA */ + u8 l5_dark_dim; /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */ + + u8 l2_trip; /* use L2_COMP_CURR_uA(I) 0 <= I <= 1106 uA */ + u8 l2_hyst; /* use L2_COMP_CURR_uA(I) 0 <= I <= 1106 uA */ + u8 l3_trip; /* use L3_COMP_CURR_uA(I) 0 <= I <= 551 uA */ + u8 l3_hyst; /* use L3_COMP_CURR_uA(I) 0 <= I <= 551 uA */ + u8 l4_trip; /* use L4_COMP_CURR_uA(I) 0 <= I <= 275 uA */ + u8 l4_hyst; /* use L4_COMP_CURR_uA(I) 0 <= I <= 275 uA */ + u8 l5_trip; /* use L5_COMP_CURR_uA(I) 0 <= I <= 138 uA */ + u8 l5_hyst; /* use L6_COMP_CURR_uA(I) 0 <= I <= 138 uA */ + + /** + * Independent Current Sinks / LEDS + * Sinks not assigned to the Backlight can be exposed to + * user space using the LEDS CLASS interface + */ + + int num_leds; + struct led_info *leds; + u8 led_fade_in; /* LED Fade-In Timer */ + u8 led_fade_out; /* LED Fade-Out Timer */ + u8 led_fade_law; /* fade-on/fade-off transfer characteristic */ + u8 led_on_time; +}; + +#endif /* __LINUX_I2C_ADP8870_H */ From e1bbd19bc4afef7adb80cca163800391c4f5773d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 15 Jun 2011 15:08:12 -0700 Subject: [PATCH 415/595] drivers/video/backlight/adp8870_bl.c: add missed props.type conversion Cc: Michael Hennerich Cc: Mike Frysinger Cc: Matthew Garrett Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/adp8870_bl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index e320b62576e2..05a8832bb3eb 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c @@ -889,6 +889,7 @@ static int __devinit adp8870_probe(struct i2c_client *client, mutex_init(&data->lock); memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; props.max_brightness = props.brightness = ADP8870_MAX_BRIGHTNESS; bl = backlight_device_register(dev_driver_string(&client->dev), &client->dev, data, &adp8870_bl_ops, &props); From a433658c30974fc87ba3ff52d7e4e6299762aa3d Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Wed, 15 Jun 2011 15:08:13 -0700 Subject: [PATCH 416/595] vmscan,memcg: memcg aware swap token Currently, memcg reclaim can disable swap token even if the swap token mm doesn't belong in its memory cgroup. It's slightly risky. If an admin creates very small mem-cgroup and silly guy runs contentious heavy memory pressure workload, every tasks are going to lose swap token and then system may become unresponsive. That's bad. This patch adds 'memcg' parameter into disable_swap_token(). and if the parameter doesn't match swap token, VM doesn't disable it. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: KOSAKI Motohiro Reviewed-by: KAMEZAWA Hiroyuki Reviewed-by: Rik van Riel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/memcontrol.h | 6 +++ include/linux/swap.h | 8 +--- mm/memcontrol.c | 16 +++---- mm/thrash.c | 87 +++++++++++++++++++++++++++++--------- mm/vmscan.c | 4 +- 5 files changed, 85 insertions(+), 36 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 9724a38ee69d..50940da6adf3 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -84,6 +84,7 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem); extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page); extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p); +extern struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm); static inline int mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *cgroup) @@ -246,6 +247,11 @@ static inline struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page) return NULL; } +static inline struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm) +{ + return NULL; +} + static inline int mm_match_cgroup(struct mm_struct *mm, struct mem_cgroup *mem) { return 1; diff --git a/include/linux/swap.h b/include/linux/swap.h index 384eb5fe530b..e70564647039 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -358,6 +358,7 @@ struct backing_dev_info; extern struct mm_struct *swap_token_mm; extern void grab_swap_token(struct mm_struct *); extern void __put_swap_token(struct mm_struct *); +extern void disable_swap_token(struct mem_cgroup *memcg); static inline int has_swap_token(struct mm_struct *mm) { @@ -370,11 +371,6 @@ static inline void put_swap_token(struct mm_struct *mm) __put_swap_token(mm); } -static inline void disable_swap_token(void) -{ - put_swap_token(swap_token_mm); -} - #ifdef CONFIG_CGROUP_MEM_RES_CTLR extern void mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout); @@ -500,7 +496,7 @@ static inline int has_swap_token(struct mm_struct *mm) return 0; } -static inline void disable_swap_token(void) +static inline void disable_swap_token(struct mem_cgroup *memcg) { } diff --git a/mm/memcontrol.c b/mm/memcontrol.c index bd9052a5d3ad..e37c44d88d46 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -735,7 +735,7 @@ struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p) struct mem_cgroup, css); } -static struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm) +struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm) { struct mem_cgroup *mem = NULL; @@ -5414,18 +5414,16 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss, struct cgroup *old_cont, struct task_struct *p) { - struct mm_struct *mm; + struct mm_struct *mm = get_task_mm(p); - if (!mc.to) - /* no need to move charge */ - return; - - mm = get_task_mm(p); if (mm) { - mem_cgroup_move_charge(mm); + if (mc.to) + mem_cgroup_move_charge(mm); + put_swap_token(mm); mmput(mm); } - mem_cgroup_clear_mc(); + if (mc.to) + mem_cgroup_clear_mc(); } #else /* !CONFIG_MMU */ static int mem_cgroup_can_attach(struct cgroup_subsys *ss, diff --git a/mm/thrash.c b/mm/thrash.c index 2372d4ed5dd8..6cdf86511385 100644 --- a/mm/thrash.c +++ b/mm/thrash.c @@ -21,11 +21,31 @@ #include #include #include +#include static DEFINE_SPINLOCK(swap_token_lock); struct mm_struct *swap_token_mm; +struct mem_cgroup *swap_token_memcg; static unsigned int global_faults; +#ifdef CONFIG_CGROUP_MEM_RES_CTLR +static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) +{ + struct mem_cgroup *memcg; + + memcg = try_get_mem_cgroup_from_mm(mm); + if (memcg) + css_put(mem_cgroup_css(memcg)); + + return memcg; +} +#else +static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) +{ + return NULL; +} +#endif + void grab_swap_token(struct mm_struct *mm) { int current_interval; @@ -38,40 +58,69 @@ void grab_swap_token(struct mm_struct *mm) return; /* First come first served */ - if (swap_token_mm == NULL) { - mm->token_priority = mm->token_priority + 2; - swap_token_mm = mm; + if (!swap_token_mm) + goto replace_token; + + if (mm == swap_token_mm) { + mm->token_priority += 2; goto out; } - if (mm != swap_token_mm) { - if (current_interval < mm->last_interval) - mm->token_priority++; - else { - if (likely(mm->token_priority > 0)) - mm->token_priority--; - } - /* Check if we deserve the token */ - if (mm->token_priority > swap_token_mm->token_priority) { - mm->token_priority += 2; - swap_token_mm = mm; - } - } else { - /* Token holder came in again! */ - mm->token_priority += 2; + if (current_interval < mm->last_interval) + mm->token_priority++; + else { + if (likely(mm->token_priority > 0)) + mm->token_priority--; } + /* Check if we deserve the token */ + if (mm->token_priority > swap_token_mm->token_priority) + goto replace_token; + out: mm->faultstamp = global_faults; mm->last_interval = current_interval; spin_unlock(&swap_token_lock); + return; + +replace_token: + mm->token_priority += 2; + swap_token_mm = mm; + swap_token_memcg = swap_token_memcg_from_mm(mm); + goto out; } /* Called on process exit. */ void __put_swap_token(struct mm_struct *mm) { spin_lock(&swap_token_lock); - if (likely(mm == swap_token_mm)) + if (likely(mm == swap_token_mm)) { swap_token_mm = NULL; + swap_token_memcg = NULL; + } spin_unlock(&swap_token_lock); } + +static bool match_memcg(struct mem_cgroup *a, struct mem_cgroup *b) +{ + if (!a) + return true; + if (!b) + return true; + if (a == b) + return true; + return false; +} + +void disable_swap_token(struct mem_cgroup *memcg) +{ + /* memcg reclaim don't disable unrelated mm token. */ + if (match_memcg(memcg, swap_token_memcg)) { + spin_lock(&swap_token_lock); + if (match_memcg(memcg, swap_token_memcg)) { + swap_token_mm = NULL; + swap_token_memcg = NULL; + } + spin_unlock(&swap_token_lock); + } +} diff --git a/mm/vmscan.c b/mm/vmscan.c index faa0a088f9cc..dbe6ea321df4 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2081,7 +2081,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, for (priority = DEF_PRIORITY; priority >= 0; priority--) { sc->nr_scanned = 0; if (!priority) - disable_swap_token(); + disable_swap_token(sc->mem_cgroup); total_scanned += shrink_zones(priority, zonelist, sc); /* * Don't shrink slabs when reclaiming memory from @@ -2407,7 +2407,7 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, /* The swap token gets in the way of swapout... */ if (!priority) - disable_swap_token(); + disable_swap_token(NULL); all_zones_ok = 1; balanced = 0; From 83cd81a34357a632509f7491eec81e62e71d65f7 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Wed, 15 Jun 2011 15:08:14 -0700 Subject: [PATCH 417/595] vmscan: implement swap token trace This is useful for observing swap token activity. example output: zsh-1845 [000] 598.962716: update_swap_token_priority: mm=ffff88015eaf7700 old_prio=1 new_prio=0 memtoy-1830 [001] 602.033900: update_swap_token_priority: mm=ffff880037a45880 old_prio=947 new_prio=949 memtoy-1830 [000] 602.041509: update_swap_token_priority: mm=ffff880037a45880 old_prio=949 new_prio=951 memtoy-1830 [000] 602.051959: update_swap_token_priority: mm=ffff880037a45880 old_prio=951 new_prio=953 memtoy-1830 [000] 602.052188: update_swap_token_priority: mm=ffff880037a45880 old_prio=953 new_prio=955 memtoy-1830 [001] 602.427184: put_swap_token: token_mm=ffff880037a45880 zsh-1789 [000] 602.427281: replace_swap_token: old_token_mm= (null) old_prio=0 new_token_mm=ffff88015eaf7018 new_prio=2 zsh-1789 [001] 602.433456: update_swap_token_priority: mm=ffff88015eaf7018 old_prio=2 new_prio=4 zsh-1789 [000] 602.437613: update_swap_token_priority: mm=ffff88015eaf7018 old_prio=4 new_prio=6 zsh-1789 [000] 602.443924: update_swap_token_priority: mm=ffff88015eaf7018 old_prio=6 new_prio=8 zsh-1789 [000] 602.451873: update_swap_token_priority: mm=ffff88015eaf7018 old_prio=8 new_prio=10 zsh-1789 [001] 602.462639: update_swap_token_priority: mm=ffff88015eaf7018 old_prio=10 new_prio=12 Signed-off-by: KOSAKI Motohiro Acked-by: Rik van Riel Reviewed-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/trace/events/vmscan.h | 77 +++++++++++++++++++++++++++++++++++ mm/thrash.c | 11 ++++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/include/trace/events/vmscan.h b/include/trace/events/vmscan.h index ea422aaa23e1..1798e0cee2a9 100644 --- a/include/trace/events/vmscan.h +++ b/include/trace/events/vmscan.h @@ -6,6 +6,8 @@ #include #include +#include +#include #include "gfpflags.h" #define RECLAIM_WB_ANON 0x0001u @@ -310,6 +312,81 @@ TRACE_EVENT(mm_vmscan_lru_shrink_inactive, show_reclaim_flags(__entry->reclaim_flags)) ); +TRACE_EVENT(replace_swap_token, + TP_PROTO(struct mm_struct *old_mm, + struct mm_struct *new_mm), + + TP_ARGS(old_mm, new_mm), + + TP_STRUCT__entry( + __field(struct mm_struct*, old_mm) + __field(unsigned int, old_prio) + __field(struct mm_struct*, new_mm) + __field(unsigned int, new_prio) + ), + + TP_fast_assign( + __entry->old_mm = old_mm; + __entry->old_prio = old_mm ? old_mm->token_priority : 0; + __entry->new_mm = new_mm; + __entry->new_prio = new_mm->token_priority; + ), + + TP_printk("old_token_mm=%p old_prio=%u new_token_mm=%p new_prio=%u", + __entry->old_mm, __entry->old_prio, + __entry->new_mm, __entry->new_prio) +); + +DECLARE_EVENT_CLASS(put_swap_token_template, + TP_PROTO(struct mm_struct *swap_token_mm), + + TP_ARGS(swap_token_mm), + + TP_STRUCT__entry( + __field(struct mm_struct*, swap_token_mm) + ), + + TP_fast_assign( + __entry->swap_token_mm = swap_token_mm; + ), + + TP_printk("token_mm=%p", __entry->swap_token_mm) +); + +DEFINE_EVENT(put_swap_token_template, put_swap_token, + TP_PROTO(struct mm_struct *swap_token_mm), + TP_ARGS(swap_token_mm) +); + +DEFINE_EVENT_CONDITION(put_swap_token_template, disable_swap_token, + TP_PROTO(struct mm_struct *swap_token_mm), + TP_ARGS(swap_token_mm), + TP_CONDITION(swap_token_mm != NULL) +); + +TRACE_EVENT_CONDITION(update_swap_token_priority, + TP_PROTO(struct mm_struct *mm, + unsigned int old_prio), + + TP_ARGS(mm, old_prio), + + TP_CONDITION(mm->token_priority != old_prio), + + TP_STRUCT__entry( + __field(struct mm_struct*, mm) + __field(unsigned int, old_prio) + __field(unsigned int, new_prio) + ), + + TP_fast_assign( + __entry->mm = mm; + __entry->old_prio = old_prio; + __entry->new_prio = mm->token_priority; + ), + + TP_printk("mm=%p old_prio=%u new_prio=%u", + __entry->mm, __entry->old_prio, __entry->new_prio) +); #endif /* _TRACE_VMSCAN_H */ diff --git a/mm/thrash.c b/mm/thrash.c index 6cdf86511385..17d9e29e4c9c 100644 --- a/mm/thrash.c +++ b/mm/thrash.c @@ -23,6 +23,8 @@ #include #include +#include + static DEFINE_SPINLOCK(swap_token_lock); struct mm_struct *swap_token_mm; struct mem_cgroup *swap_token_memcg; @@ -49,6 +51,7 @@ static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) void grab_swap_token(struct mm_struct *mm) { int current_interval; + unsigned int old_prio = mm->token_priority; global_faults++; @@ -63,7 +66,7 @@ void grab_swap_token(struct mm_struct *mm) if (mm == swap_token_mm) { mm->token_priority += 2; - goto out; + goto update_priority; } if (current_interval < mm->last_interval) @@ -77,6 +80,9 @@ void grab_swap_token(struct mm_struct *mm) if (mm->token_priority > swap_token_mm->token_priority) goto replace_token; +update_priority: + trace_update_swap_token_priority(mm, old_prio); + out: mm->faultstamp = global_faults; mm->last_interval = current_interval; @@ -85,6 +91,7 @@ void grab_swap_token(struct mm_struct *mm) replace_token: mm->token_priority += 2; + trace_replace_swap_token(swap_token_mm, mm); swap_token_mm = mm; swap_token_memcg = swap_token_memcg_from_mm(mm); goto out; @@ -95,6 +102,7 @@ void __put_swap_token(struct mm_struct *mm) { spin_lock(&swap_token_lock); if (likely(mm == swap_token_mm)) { + trace_put_swap_token(swap_token_mm); swap_token_mm = NULL; swap_token_memcg = NULL; } @@ -118,6 +126,7 @@ void disable_swap_token(struct mem_cgroup *memcg) if (match_memcg(memcg, swap_token_memcg)) { spin_lock(&swap_token_lock); if (match_memcg(memcg, swap_token_memcg)) { + trace_disable_swap_token(swap_token_mm); swap_token_mm = NULL; swap_token_memcg = NULL; } From d7911ef30cb7bec52234c2b7a5c275ac8f07905a Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Wed, 15 Jun 2011 15:08:15 -0700 Subject: [PATCH 418/595] vmscan: implement swap token priority aging While testing for memcg aware swap token, I observed a swap token was often grabbed an intermittent running process (eg init, auditd) and they never release a token. Why? Some processes (eg init, auditd, audispd) wake up when a process exiting. And swap token can be get first page-in process when a process exiting makes no swap token owner. Thus such above intermittent running process often get a token. And currently, swap token priority is only decreased at page fault path. Then, if the process sleep immediately after to grab swap token, the swap token priority never be decreased. That's obviously undesirable. This patch implement very poor (and lightweight) priority aging. It only be affect to the above corner case and doesn't change swap tendency workload performance (eg multi process qsbench load) Signed-off-by: KOSAKI Motohiro Reviewed-by: Rik van Riel Reviewed-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/trace/events/vmscan.h | 20 +++++++++++++------- mm/thrash.c | 11 ++++++++++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/include/trace/events/vmscan.h b/include/trace/events/vmscan.h index 1798e0cee2a9..b2c33bd955fa 100644 --- a/include/trace/events/vmscan.h +++ b/include/trace/events/vmscan.h @@ -366,9 +366,10 @@ DEFINE_EVENT_CONDITION(put_swap_token_template, disable_swap_token, TRACE_EVENT_CONDITION(update_swap_token_priority, TP_PROTO(struct mm_struct *mm, - unsigned int old_prio), + unsigned int old_prio, + struct mm_struct *swap_token_mm), - TP_ARGS(mm, old_prio), + TP_ARGS(mm, old_prio, swap_token_mm), TP_CONDITION(mm->token_priority != old_prio), @@ -376,16 +377,21 @@ TRACE_EVENT_CONDITION(update_swap_token_priority, __field(struct mm_struct*, mm) __field(unsigned int, old_prio) __field(unsigned int, new_prio) + __field(struct mm_struct*, swap_token_mm) + __field(unsigned int, swap_token_prio) ), TP_fast_assign( - __entry->mm = mm; - __entry->old_prio = old_prio; - __entry->new_prio = mm->token_priority; + __entry->mm = mm; + __entry->old_prio = old_prio; + __entry->new_prio = mm->token_priority; + __entry->swap_token_mm = swap_token_mm; + __entry->swap_token_prio = swap_token_mm ? swap_token_mm->token_priority : 0; ), - TP_printk("mm=%p old_prio=%u new_prio=%u", - __entry->mm, __entry->old_prio, __entry->new_prio) + TP_printk("mm=%p old_prio=%u new_prio=%u swap_token_mm=%p token_prio=%u", + __entry->mm, __entry->old_prio, __entry->new_prio, + __entry->swap_token_mm, __entry->swap_token_prio) ); #endif /* _TRACE_VMSCAN_H */ diff --git a/mm/thrash.c b/mm/thrash.c index 17d9e29e4c9c..fabf2d0f5169 100644 --- a/mm/thrash.c +++ b/mm/thrash.c @@ -25,10 +25,13 @@ #include +#define TOKEN_AGING_INTERVAL (0xFF) + static DEFINE_SPINLOCK(swap_token_lock); struct mm_struct *swap_token_mm; struct mem_cgroup *swap_token_memcg; static unsigned int global_faults; +static unsigned int last_aging; #ifdef CONFIG_CGROUP_MEM_RES_CTLR static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) @@ -64,6 +67,11 @@ void grab_swap_token(struct mm_struct *mm) if (!swap_token_mm) goto replace_token; + if ((global_faults - last_aging) > TOKEN_AGING_INTERVAL) { + swap_token_mm->token_priority /= 2; + last_aging = global_faults; + } + if (mm == swap_token_mm) { mm->token_priority += 2; goto update_priority; @@ -81,7 +89,7 @@ void grab_swap_token(struct mm_struct *mm) goto replace_token; update_priority: - trace_update_swap_token_priority(mm, old_prio); + trace_update_swap_token_priority(mm, old_prio, swap_token_mm); out: mm->faultstamp = global_faults; @@ -94,6 +102,7 @@ void grab_swap_token(struct mm_struct *mm) trace_replace_swap_token(swap_token_mm, mm); swap_token_mm = mm; swap_token_memcg = swap_token_memcg_from_mm(mm); + last_aging = global_faults; goto out; } From 50c35e5ba255fd8428cef8ff076da8d23bfd4909 Mon Sep 17 00:00:00 2001 From: Ying Han Date: Wed, 15 Jun 2011 15:08:16 -0700 Subject: [PATCH 419/595] memcg: add documentation for the memory.numastat API [akpm@linux-foundation.org: rework text, fit it into 80-cols] Signed-off-by: Ying Han Reviewed-by: KOSAKI Motohiro Acked-by: Balbir Singh Acked-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/cgroups/memory.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 7c163477fcd8..510d64570d60 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -70,6 +70,7 @@ Brief summary of control files. (See sysctl's vm.swappiness) memory.move_charge_at_immigrate # set/show controls of moving charges memory.oom_control # set/show oom controls. + memory.numa_stat # show the number of memory usage per numa node 1. History @@ -464,6 +465,24 @@ value for efficient access. (Of course, when necessary, it's synchronized.) If you want to know more exact memory usage, you should use RSS+CACHE(+SWAP) value in memory.stat(see 5.2). +5.6 numa_stat + +This is similar to numa_maps but operates on a per-memcg basis. This is +useful for providing visibility into the numa locality information within +an memcg since the pages are allowed to be allocated from any physical +node. One of the usecases is evaluating application performance by +combining this information with the application's cpu allocation. + +We export "total", "file", "anon" and "unevictable" pages per-node for +each memcg. The ouput format of memory.numa_stat is: + +total= N0= N1= ... +file= N0= N1= ... +anon= N0= N1= ... +unevictable= N0= N1= ... + +And we have total = file + anon + unevictable. + 6. Hierarchy support The memory controller supports a deep hierarchy and hierarchical accounting. From ac5622418bbff9cd3dc607aa57dfb4f62a7f2043 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 15 Jun 2011 15:08:17 -0700 Subject: [PATCH 420/595] kmsg_dump.h: fix build when CONFIG_PRINTK is disabled Fix when CONFIG_PRINTK is not enabled: include/linux/kmsg_dump.h:56: error: 'EINVAL' undeclared (first use in this function) include/linux/kmsg_dump.h:61: error: 'EINVAL' undeclared (first use in this function) Looks like commit 595dd3d8bf95 ("kmsg_dump: fix build for CONFIG_PRINTK=n") uses EINVAL without having the needed header file(s), but I'm sure that I build tested that patch also. oh well. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kmsg_dump.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h index 2a0d7d651dc3..ee0c952188de 100644 --- a/include/linux/kmsg_dump.h +++ b/include/linux/kmsg_dump.h @@ -12,6 +12,7 @@ #ifndef _LINUX_KMSG_DUMP_H #define _LINUX_KMSG_DUMP_H +#include #include enum kmsg_dump_reason { From 17441227f6258fc379c6ebfe21c3eec43b6f0de3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 15 Jun 2011 15:08:17 -0700 Subject: [PATCH 421/595] checkpatch: add warning for uses of printk_ratelimit Warn about uses of printk_ratelimit() because it uses a global state and can hide subsequent useful messages. Signed-off-by: Joe Perches Cc: Andy Whitcroft Cc: Richard Weinberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 8657f99bfb2b..b0aa2c680593 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1943,6 +1943,11 @@ sub process { WARN("LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr); } +# check for uses of printk_ratelimit + if ($line =~ /\bprintk_ratelimit\s*\(/) { + WARN("Prefer printk_ratelimited or pr__ratelimited to printk_ratelimit\n" . $herecurr); + } + # printk should use KERN_* levels. Note that follow on printk's on the # same line do not need a level, so we use the current block context # to try and find and validate the current printk. In summary the current From 32e45ff43eaf5c17f5a82c9ad358d515622c2562 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Wed, 15 Jun 2011 15:08:20 -0700 Subject: [PATCH 422/595] mm: increase RECLAIM_DISTANCE to 30 Recently, Robert Mueller reported (http://lkml.org/lkml/2010/9/12/236) that zone_reclaim_mode doesn't work properly on his new NUMA server (Dual Xeon E5520 + Intel S5520UR MB). He is using Cyrus IMAPd and it's built on a very traditional single-process model. * a master process which reads config files and manages the other process * multiple imapd processes, one per connection * multiple pop3d processes, one per connection * multiple lmtpd processes, one per connection * periodical "cleanup" processes. There are thousands of independent processes. The problem is, recent Intel motherboard turn on zone_reclaim_mode by default and traditional prefork model software don't work well on it. Unfortunatelly, such models are still typical even in the 21st century. We can't ignore them. This patch raises the zone_reclaim_mode threshold to 30. 30 doesn't have any specific meaning. but 20 means that one-hop QPI/Hypertransport and such relatively cheap 2-4 socket machine are often used for traditional servers as above. The intention is that these machines don't use zone_reclaim_mode. Note: ia64 and Power have arch specific RECLAIM_DISTANCE definitions. This patch doesn't change such high-end NUMA machine behavior. Dave Hansen said: : I know specifically of pieces of x86 hardware that set the information : in the BIOS to '21' *specifically* so they'll get the zone_reclaim_mode : behavior which that implies. : : They've done performance testing and run very large and scary benchmarks : to make sure that they _want_ this turned on. What this means for them : is that they'll probably be de-optimized, at least on newer versions of : the kernel. : : If you want to do this for particular systems, maybe _that_'s what we : should do. Have a list of specific configurations that need the : defaults overridden either because they're buggy, or they have an : unusual hardware configuration not really reflected in the distance : table. And later said: : The original change in the hardware tables was for the benefit of a : benchmark. Said benchmark isn't going to get run on mainline until the : next batch of enterprise distros drops, at which point the hardware where : this was done will be irrelevant for the benchmark. I'm sure any new : hardware will just set this distance to another yet arbitrary value to : make the kernel do what it wants. :) : : Also, when the hardware got _set_ to this initially, I complained. So, I : guess I'm getting my way now, with this patch. I'm cool with it. Reported-by: Robert Mueller Signed-off-by: KOSAKI Motohiro Acked-by: Christoph Lameter Acked-by: David Rientjes Reviewed-by: KAMEZAWA Hiroyuki Cc: Benjamin Herrenschmidt Cc: "Luck, Tony" Acked-by: Dave Hansen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/topology.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/topology.h b/include/linux/topology.h index b91a40e847d2..fc839bfa7935 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -60,7 +60,7 @@ int arch_update_cpu_topology(void); * (in whatever arch specific measurement units returned by node_distance()) * then switch on zone reclaim on boot. */ -#define RECLAIM_DISTANCE 20 +#define RECLAIM_DISTANCE 30 #endif #ifndef PENALTY_FOR_NODE_WITH_CPUS #define PENALTY_FOR_NODE_WITH_CPUS (1) From 5a1e6f75831bf1f8e596d642cd8a2512f11548fc Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 15 Jun 2011 15:08:21 -0700 Subject: [PATCH 423/595] drivers/misc/spear13xx_pcie_gadget.c: fix a memory leak in spear_pcie_gadget_probe error path In the case of goto err_kzalloc, we should kfree target. Signed-off-by: Axel Lin Acked-by: Pratyush Anand Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/spear13xx_pcie_gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c index 7aded90f9daa..cfbddbef11de 100644 --- a/drivers/misc/spear13xx_pcie_gadget.c +++ b/drivers/misc/spear13xx_pcie_gadget.c @@ -845,7 +845,7 @@ static int __devinit spear_pcie_gadget_probe(struct platform_device *pdev) err_iounmap_app: iounmap(config->va_app_base); err_kzalloc: - kfree(config); + kfree(target); err_rel_res: release_mem_region(res1->start, resource_size(res1)); err_rel_res0: From 4bbd61fb9726808e72ab2aa440401f6e5e1aa8f7 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Wed, 15 Jun 2011 15:08:22 -0700 Subject: [PATCH 424/595] drivers/misc/cs5535-mfgpt.c: fix wrong if condition Fix the wrong `if' condition for the check if the requested timer is available. The bitmap avail is used to store if a timer is used already. test_bit() is used to check if the requested timer is available. If a bit in the avail bitmap is set it means that the timer is available. The runtime effect would be that allocating a specific timer always fails (versus telling cs5535_mfgpt_alloc_timer to allocate the first available timer, which works). Signed-off-by: Christian Gmeiner Acked-by: Andres Salomon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/cs5535-mfgpt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c index e01e08c8c88b..bc685bfc4c33 100644 --- a/drivers/misc/cs5535-mfgpt.c +++ b/drivers/misc/cs5535-mfgpt.c @@ -174,7 +174,7 @@ struct cs5535_mfgpt_timer *cs5535_mfgpt_alloc_timer(int timer_nr, int domain) timer_nr = t < max ? (int) t : -1; } else { /* check if the requested timer's available */ - if (test_bit(timer_nr, mfgpt->avail)) + if (!test_bit(timer_nr, mfgpt->avail)) timer_nr = -1; } From 5f1a19070b16c20cdc71ed0e981bfa19f8f6a4ee Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 15 Jun 2011 15:08:23 -0700 Subject: [PATCH 425/595] mm: fix wrong kunmap_atomic() pointer Running a ktest.pl test, I hit the following bug on x86_32: ------------[ cut here ]------------ WARNING: at arch/x86/mm/highmem_32.c:81 __kunmap_atomic+0x64/0xc1() Hardware name: Modules linked in: Pid: 93, comm: sh Not tainted 2.6.39-test+ #1 Call Trace: [] warn_slowpath_common+0x7c/0x91 [] ? __kunmap_atomic+0x64/0xc1 [] ? __kunmap_atomic+0x64/0xc1^M [] warn_slowpath_null+0x22/0x24 [] __kunmap_atomic+0x64/0xc1 [] unmap_vmas+0x43a/0x4e0 [] exit_mmap+0x91/0xd2 [] mmput+0x43/0xad [] exit_mm+0x111/0x119 [] do_exit+0x1ff/0x5fa [] ? set_current_blocked+0x3c/0x40 [] ? sigprocmask+0x7e/0x8e [] do_group_exit+0x65/0x88 [] sys_exit_group+0x18/0x1c [] sysenter_do_call+0x12/0x38 ---[ end trace 8055f74ea3c0eb62 ]--- Running a ktest.pl git bisect, found the culprit: commit e303297e6c3a ("mm: extended batches for generic mmu_gather") But although this was the commit triggering the bug, it was not the one originally responsible for the bug. That was commit d16dfc550f53 ("mm: mmu_gather rework"). The code in zap_pte_range() has something that looks like the following: pte = pte_offset_map_lock(mm, pmd, addr, &ptl); do { [...] } while (pte++, addr += PAGE_SIZE, addr != end); pte_unmap_unlock(pte - 1, ptl); The pte starts off pointing at the first element in the page table directory that was returned by the pte_offset_map_lock(). When it's done with the page, pte will be pointing to anything between the next entry and the first entry of the next page inclusive. By doing a pte - 1, this puts the pte back onto the original page, which is all that pte_unmap_unlock() needs. In most archs (64 bit), this is not an issue as the pte is ignored in the pte_unmap_unlock(). But on 32 bit archs, where things may be kmapped, it is essential that the pte passed to pte_unmap_unlock() resides on the same page that was given by pte_offest_map_lock(). The problem came in d16dfc55 ("mm: mmu_gather rework") where it introduced a "break;" from the while loop. This alone did not seem to easily trigger the bug. But the modifications made by e303297e6 caused that "break;" to be hit on the first iteration, before the pte++. The pte not being incremented will now cause pte_unmap_unlock(pte - 1) to be pointing to the previous page. This will cause the wrong page to be unmapped, and also trigger the warning above. The simple solution is to just save the pointer given by pte_offset_map_lock() and use it in the unlock. Signed-off-by: Steven Rostedt Cc: Peter Zijlstra Cc: KAMEZAWA Hiroyuki Acked-by: Hugh Dickins Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index b13e7dbc399b..87d935333f0d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1112,11 +1112,13 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, int force_flush = 0; int rss[NR_MM_COUNTERS]; spinlock_t *ptl; + pte_t *start_pte; pte_t *pte; again: init_rss_vec(rss); - pte = pte_offset_map_lock(mm, pmd, addr, &ptl); + start_pte = pte_offset_map_lock(mm, pmd, addr, &ptl); + pte = start_pte; arch_enter_lazy_mmu_mode(); do { pte_t ptent = *pte; @@ -1196,7 +1198,7 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, add_mm_rss_vec(mm, rss); arch_leave_lazy_mmu_mode(); - pte_unmap_unlock(pte - 1, ptl); + pte_unmap_unlock(start_pte, ptl); /* * mmu_gather ran out of room to batch pages, we break out of From 3957c7768e5ea02fd3345176ddd340f820e5d285 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Wed, 15 Jun 2011 15:08:25 -0700 Subject: [PATCH 426/595] mm: compaction: fix special case -1 order checks Commit 56de7263fcf3 ("mm: compaction: direct compact when a high-order allocation fails") introduced a check for cc->order == -1 in compact_finished. We should continue compacting in that case because the request came from userspace and there is no particular order to compact for. Similar check has been added by 82478fb7 (mm: compaction: prevent division-by-zero during user-requested compaction) for compaction_suitable. The check is, however, done after zone_watermark_ok which uses order as a right hand argument for shifts. Not only watermark check is pointless if we can break out without it but it also uses 1 << -1 which is not well defined (at least from C standard). Let's move the -1 check above zone_watermark_ok. [minchan.kim@gmail.com> - caught compaction_suitable] Signed-off-by: Michal Hocko Cc: Mel Gorman Reviewed-by: Minchan Kim Reviewed-by: KAMEZAWA Hiroyuki Acked-by: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/compaction.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/mm/compaction.c b/mm/compaction.c index 021a2960ef9e..94bdbe1f7caf 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -420,13 +420,6 @@ static int compact_finished(struct zone *zone, if (cc->free_pfn <= cc->migrate_pfn) return COMPACT_COMPLETE; - /* Compaction run is not finished if the watermark is not met */ - watermark = low_wmark_pages(zone); - watermark += (1 << cc->order); - - if (!zone_watermark_ok(zone, cc->order, watermark, 0, 0)) - return COMPACT_CONTINUE; - /* * order == -1 is expected when compacting via * /proc/sys/vm/compact_memory @@ -434,6 +427,13 @@ static int compact_finished(struct zone *zone, if (cc->order == -1) return COMPACT_CONTINUE; + /* Compaction run is not finished if the watermark is not met */ + watermark = low_wmark_pages(zone); + watermark += (1 << cc->order); + + if (!zone_watermark_ok(zone, cc->order, watermark, 0, 0)) + return COMPACT_CONTINUE; + /* Direct compactor: Is a suitable page free? */ for (order = cc->order; order < MAX_ORDER; order++) { /* Job done if page is free of the right migratetype */ @@ -460,6 +460,13 @@ unsigned long compaction_suitable(struct zone *zone, int order) int fragindex; unsigned long watermark; + /* + * order == -1 is expected when compacting via + * /proc/sys/vm/compact_memory + */ + if (order == -1) + return COMPACT_CONTINUE; + /* * Watermarks for order-0 must be met for compaction. Note the 2UL. * This is because during migration, copies of pages need to be @@ -469,13 +476,6 @@ unsigned long compaction_suitable(struct zone *zone, int order) if (!zone_watermark_ok(zone, 0, watermark, 0, 0)) return COMPACT_SKIPPED; - /* - * order == -1 is expected when compacting via - * /proc/sys/vm/compact_memory - */ - if (order == -1) - return COMPACT_CONTINUE; - /* * fragmentation index determines if allocation failures are due to * low memory or external fragmentation From ca39599c633fb02aceac31a7e67563612e4fe347 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Wed, 15 Jun 2011 15:08:27 -0700 Subject: [PATCH 427/595] BUILD_BUG_ON_ZERO: fix sparse breakage BUILD_BUG_ON_ZERO and BUILD_BUG_ON_NULL must return values, even in the CHECKER case otherwise various users of it become syntactically invalid. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kernel.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index fb0e7329fee1..953352a88336 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -671,8 +671,8 @@ struct sysinfo { #ifdef __CHECKER__ #define BUILD_BUG_ON_NOT_POWER_OF_2(n) -#define BUILD_BUG_ON_ZERO(e) -#define BUILD_BUG_ON_NULL(e) +#define BUILD_BUG_ON_ZERO(e) (0) +#define BUILD_BUG_ON_NULL(e) ((void*)0) #define BUILD_BUG_ON(condition) #else /* __CHECKER__ */ From bd5dc17be87b3a3073d50b23802647db3ae3fa8e Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 15 Jun 2011 15:08:28 -0700 Subject: [PATCH 428/595] uts: make default hostname configurable, rather than always using "(none)" The "hostname" tool falls back to setting the hostname to "localhost" if /etc/hostname does not exist. Distribution init scripts have the same fallback. However, if userspace never calls sethostname, such as when booting with init=/bin/sh, or otherwise booting a minimal system without the usual init scripts, the default hostname of "(none)" remains, unhelpfully appearing in various places such as prompts ("root@(none):~#") and logs. Furthermore, "(none)" doesn't typically resolve to anything useful. Make the default hostname configurable. This removes the need for the standard fallback, provides a useful default for systems that never call sethostname, and makes minimal systems that much more useful with less configuration. Distributions could choose to use "localhost" here to avoid the fallback, while embedded systems may wish to use a specific target hostname. Signed-off-by: Josh Triplett Acked-by: Linus Torvalds Acked-by: David Miller Cc: Serge Hallyn Cc: Kel Modderman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/uts.h | 2 +- init/Kconfig | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/linux/uts.h b/include/linux/uts.h index 73eb1ed36ec4..6ddbd86377de 100644 --- a/include/linux/uts.h +++ b/include/linux/uts.h @@ -9,7 +9,7 @@ #endif #ifndef UTS_NODENAME -#define UTS_NODENAME "(none)" /* set by sethostname() */ +#define UTS_NODENAME CONFIG_DEFAULT_HOSTNAME /* set by sethostname() */ #endif #ifndef UTS_DOMAINNAME diff --git a/init/Kconfig b/init/Kconfig index ebafac4231ee..e0a22e42d39a 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -204,6 +204,15 @@ config KERNEL_LZO endchoice +config DEFAULT_HOSTNAME + string "Default hostname" + default "(none)" + help + This option determines the default system hostname before userspace + calls sethostname(2). The kernel traditionally uses "(none)" here, + but you may wish to use a different default here to make a minimal + system more usable with less configuration. + config SWAP bool "Support for paging of anonymous memory (swap)" depends on MMU && BLOCK From 185e595f770219f2329e590a6be69e6e89e152af Mon Sep 17 00:00:00 2001 From: Balbir Singh Date: Wed, 15 Jun 2011 15:08:30 -0700 Subject: [PATCH 429/595] MAINTAINERS: Balbir has moved Update my email address. Email will start to the old address bouncing soon Signed-off-by: Balbir Singh Cc: Balbir Singh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 2cc3a9430503..88c016d209ff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4144,7 +4144,7 @@ F: include/linux/mm.h F: mm/ MEMORY RESOURCE CONTROLLER -M: Balbir Singh +M: Balbir Singh M: Daisuke Nishimura M: KAMEZAWA Hiroyuki L: linux-mm@kvack.org @@ -4889,7 +4889,7 @@ F: mm/percpu*.c F: arch/*/include/asm/percpu.h PER-TASK DELAY ACCOUNTING -M: Balbir Singh +M: Balbir Singh S: Maintained F: include/linux/delayacct.h F: kernel/delayacct.c @@ -6097,7 +6097,7 @@ F: include/target/ F: Documentation/target/ TASKSTATS STATISTICS INTERFACE -M: Balbir Singh +M: Balbir Singh S: Maintained F: Documentation/accounting/taskstats* F: include/linux/taskstats* From 9d8f776bfb812dd23fcdbb698e9ac4298fc3c624 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 15 Jun 2011 15:08:31 -0700 Subject: [PATCH 430/595] drivers/leds/leds-asic3: make LEDS_ASIC3 depend on LEDS_CLASS We call led_classdev_unregister/led_classdev_register in asic3_led_remove/asic3_led_probe, thus make LEDS_ASIC3 depend on LEDS_CLASS. This patch fixes below build error if LEDS_CLASS is not configured. LD .tmp_vmlinux1 drivers/built-in.o: In function `asic3_led_remove': clkdev.c:(.devexit.text+0x1860): undefined reference to `led_classdev_unregister' drivers/built-in.o: In function `asic3_led_probe': clkdev.c:(.devinit.text+0xcee8): undefined reference to `led_classdev_register' make: *** [.tmp_vmlinux1] Error 1 Signed-off-by: Axel Lin Cc: Paul Parsons Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 23f0d5e99f35..883813d7843c 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -391,6 +391,7 @@ config LEDS_NETXBIG config LEDS_ASIC3 bool "LED support for the HTC ASIC3" + depends on LEDS_CLASS depends on MFD_ASIC3 default y help From be5ce2f1c93295711be4ae5565f9194ed9776ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Jun 2011 15:08:31 -0700 Subject: [PATCH 431/595] leds: move LEDS_GPIO_REGISTER out of menuconfig NEW_LEDS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 4440673a95e6 ("leds: provide helper to register "leds-gpio" devices") broke the display of the NEW_LEDS menu as it didn't depend on NEW_LEDS and so made "LED drivers" and "LED Triggers" appear at the same level as "LED Support" instead of below it as it was before 4440673a. Moving LEDS_GPIO_REGISTER out of the menuconfig NEW_LEDS fixes this unintended side effect. Reported-by: Axel Lin Signed-off-by: Uwe Kleine-König Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 883813d7843c..1032730cd17b 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -1,3 +1,10 @@ +config LEDS_GPIO_REGISTER + bool + help + This option provides the function gpio_led_register_device. + As this function is used by arch code it must not be compiled as a + module. + menuconfig NEW_LEDS bool "LED Support" help @@ -14,13 +21,6 @@ config LEDS_CLASS This option enables the led sysfs class in /sys/class/leds. You'll need this to do anything useful with LEDs. If unsure, say N. -config LEDS_GPIO_REGISTER - bool - help - This option provides the function gpio_led_register_device. - As this function is used by arch code it must not be compiled as a - module. - if NEW_LEDS comment "LED drivers" From 9e6f343852cb16ea961ba5be2ca8dde609aa6f23 Mon Sep 17 00:00:00 2001 From: Pawel Osciak Date: Wed, 15 Jun 2011 15:08:32 -0700 Subject: [PATCH 432/595] MAINTAINERS: add videobuf2 maintainers Add maintainers for the videobuf2 V4L2 driver framework. Signed-off-by: Pawel Osciak Acked-by: Marek Szyprowski Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 88c016d209ff..518442ab25af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6716,6 +6716,14 @@ S: Maintained F: Documentation/filesystems/vfat.txt F: fs/fat/ +VIDEOBUF2 FRAMEWORK +M: Pawel Osciak +M: Marek Szyprowski +L: linux-media@vger.kernel.org +S: Maintained +F: drivers/media/video/videobuf2-* +F: include/media/videobuf2-* + VIRTIO CONSOLE DRIVER M: Amit Shah L: virtualization@lists.linux-foundation.org From 49b24d6b41c576ba43153fc94695f871cce139a5 Mon Sep 17 00:00:00 2001 From: Nicolas Kaiser Date: Wed, 15 Jun 2011 15:08:34 -0700 Subject: [PATCH 433/595] include/asm-generic/pgtable.h: fix unbalanced parenthesis Signed-off-by: Nicolas Kaiser Reviewed-by: Andrea Arcangeli Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-generic/pgtable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index e9b8e5926bef..76bff2bff15e 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -88,7 +88,7 @@ static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm, pmd_t pmd = *pmdp; pmd_clear(mm, address, pmdp); return pmd; -}) +} #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ #endif From 26575f9544530127757297d4de8fb2f2c75f1f69 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 15 Jun 2011 15:08:35 -0700 Subject: [PATCH 434/595] w1: W1_MASTER_DS1WM should depend on GENERIC_HARDIRQS On m68k (which doesn't support generic hardirqs yet): drivers/w1/masters/ds1wm.c: In function `ds1wm_probe': drivers/w1/masters/ds1wm.c: error: implicit declaration of function `irq_set_irq_type' Signed-off-by: Geert Uytterhoeven Cc: Evgeniy Polyakov Cc: Jean-Franois Dagenais Cc: Matt Reimer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/w1/masters/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 00d615d7aa21..979d6eed9a0f 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -42,7 +42,7 @@ config W1_MASTER_MXC config W1_MASTER_DS1WM tristate "Maxim DS1WM 1-wire busmaster" - depends on W1 + depends on W1 && GENERIC_HARDIRQS help Say Y here to enable the DS1WM 1-wire driver, such as that in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like From de695e159e3fd679594eb45449d2638d54434c32 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 15 Jun 2011 15:08:37 -0700 Subject: [PATCH 435/595] init/calibrate.c: remove annoying printk Remove calibrate_delay_direct()'s KERN_DEBUG printk related to bogomips calculation as it appears when booting every core on setups with 'ignore_loglevel' which dmesg people scan for possible issues. As the message doesn't show very useful information to the widest audience of kernel boot message gazers, it should be removed. Introduced by commit d2b463135f84 ("init/calibrate.c: fix for critical bogoMIPS intermittent calculation failure"). Signed-off-by: Borislav Petkov Cc: Andrew Worsley Cc: Phil Carmody Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/calibrate.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/init/calibrate.c b/init/calibrate.c index cfd7000c9d71..2568d22a304e 100644 --- a/init/calibrate.c +++ b/init/calibrate.c @@ -93,9 +93,6 @@ static unsigned long __cpuinit calibrate_delay_direct(void) * If the upper limit and lower limit of the timer_rate is * >= 12.5% apart, redo calibration. */ - printk(KERN_DEBUG "calibrate_delay_direct() timer_rate_max=%lu " - "timer_rate_min=%lu pre_start=%lu pre_end=%lu\n", - timer_rate_max, timer_rate_min, pre_start, pre_end); if (start >= post_end) printk(KERN_NOTICE "calibrate_delay_direct() ignoring " "timer_rate as we had a TSC wrap around" From 959ecc48fc7506b9d7825ea70e40d92d9b308033 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:38 -0700 Subject: [PATCH 436/595] mm/memory_hotplug.c: fix building of node hotplug zonelist During memory hotplug we refresh zonelists when we online a page in a new zone. It means that the node's zonelist is not initialized until pages are onlined. So for example, "nid" passed by MEM_GOING_ONLINE notifier will point to NODE_DATA(nid) which has no zone fallback list. Moreover, if we hot-add cpu-only nodes, alloc_pages() will do no fallback. This patch makes a zonelist when a new pgdata is available. Note: in production, at fujitsu, memory should be onlined before cpu and our server didn't have any memory-less nodes and had no problems. But recent changes in MEM_GOING_ONLINE+page_cgroup will access not initialized zonelist of node. Anyway, there are memory-less node and we need some care. Signed-off-by: KAMEZAWA Hiroyuki Cc: Mel Gorman Cc: Dave Hansen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory_hotplug.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 9f646374e32f..02159c755136 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -494,6 +494,12 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start) /* init node's zones as empty zones, we don't have any present pages.*/ free_area_init_node(nid, zones_size, start_pfn, zholes_size); + /* + * The node we allocated has no zone fallback lists. For avoiding + * to access not-initialized zonelist, build here. + */ + build_all_zonelists(NULL); + return pgdat; } From b0320c7b7d1ac1bd5c2d9dff3258524ab39bad32 Mon Sep 17 00:00:00 2001 From: Rafael Aquini Date: Wed, 15 Jun 2011 15:08:39 -0700 Subject: [PATCH 437/595] mm: fix negative commitlimit when gigantic hugepages are allocated When 1GB hugepages are allocated on a system, free(1) reports less available memory than what really is installed in the box. Also, if the total size of hugepages allocated on a system is over half of the total memory size, CommitLimit becomes a negative number. The problem is that gigantic hugepages (order > MAX_ORDER) can only be allocated at boot with bootmem, thus its frames are not accounted to 'totalram_pages'. However, they are accounted to hugetlb_total_pages() What happens to turn CommitLimit into a negative number is this calculation, in fs/proc/meminfo.c: allowed = ((totalram_pages - hugetlb_total_pages()) * sysctl_overcommit_ratio / 100) + total_swap_pages; A similar calculation occurs in __vm_enough_memory() in mm/mmap.c. Also, every vm statistic which depends on 'totalram_pages' will render confusing values, as if system were 'missing' some part of its memory. Impact of this bug: When gigantic hugepages are allocated and sysctl_overcommit_memory == OVERCOMMIT_NEVER. In a such situation, __vm_enough_memory() goes through the mentioned 'allowed' calculation and might end up mistakenly returning -ENOMEM, thus forcing the system to start reclaiming pages earlier than it would be ususal, and this could cause detrimental impact to overall system's performance, depending on the workload. Besides the aforementioned scenario, I can only think of this causing annoyances with memory reports from /proc/meminfo and free(1). [akpm@linux-foundation.org: standardize comment layout] Reported-by: Russ Anderson Signed-off-by: Rafael Aquini Acked-by: Russ Anderson Cc: Andrea Arcangeli Cc: Christoph Lameter Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 6402458fee38..bfcf153bc829 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1111,6 +1111,14 @@ static void __init gather_bootmem_prealloc(void) WARN_ON(page_count(page) != 1); prep_compound_huge_page(page, h->order); prep_new_huge_page(h, page, page_to_nid(page)); + /* + * If we had gigantic hugepages allocated at boot time, we need + * to restore the 'stolen' pages to totalram_pages in order to + * fix confusing memory reports from free(1) and another + * side-effects, like CommitLimit going negative. + */ + if (h->order > (MAX_ORDER - 1)) + totalram_pages += 1 << h->order; } } From 45d16f09ddd66597e561876f5652c05bf986360a Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 15 Jun 2011 15:08:40 -0700 Subject: [PATCH 438/595] leds: fix the incorrect display in menuconfig Seems when a config option does not have a dependency of the menuconfig, it messes the display of the rest configs, even if it's a hidden one. Signed-off-by: Eric Miao Cc: Richard Purdie Cc: Valdis Kletnieks Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 1032730cd17b..713d43b4e563 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -14,15 +14,14 @@ menuconfig NEW_LEDS This is not related to standard keyboard LEDs which are controlled via the input system. +if NEW_LEDS + config LEDS_CLASS bool "LED Class Support" - depends on NEW_LEDS help This option enables the led sysfs class in /sys/class/leds. You'll need this to do anything useful with LEDs. If unsure, say N. -if NEW_LEDS - comment "LED drivers" config LEDS_88PM860X From 8957712710e045044e3c44375c6a87d7ffa17d51 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:41 -0700 Subject: [PATCH 439/595] mm: memory.numa_stat: fix file permission Commit 406eb0c9ba76 ("memcg: add memory.numastat api for numa statistics") adds memory.numa_stat file for memory cgroup. But the file permissions are wrong. [kamezawa@bluextal linux-2.6]$ ls -l /cgroup/memory/A/memory.numa_stat ---------- 1 root root 0 Jun 9 18:36 /cgroup/memory/A/memory.numa_stat This patch fixes the permission as [root@bluextal kamezawa]# ls -l /cgroup/memory/A/memory.numa_stat -r--r--r-- 1 root root 0 Jun 10 16:49 /cgroup/memory/A/memory.numa_stat Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Ying Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e37c44d88d46..02a7947608ad 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4640,6 +4640,7 @@ static struct cftype mem_cgroup_files[] = { { .name = "numa_stat", .open = mem_control_numa_stat_open, + .mode = S_IRUGO, }, #endif }; From 37573e8c718277103f61f03741bdc5606d31b07e Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:42 -0700 Subject: [PATCH 440/595] memcg: fix init_page_cgroup nid with sparsemem Commit 21a3c9646873 ("memcg: allocate memory cgroup structures in local nodes") makes page_cgroup allocation as NUMA aware. But that caused a problem https://bugzilla.kernel.org/show_bug.cgi?id=36192. The problem was getting a NID from invalid struct pages, which was not initialized because it was out-of-node, out of [node_start_pfn, node_end_pfn) Now, with sparsemem, page_cgroup_init scans pfn from 0 to max_pfn. But this may scan a pfn which is not on any node and can access memmap which is not initialized. This makes page_cgroup_init() for SPARSEMEM node aware and remove a code to get nid from page->flags. (Then, we'll use valid NID always.) [akpm@linux-foundation.org: try to fix up comments] Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_cgroup.c | 71 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index 74ccff61d1be..53bffc6c293e 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c @@ -162,13 +162,13 @@ static void free_page_cgroup(void *addr) } #endif -static int __meminit init_section_page_cgroup(unsigned long pfn) +static int __meminit init_section_page_cgroup(unsigned long pfn, int nid) { struct page_cgroup *base, *pc; struct mem_section *section; unsigned long table_size; unsigned long nr; - int nid, index; + int index; nr = pfn_to_section_nr(pfn); section = __nr_to_section(nr); @@ -176,7 +176,6 @@ static int __meminit init_section_page_cgroup(unsigned long pfn) if (section->page_cgroup) return 0; - nid = page_to_nid(pfn_to_page(pfn)); table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION; base = alloc_page_cgroup(table_size, nid); @@ -196,7 +195,11 @@ static int __meminit init_section_page_cgroup(unsigned long pfn) pc = base + index; init_page_cgroup(pc, nr); } - + /* + * The passed "pfn" may not be aligned to SECTION. For the calculation + * we need to apply a mask. + */ + pfn &= PAGE_SECTION_MASK; section->page_cgroup = base - pfn; total_usage += table_size; return 0; @@ -225,10 +228,20 @@ int __meminit online_page_cgroup(unsigned long start_pfn, start = start_pfn & ~(PAGES_PER_SECTION - 1); end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION); + if (nid == -1) { + /* + * In this case, "nid" already exists and contains valid memory. + * "start_pfn" passed to us is a pfn which is an arg for + * online__pages(), and start_pfn should exist. + */ + nid = pfn_to_nid(start_pfn); + VM_BUG_ON(!node_state(nid, N_ONLINE)); + } + for (pfn = start; !fail && pfn < end; pfn += PAGES_PER_SECTION) { if (!pfn_present(pfn)) continue; - fail = init_section_page_cgroup(pfn); + fail = init_section_page_cgroup(pfn, nid); } if (!fail) return 0; @@ -284,25 +297,47 @@ static int __meminit page_cgroup_callback(struct notifier_block *self, void __init page_cgroup_init(void) { unsigned long pfn; - int fail = 0; + int nid; if (mem_cgroup_disabled()) return; - for (pfn = 0; !fail && pfn < max_pfn; pfn += PAGES_PER_SECTION) { - if (!pfn_present(pfn)) - continue; - fail = init_section_page_cgroup(pfn); - } - if (fail) { - printk(KERN_CRIT "try 'cgroup_disable=memory' boot option\n"); - panic("Out of memory"); - } else { - hotplug_memory_notifier(page_cgroup_callback, 0); + for_each_node_state(nid, N_HIGH_MEMORY) { + unsigned long start_pfn, end_pfn; + + start_pfn = node_start_pfn(nid); + end_pfn = node_end_pfn(nid); + /* + * start_pfn and end_pfn may not be aligned to SECTION and the + * page->flags of out of node pages are not initialized. So we + * scan [start_pfn, the biggest section's pfn < end_pfn) here. + */ + for (pfn = start_pfn; + pfn < end_pfn; + pfn = ALIGN(pfn + 1, PAGES_PER_SECTION)) { + + if (!pfn_valid(pfn)) + continue; + /* + * Nodes's pfns can be overlapping. + * We know some arch can have a nodes layout such as + * -------------pfn--------------> + * N0 | N1 | N2 | N0 | N1 | N2|.... + */ + if (pfn_to_nid(pfn) != nid) + continue; + if (init_section_page_cgroup(pfn, nid)) + goto oom; + } } + hotplug_memory_notifier(page_cgroup_callback, 0); printk(KERN_INFO "allocated %ld bytes of page_cgroup\n", total_usage); - printk(KERN_INFO "please try 'cgroup_disable=memory' option if you don't" - " want memory cgroups\n"); + printk(KERN_INFO "please try 'cgroup_disable=memory' option if you " + "don't want memory cgroups\n"); + return; +oom: + printk(KERN_CRIT "try 'cgroup_disable=memory' boot option\n"); + panic("Out of memory"); } void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat) From 733eda7ac316cd4e550fa096e4ed42356dc546e7 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:43 -0700 Subject: [PATCH 441/595] memcg: clear mm->owner when last possible owner leaves The following crash was reported: > Call Trace: > [] mem_cgroup_from_task+0x15/0x17 > [] __mem_cgroup_try_charge+0x148/0x4b4 > [] ? need_resched+0x23/0x2d > [] ? preempt_schedule+0x46/0x4f > [] mem_cgroup_charge_common+0x9a/0xce > [] mem_cgroup_newpage_charge+0x5d/0x5f > [] khugepaged+0x5da/0xfaf > [] ? __init_waitqueue_head+0x4b/0x4b > [] ? add_mm_counter.constprop.5+0x13/0x13 > [] kthread+0xa8/0xb0 > [] ? sub_preempt_count+0xa1/0xb4 > [] kernel_thread_helper+0x4/0x10 > [] ? retint_restore_args+0x13/0x13 > [] ? __init_kthread_worker+0x5a/0x5a What happens is that khugepaged tries to charge a huge page against an mm whose last possible owner has already exited, and the memory controller crashes when the stale mm->owner is used to look up the cgroup to charge. mm->owner has never been set to NULL with the last owner going away, but nobody cared until khugepaged came along. Even then it wasn't a problem because the final mmput() on an mm was forced to acquire and release mmap_sem in write-mode, preventing an exiting owner to go away while the mmap_sem was held, and until "692e0b3 mm: thp: optimize memcg charge in khugepaged", the memory cgroup charge was protected by mmap_sem in read-mode. Instead of going back to relying on the mmap_sem to enforce lifetime of a task, this patch ensures that mm->owner is properly set to NULL when the last possible owner is exiting, which the memory controller can handle just fine. [akpm@linux-foundation.org: tweak comments] Signed-off-by: Hugh Dickins Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Johannes Weiner Reported-by: Hugh Dickins Reported-by: Dave Jones Reviewed-by: Andrea Arcangeli Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/exit.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/kernel/exit.c b/kernel/exit.c index 20a406471525..f2b321bae440 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -561,29 +561,28 @@ void exit_files(struct task_struct *tsk) #ifdef CONFIG_MM_OWNER /* - * Task p is exiting and it owned mm, lets find a new owner for it + * A task is exiting. If it owned this mm, find a new owner for the mm. */ -static inline int -mm_need_new_owner(struct mm_struct *mm, struct task_struct *p) -{ - /* - * If there are other users of the mm and the owner (us) is exiting - * we need to find a new owner to take on the responsibility. - */ - if (atomic_read(&mm->mm_users) <= 1) - return 0; - if (mm->owner != p) - return 0; - return 1; -} - void mm_update_next_owner(struct mm_struct *mm) { struct task_struct *c, *g, *p = current; retry: - if (!mm_need_new_owner(mm, p)) + /* + * If the exiting or execing task is not the owner, it's + * someone else's problem. + */ + if (mm->owner != p) return; + /* + * The current owner is exiting/execing and there are no other + * candidates. Do not leave the mm pointing to a possibly + * freed task structure. + */ + if (atomic_read(&mm->mm_users) <= 1) { + mm->owner = NULL; + return; + } read_lock(&tasklist_lock); /* From 7ae534d074e01e54d5cfbc9734b73fdfc855501f Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:44 -0700 Subject: [PATCH 442/595] memcg: fix wrong check of noswap with softlimit Hierarchical reclaim doesn't swap out if memsw and resource limits are thye same (memsw_is_minimum == true) because we would hit mem+swap limit anyway (during hard limit reclaim). If it comes to the soft limit we shouldn't consider memsw_is_minimum at all because it doesn't make much sense. Either the soft limit is bellow the hard limit and then we cannot hit mem+swap limit or the direct reclaim takes a precedence. Signed-off-by: KAMEZAWA Hiroyuki Reviewed-by: Michal Hocko Acked-by: Daisuke Nishimura Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 02a7947608ad..0b1a32cbd74d 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1663,7 +1663,7 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, excess = res_counter_soft_limit_excess(&root_mem->res) >> PAGE_SHIFT; /* If memsw_is_minimum==1, swap-out is of-no-use. */ - if (root_mem->memsw_is_minimum) + if (!check_soft && root_mem->memsw_is_minimum) noswap = true; while (1) { From 26fe616844491a41a1abc02e29f7a9d1ec2f8ddb Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:45 -0700 Subject: [PATCH 443/595] memcg: fix percpu cached charge draining frequency For performance, memory cgroup caches some "charge" from res_counter into per cpu cache. This works well but because it's cache, it needs to be flushed in some cases. Typical cases are 1. when someone hit limit. 2. when rmdir() is called and need to charges to be 0. But "1" has problem. Recently, with large SMP machines, we see many kworker runs because of flushing memcg's cache. Bad things in implementation are that even if a cpu contains a cache for memcg not related to a memcg which hits limit, drain code is called. This patch does A) check percpu cache contains a useful data or not. B) check other asynchronous percpu draining doesn't run. C) don't call local cpu callback. (*)This patch avoid changing the calling condition with hard-limit. When I run "cat 1Gfile > /dev/null" under 300M limit memcg, [Before] 13767 kamezawa 20 0 98.6m 424 416 D 10.0 0.0 0:00.61 cat 58 root 20 0 0 0 0 S 0.6 0.0 0:00.09 kworker/2:1 60 root 20 0 0 0 0 S 0.6 0.0 0:00.08 kworker/4:1 4 root 20 0 0 0 0 S 0.3 0.0 0:00.02 kworker/0:0 57 root 20 0 0 0 0 S 0.3 0.0 0:00.05 kworker/1:1 61 root 20 0 0 0 0 S 0.3 0.0 0:00.05 kworker/5:1 62 root 20 0 0 0 0 S 0.3 0.0 0:00.05 kworker/6:1 63 root 20 0 0 0 0 S 0.3 0.0 0:00.05 kworker/7:1 [After] 2676 root 20 0 98.6m 416 416 D 9.3 0.0 0:00.87 cat 2626 kamezawa 20 0 15192 1312 920 R 0.3 0.0 0:00.28 top 1 root 20 0 19384 1496 1204 S 0.0 0.0 0:00.66 init 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd 3 root 20 0 0 0 0 S 0.0 0.0 0:00.00 ksoftirqd/0 4 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0 [akpm@linux-foundation.org: make percpu_charge_mutex static, tweak comments] Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Daisuke Nishimura Reviewed-by: Michal Hocko Tested-by: Ying Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 54 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 0b1a32cbd74d..c39a177bb641 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -359,7 +359,7 @@ enum charge_type { static void mem_cgroup_get(struct mem_cgroup *mem); static void mem_cgroup_put(struct mem_cgroup *mem); static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem); -static void drain_all_stock_async(void); +static void drain_all_stock_async(struct mem_cgroup *mem); static struct mem_cgroup_per_zone * mem_cgroup_zoneinfo(struct mem_cgroup *mem, int nid, int zid) @@ -1671,7 +1671,7 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, if (victim == root_mem) { loop++; if (loop >= 1) - drain_all_stock_async(); + drain_all_stock_async(root_mem); if (loop >= 2) { /* * If we have not been able to reclaim @@ -1934,9 +1934,11 @@ struct memcg_stock_pcp { struct mem_cgroup *cached; /* this never be root cgroup */ unsigned int nr_pages; struct work_struct work; + unsigned long flags; +#define FLUSHING_CACHED_CHARGE (0) }; static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock); -static atomic_t memcg_drain_count; +static DEFINE_MUTEX(percpu_charge_mutex); /* * Try to consume stocked charge on this cpu. If success, one page is consumed @@ -1984,6 +1986,7 @@ static void drain_local_stock(struct work_struct *dummy) { struct memcg_stock_pcp *stock = &__get_cpu_var(memcg_stock); drain_stock(stock); + clear_bit(FLUSHING_CACHED_CHARGE, &stock->flags); } /* @@ -2008,26 +2011,45 @@ static void refill_stock(struct mem_cgroup *mem, unsigned int nr_pages) * expects some charges will be back to res_counter later but cannot wait for * it. */ -static void drain_all_stock_async(void) +static void drain_all_stock_async(struct mem_cgroup *root_mem) { - int cpu; - /* This function is for scheduling "drain" in asynchronous way. - * The result of "drain" is not directly handled by callers. Then, - * if someone is calling drain, we don't have to call drain more. - * Anyway, WORK_STRUCT_PENDING check in queue_work_on() will catch if - * there is a race. We just do loose check here. + int cpu, curcpu; + /* + * If someone calls draining, avoid adding more kworker runs. */ - if (atomic_read(&memcg_drain_count)) + if (!mutex_trylock(&percpu_charge_mutex)) return; /* Notify other cpus that system-wide "drain" is running */ - atomic_inc(&memcg_drain_count); get_online_cpus(); + /* + * Get a hint for avoiding draining charges on the current cpu, + * which must be exhausted by our charging. It is not required that + * this be a precise check, so we use raw_smp_processor_id() instead of + * getcpu()/putcpu(). + */ + curcpu = raw_smp_processor_id(); for_each_online_cpu(cpu) { struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu); - schedule_work_on(cpu, &stock->work); + struct mem_cgroup *mem; + + if (cpu == curcpu) + continue; + + mem = stock->cached; + if (!mem) + continue; + if (mem != root_mem) { + if (!root_mem->use_hierarchy) + continue; + /* check whether "mem" is under tree of "root_mem" */ + if (!css_is_ancestor(&mem->css, &root_mem->css)) + continue; + } + if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) + schedule_work_on(cpu, &stock->work); } put_online_cpus(); - atomic_dec(&memcg_drain_count); + mutex_unlock(&percpu_charge_mutex); /* We don't wait for flush_work */ } @@ -2035,9 +2057,9 @@ static void drain_all_stock_async(void) static void drain_all_stock_sync(void) { /* called when force_empty is called */ - atomic_inc(&memcg_drain_count); + mutex_lock(&percpu_charge_mutex); schedule_on_each_cpu(drain_local_stock); - atomic_dec(&memcg_drain_count); + mutex_unlock(&percpu_charge_mutex); } /* From fbc29a25e484be073e7d762c9f7f1d4bf8aecc48 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 15 Jun 2011 15:08:46 -0700 Subject: [PATCH 444/595] memcg: avoid percpu cached charge draining at softlimit Based on Michal Hocko's comment. We are not draining per cpu cached charges during soft limit reclaim because background reclaim doesn't care about charges. It tries to free some memory and charges will not give any. Cached charges might influence only selection of the biggest soft limit offender but as the call is done only after the selection has been already done it makes no change. Signed-off-by: KAMEZAWA Hiroyuki Cc: Daisuke Nishimura Reviewed-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index c39a177bb641..cf7d027a8844 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1670,7 +1670,13 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, victim = mem_cgroup_select_victim(root_mem); if (victim == root_mem) { loop++; - if (loop >= 1) + /* + * We are not draining per cpu cached charges during + * soft limit reclaim because global reclaim doesn't + * care about charges. It tries to free some memory and + * charges will not give any. + */ + if (!check_soft && loop >= 1) drain_all_stock_async(root_mem); if (loop >= 2) { /* From b0461a44a2f1fc052fc949ae19c3a5d684627b09 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 15 Jun 2011 15:08:46 -0700 Subject: [PATCH 445/595] MAINTAINERS: add entry for legacy eeprom driver I shall maintain the legacy eeprom driver, until we finally get rid of it. Signed-off-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 518442ab25af..6c59eb90fdf4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3819,6 +3819,12 @@ S: Maintained F: drivers/leds/ F: include/linux/leds.h +LEGACY EEPROM DRIVER +M: Jean Delvare +S: Maintained +F: Documentation/misc-devices/eeprom +F: drivers/misc/eeprom/eeprom.c + LEGO USB Tower driver M: Juergen Stuber L: legousb-devel@lists.sourceforge.net From d2c32258798f813dc2be6cbc32f78aa5ac5cb205 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 15 Jun 2011 15:08:47 -0700 Subject: [PATCH 446/595] gcov: disable CONFIG_CONSTRUCTORS when not needed by CONFIG_GCOV_KERNEL CONFIG_CONSTRUCTORS controls support for running constructor functions at kernel init time. According to commit b99b87f70c7785ab ("kernel: constructor support"), gcov (CONFIG_GCOV_KERNEL) needs this. However, CONFIG_CONSTRUCTORS currently defaults to y, with no option to disable it, and CONFIG_GCOV_KERNEL depends on it. Instead, default it to n and have CONFIG_GCOV_KERNEL select it, so that the normal case of CONFIG_GCOV_KERNEL=n will result in CONFIG_CONSTRUCTORS=n. Observed in the short list of =y values in a minimal kernel configuration. Signed-off-by: Josh Triplett Acked-by: WANG Cong Acked-by: Peter Oberparleiter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/Kconfig | 1 - kernel/gcov/Kconfig | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/init/Kconfig b/init/Kconfig index e0a22e42d39a..412c21b00d51 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -19,7 +19,6 @@ config DEFCONFIG_LIST config CONSTRUCTORS bool depends on !UML - default y config HAVE_IRQ_WORK bool diff --git a/kernel/gcov/Kconfig b/kernel/gcov/Kconfig index b8cadf70b1fb..5bf924d80b5c 100644 --- a/kernel/gcov/Kconfig +++ b/kernel/gcov/Kconfig @@ -2,7 +2,8 @@ menu "GCOV-based kernel profiling" config GCOV_KERNEL bool "Enable gcov-based kernel profiling" - depends on DEBUG_FS && CONSTRUCTORS + depends on DEBUG_FS + select CONSTRUCTORS default n ---help--- This option enables gcov-based code profiling (e.g. for code coverage From 5db8a73a8d7cc6a66afbf25ed7fda338caa8f5f9 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Wed, 15 Jun 2011 15:08:48 -0700 Subject: [PATCH 447/595] mm/memory-failure.c: fix page isolated count mismatch Pages isolated for migration are accounted with the vmstat counters NR_ISOLATE_[ANON|FILE]. Callers of migrate_pages() are expected to increment these counters when pages are isolated from the LRU. Once the pages have been migrated, they are put back on the LRU or freed and the isolated count is decremented. Memory failure is not properly accounting for pages it isolates causing the NR_ISOLATED counters to be negative. On SMP builds, this goes unnoticed as negative counters are treated as 0 due to expected per-cpu drift. On UP builds, the counter is treated by too_many_isolated() as a large value causing processes to enter D state during page reclaim or compaction. This patch accounts for pages isolated by memory failure correctly. [mel@csn.ul.ie: rewrote changelog] Reviewed-by: Andrea Arcangeli Signed-off-by: Minchan Kim Cc: Andi Kleen Acked-by: Mel Gorman Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory-failure.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 5c8f7e08928d..eac0ba561491 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -52,6 +52,7 @@ #include #include #include +#include #include "internal.h" int sysctl_memory_failure_early_kill __read_mostly = 0; @@ -1468,7 +1469,8 @@ int soft_offline_page(struct page *page, int flags) put_page(page); if (!ret) { LIST_HEAD(pagelist); - + inc_zone_page_state(page, NR_ISOLATED_ANON + + page_is_file_cache(page)); list_add(&page->lru, &pagelist); ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0, true); From a582a738c763e106f47eab24b8146c698a9c700b Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 15 Jun 2011 15:08:49 -0700 Subject: [PATCH 448/595] compaction: checks correct fragmentation index fragmentation_index() returns -1000 when the allocation might succeed This doesn't match the comment and code in compaction_suitable(). I thought compaction_suitable should return COMPACT_PARTIAL in -1000 case, because in this case allocation could succeed depending on watermarks. The impact of this is that compaction starts and compact_finished() is called which rechecks the watermarks and the free lists. It should have the same result in that compaction should not start but is more expensive. Acked-by: Mel Gorman Signed-off-by: Shaohua Li Cc: Minchan Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/compaction.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/compaction.c b/mm/compaction.c index 94bdbe1f7caf..cf7086c6dc07 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -480,7 +480,8 @@ unsigned long compaction_suitable(struct zone *zone, int order) * fragmentation index determines if allocation failures are due to * low memory or external fragmentation * - * index of -1 implies allocations might succeed dependingon watermarks + * index of -1000 implies allocations might succeed depending on + * watermarks * index towards 0 implies failure is due to lack of memory * index towards 1000 implies failure is due to fragmentation * @@ -490,7 +491,8 @@ unsigned long compaction_suitable(struct zone *zone, int order) if (fragindex >= 0 && fragindex <= sysctl_extfrag_threshold) return COMPACT_SKIPPED; - if (fragindex == -1 && zone_watermark_ok(zone, order, watermark, 0, 0)) + if (fragindex == -1000 && zone_watermark_ok(zone, order, watermark, + 0, 0)) return COMPACT_PARTIAL; return COMPACT_CONTINUE; From 7454f4ba40b419eb999a3c61a99da662bf1a2bb8 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Wed, 15 Jun 2011 15:08:50 -0700 Subject: [PATCH 449/595] mm: compaction: ensure that the compaction free scanner does not move to the next zone Compaction works with two scanners, a migration and a free scanner. When the scanners crossover, migration within the zone is complete. The location of the scanner is recorded on each cycle to avoid excesive scanning. When a zone is small and mostly reserved, it's very easy for the migration scanner to be close to the end of the zone. Then the following situation can occurs o migration scanner isolates some pages near the end of the zone o free scanner starts at the end of the zone but finds that the migration scanner is already there o free scanner gets reinitialised for the next cycle as cc->migrate_pfn + pageblock_nr_pages moving the free scanner into the next zone o migration scanner moves into the next zone When this happens, NR_ISOLATED accounting goes haywire because some of the accounting happens against the wrong zone. One zones counter remains positive while the other goes negative even though the overall global count is accurate. This was reported on X86-32 with !SMP because !SMP allows the negative counters to be visible. The fact that it is the bug should theoritically be possible there. Signed-off-by: Mel Gorman Reviewed-by: Minchan Kim Reviewed-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/compaction.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/mm/compaction.c b/mm/compaction.c index cf7086c6dc07..9b94eaf537e4 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -144,9 +144,20 @@ static void isolate_freepages(struct zone *zone, int nr_freepages = cc->nr_freepages; struct list_head *freelist = &cc->freepages; + /* + * Initialise the free scanner. The starting point is where we last + * scanned from (or the end of the zone if starting). The low point + * is the end of the pageblock the migration scanner is using. + */ pfn = cc->free_pfn; low_pfn = cc->migrate_pfn + pageblock_nr_pages; - high_pfn = low_pfn; + + /* + * Take care that if the migration scanner is at the end of the zone + * that the free scanner does not accidentally move to the next zone + * in the next isolation cycle. + */ + high_pfn = min(low_pfn, pfn); /* * Isolate free pages until enough are available to migrate the From d179e84ba5da1d0024087d1759a2938817a00f3f Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Wed, 15 Jun 2011 15:08:51 -0700 Subject: [PATCH 450/595] mm: vmscan: do not use page_count without a page pin It is unsafe to run page_count during the physical pfn scan because compound_head could trip on a dangling pointer when reading page->first_page if the compound page is being freed by another CPU. [mgorman@suse.de: split out patch] Signed-off-by: Andrea Arcangeli Signed-off-by: Mel Gorman Reviewed-by: Michal Hocko Reviewed-by: Minchan Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index dbe6ea321df4..8ff834e19c24 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1124,8 +1124,20 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan, nr_lumpy_dirty++; scan++; } else { - /* the page is freed already. */ - if (!page_count(cursor_page)) + /* + * Check if the page is freed already. + * + * We can't use page_count() as that + * requires compound_head and we don't + * have a pin on the page here. If a + * page is tail, we may or may not + * have isolated the head, so assume + * it's not free, it'd be tricky to + * track the head status without a + * page pin. + */ + if (!PageTail(cursor_page) && + !atomic_read(&cursor_page->_count)) continue; break; } From f9e35b3b41f47c4e17d8132edbcab305a6aaa4b0 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Wed, 15 Jun 2011 15:08:52 -0700 Subject: [PATCH 451/595] mm: compaction: abort compaction if too many pages are isolated and caller is asynchronous V2 Asynchronous compaction is used when promoting to huge pages. This is all very nice but if there are a number of processes in compacting memory, a large number of pages can be isolated. An "asynchronous" process can stall for long periods of time as a result with a user reporting that firefox can stall for 10s of seconds. This patch aborts asynchronous compaction if too many pages are isolated as it's better to fail a hugepage promotion than stall a process. [minchan.kim@gmail.com: return COMPACT_PARTIAL for abort] Reported-and-tested-by: Ury Stankevich Signed-off-by: Mel Gorman Reviewed-by: Minchan Kim Reviewed-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/compaction.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/mm/compaction.c b/mm/compaction.c index 9b94eaf537e4..6cc604bd5649 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -251,11 +251,18 @@ static bool too_many_isolated(struct zone *zone) return isolated > (inactive + active) / 2; } +/* possible outcome of isolate_migratepages */ +typedef enum { + ISOLATE_ABORT, /* Abort compaction now */ + ISOLATE_NONE, /* No pages isolated, continue scanning */ + ISOLATE_SUCCESS, /* Pages isolated, migrate */ +} isolate_migrate_t; + /* * Isolate all pages that can be migrated from the block pointed to by * the migrate scanner within compact_control. */ -static unsigned long isolate_migratepages(struct zone *zone, +static isolate_migrate_t isolate_migratepages(struct zone *zone, struct compact_control *cc) { unsigned long low_pfn, end_pfn; @@ -272,7 +279,7 @@ static unsigned long isolate_migratepages(struct zone *zone, /* Do not cross the free scanner or scan within a memory hole */ if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) { cc->migrate_pfn = end_pfn; - return 0; + return ISOLATE_NONE; } /* @@ -281,10 +288,14 @@ static unsigned long isolate_migratepages(struct zone *zone, * delay for some time until fewer pages are isolated */ while (unlikely(too_many_isolated(zone))) { + /* async migration should just abort */ + if (!cc->sync) + return ISOLATE_ABORT; + congestion_wait(BLK_RW_ASYNC, HZ/10); if (fatal_signal_pending(current)) - return 0; + return ISOLATE_ABORT; } /* Time to isolate some pages for migration */ @@ -369,7 +380,7 @@ static unsigned long isolate_migratepages(struct zone *zone, trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated); - return cc->nr_migratepages; + return ISOLATE_SUCCESS; } /* @@ -535,8 +546,15 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) unsigned long nr_migrate, nr_remaining; int err; - if (!isolate_migratepages(zone, cc)) + switch (isolate_migratepages(zone, cc)) { + case ISOLATE_ABORT: + ret = COMPACT_PARTIAL; + goto out; + case ISOLATE_NONE: continue; + case ISOLATE_SUCCESS: + ; + } nr_migrate = cc->nr_migratepages; err = migrate_pages(&cc->migratepages, compaction_alloc, @@ -560,6 +578,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) } +out: /* Release free pages and check accounting */ cc->nr_freepages -= release_freepages(&cc->freepages); VM_BUG_ON(cc->nr_freepages != 0); From 31b5f8eeece4c0d70b649bfac7759cf7e3f915dd Mon Sep 17 00:00:00 2001 From: "akpm@linux-foundation.org" Date: Wed, 15 Jun 2011 15:08:52 -0700 Subject: [PATCH 452/595] Documentation/feature-removal-schedule.txt: remove ns_cgroup from feature-removal-schedule.txt Commit a77aea92010acf ("cgroup: remove the ns_cgroup") removed the ns_cgroup but it forgot to remove the related doc in feature-removal-schedule.txt. Signed-off-by: WANG Cong Cc: Daniel Lezcano Cc: Serge E. Hallyn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 1a9446b59153..72e238465b0b 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -481,23 +481,6 @@ Who: FUJITA Tomonori ---------------------------- -What: namespace cgroup (ns_cgroup) -When: 2.6.38 -Why: The ns_cgroup leads to some problems: - * cgroup creation is out-of-control - * cgroup name can conflict when pids are looping - * it is not possible to have a single process handling - a lot of namespaces without falling in a exponential creation time - * we may want to create a namespace without creating a cgroup - - The ns_cgroup is replaced by a compatibility flag 'clone_children', - where a newly created cgroup will copy the parent cgroup values. - The userspace has to manually create a cgroup and add a task to - the 'tasks' file. -Who: Daniel Lezcano - ----------------------------- - What: iwlwifi disable_hw_scan module parameters When: 2.6.40 Why: Hareware scan is the prefer method for iwlwifi devices for From 273ef9509b7903e50f36aaf9f1d5dc9087fca506 Mon Sep 17 00:00:00 2001 From: Nils Carlson Date: Wed, 15 Jun 2011 15:08:54 -0700 Subject: [PATCH 453/595] drivers/char/hpet.c: fix periodic-emulation for delayed interrupts When interrupts are delayed due to interrupt masking or due to other interrupts being serviced the HPET periodic-emuation would fail. This happened because given an interval t and a time for the current interrupt m we would compute the next time as t + m. This works until we are delayed for > t, in which case we would be writing a new value which is in fact in the past. This can be solved by computing the next time instead as (k * t) + m where k is large enough to be in the future. The exact computation of k is described in a comment to the code. More detail: Assuming an interval of 5 between each expected interrupt we have a normal case of t0: interrupt, read t0 from comparator, set next interrupt t0 + 5 t5: interrupt, read t5 from comparator, set next interrupt t5 + 5 t10: interrupt, read t10 from comparator, set next interrupt t10 + 5 ... So, what happens when the interrupt is serviced too late? t0: interrupt, read t0 from comparator, set next interrupt t0 + 5 t11: delayed interrupt serviced, read t5 from comparator, set next interrupt t5 + 5, which is in the past! ... counter loops ... t10: Much much later, get the next interrupt. This can happen either because we have interrupts masked for too long (some stupid driver goes on a printk rampage) or just because we are pushing the limits of the interval (too small a period), or both most probably. My solution is to read the main counter as well and set the next interrupt to occur at the right interval, for example: t0: interrupt, read t0 from comparator, set next interrupt t0 + 5 t11: delayed interrupt serviced, read t5 from comparator, set next interrupt t15 as t10 has been missed. t15: back on track. Signed-off-by: Nils Carlson Cc: John Stultz Cc: Thomas Gleixner Cc: Clemens Ladisch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/hpet.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 051474c65b78..34d6a1cab8de 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -163,11 +163,32 @@ static irqreturn_t hpet_interrupt(int irq, void *data) * This has the effect of treating non-periodic like periodic. */ if ((devp->hd_flags & (HPET_IE | HPET_PERIODIC)) == HPET_IE) { - unsigned long m, t; + unsigned long m, t, mc, base, k; + struct hpet __iomem *hpet = devp->hd_hpet; + struct hpets *hpetp = devp->hd_hpets; t = devp->hd_ireqfreq; m = read_counter(&devp->hd_timer->hpet_compare); - write_counter(t + m, &devp->hd_timer->hpet_compare); + mc = read_counter(&hpet->hpet_mc); + /* The time for the next interrupt would logically be t + m, + * however, if we are very unlucky and the interrupt is delayed + * for longer than t then we will completely miss the next + * interrupt if we set t + m and an application will hang. + * Therefore we need to make a more complex computation assuming + * that there exists a k for which the following is true: + * k * t + base < mc + delta + * (k + 1) * t + base > mc + delta + * where t is the interval in hpet ticks for the given freq, + * base is the theoretical start value 0 < base < t, + * mc is the main counter value at the time of the interrupt, + * delta is the time it takes to write the a value to the + * comparator. + * k may then be computed as (mc - base + delta) / t . + */ + base = mc % t; + k = (mc - base + hpetp->hp_delta) / t; + write_counter(t * (k + 1) + base, + &devp->hd_timer->hpet_compare); } if (devp->hd_flags & HPET_SHARED_IRQ) From fb139dfeef9558a12ffdbf9e26951fd1a9304f3b Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 15 Jun 2011 15:08:55 -0700 Subject: [PATCH 454/595] drivers/tty/serial/pch_uart.c: don't oops if dmi_get_system_info returns NULL If dmi_get_system_info() returns NULL, pch_uart_init_port() will dereferencea a zero pointer. This oops was observed on an Atom based board which has no BIOS, but a bootloder which doesn't provide DMI data. Signed-off-by: Alexander Stein Cc: Greg KH Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/tty/serial/pch_uart.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index f2cb7503fcb2..465210930890 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1397,6 +1397,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, int fifosize, base_baud; int port_type; struct pch_uart_driver_data *board; + const char *board_name; board = &drv_dat[id->driver_data]; port_type = board->port_type; @@ -1412,7 +1413,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, base_baud = 1843200; /* 1.8432MHz */ /* quirk for CM-iTC board */ - if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC")) + board_name = dmi_get_system_info(DMI_BOARD_NAME); + if (board_name && strstr(board_name, "CM-iTC")) base_baud = 192000000; /* 192.0MHz */ switch (port_type) { From c7cbb02222eccb82bfd42696b01abceddae663f2 Mon Sep 17 00:00:00 2001 From: Wanlong Gao Date: Wed, 15 Jun 2011 15:08:56 -0700 Subject: [PATCH 455/595] rtc: fix build warnings in defconfigs RTC_CLASS is changed to bool, so 'm' is invalid. Signed-off-by: Wanlong Gao Acked-by: Mike Frysinger Acked-by: Wolfram Sang Acked-by: Hans-Christian Egtvedt Acked-by: Benjamin Herrenschmidt Cc: Guan Xuetao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/configs/davinci_all_defconfig | 2 +- arch/arm/configs/netx_defconfig | 2 +- arch/arm/configs/viper_defconfig | 2 +- arch/arm/configs/xcep_defconfig | 2 +- arch/arm/configs/zeus_defconfig | 2 +- arch/avr32/configs/atngw100_mrmt_defconfig | 2 +- arch/blackfin/configs/CM-BF548_defconfig | 2 +- arch/mips/configs/mtx1_defconfig | 2 +- arch/powerpc/configs/52xx/pcm030_defconfig | 2 +- arch/powerpc/configs/ps3_defconfig | 2 +- arch/sh/configs/titan_defconfig | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig index 889922ad229c..67b5abb6f857 100644 --- a/arch/arm/configs/davinci_all_defconfig +++ b/arch/arm/configs/davinci_all_defconfig @@ -157,7 +157,7 @@ CONFIG_LEDS_GPIO=m CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=m CONFIG_LEDS_TRIGGER_HEARTBEAT=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y CONFIG_XFS_FS=m diff --git a/arch/arm/configs/netx_defconfig b/arch/arm/configs/netx_defconfig index 316af5479d90..9c0ad7993986 100644 --- a/arch/arm/configs/netx_defconfig +++ b/arch/arm/configs/netx_defconfig @@ -60,7 +60,7 @@ CONFIG_FB_ARMCLCD=y # CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_INOTIFY=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig index 8b0c717378fa..1d01ddd33122 100644 --- a/arch/arm/configs/viper_defconfig +++ b/arch/arm/configs/viper_defconfig @@ -142,7 +142,7 @@ CONFIG_USB_GADGETFS=m CONFIG_USB_FILE_STORAGE=m CONFIG_USB_G_SERIAL=m CONFIG_USB_G_PRINTER=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=m CONFIG_RTC_DRV_SA1100=m CONFIG_EXT2_FS=m diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig index 5b5504143647..721832ffe2d7 100644 --- a/arch/arm/configs/xcep_defconfig +++ b/arch/arm/configs/xcep_defconfig @@ -73,7 +73,7 @@ CONFIG_SENSORS_MAX6650=m # CONFIG_VGA_CONSOLE is not set # CONFIG_HID_SUPPORT is not set # CONFIG_USB_SUPPORT is not set -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_SA1100=m CONFIG_DMADEVICES=y # CONFIG_DNOTIFY is not set diff --git a/arch/arm/configs/zeus_defconfig b/arch/arm/configs/zeus_defconfig index 960f65514d88..59577ad3f4ef 100644 --- a/arch/arm/configs/zeus_defconfig +++ b/arch/arm/configs/zeus_defconfig @@ -158,7 +158,7 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=m CONFIG_LEDS_TRIGGER_BACKLIGHT=m CONFIG_LEDS_TRIGGER_GPIO=m CONFIG_LEDS_TRIGGER_DEFAULT_ON=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_ISL1208=m CONFIG_RTC_DRV_PXA=m CONFIG_EXT2_FS=y diff --git a/arch/avr32/configs/atngw100_mrmt_defconfig b/arch/avr32/configs/atngw100_mrmt_defconfig index 6cb786c0baf6..77ca4f905d2c 100644 --- a/arch/avr32/configs/atngw100_mrmt_defconfig +++ b/arch/avr32/configs/atngw100_mrmt_defconfig @@ -110,7 +110,7 @@ CONFIG_LEDS_GPIO=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_S35390A=m CONFIG_RTC_DRV_AT32AP700X=m CONFIG_DMADEVICES=y diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig index 31d954216c05..9f1d08401fca 100644 --- a/arch/blackfin/configs/CM-BF548_defconfig +++ b/arch/blackfin/configs/CM-BF548_defconfig @@ -112,7 +112,7 @@ CONFIG_USB_G_SERIAL=m CONFIG_USB_G_PRINTER=m CONFIG_MMC=m CONFIG_SDH_BFIN=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_BFIN=m CONFIG_EXT2_FS=m # CONFIG_DNOTIFY is not set diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig index 37862b2ce363..807c97eed8a8 100644 --- a/arch/mips/configs/mtx1_defconfig +++ b/arch/mips/configs/mtx1_defconfig @@ -678,7 +678,7 @@ CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_INTF_DEV_UIE_EMUL=y CONFIG_RTC_DRV_TEST=m CONFIG_RTC_DRV_DS1307=m diff --git a/arch/powerpc/configs/52xx/pcm030_defconfig b/arch/powerpc/configs/52xx/pcm030_defconfig index 7f7e4a878602..22e719575c60 100644 --- a/arch/powerpc/configs/52xx/pcm030_defconfig +++ b/arch/powerpc/configs/52xx/pcm030_defconfig @@ -85,7 +85,7 @@ CONFIG_USB_OHCI_HCD=m CONFIG_USB_OHCI_HCD_PPC_OF_BE=y # CONFIG_USB_OHCI_HCD_PCI is not set CONFIG_USB_STORAGE=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_PCF8563=m CONFIG_EXT2_FS=m CONFIG_EXT3_FS=m diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig index 6472322bf13b..185c292b0f1c 100644 --- a/arch/powerpc/configs/ps3_defconfig +++ b/arch/powerpc/configs/ps3_defconfig @@ -141,7 +141,7 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y # CONFIG_USB_EHCI_HCD_PPC_OF is not set CONFIG_USB_OHCI_HCD=m CONFIG_USB_STORAGE=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_PS3=m CONFIG_EXT2_FS=m CONFIG_EXT3_FS=m diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig index 0f558914e760..e2cbd92d520b 100644 --- a/arch/sh/configs/titan_defconfig +++ b/arch/sh/configs/titan_defconfig @@ -227,7 +227,7 @@ CONFIG_USB_SERIAL=m CONFIG_USB_SERIAL_GENERIC=y CONFIG_USB_SERIAL_ARK3116=m CONFIG_USB_SERIAL_PL2303=m -CONFIG_RTC_CLASS=m +CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_SH=m CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y From 2b472611a32a72f4a118c069c2d62a1a3f087afd Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 15 Jun 2011 15:08:58 -0700 Subject: [PATCH 456/595] ksm: fix NULL pointer dereference in scan_get_next_rmap_item() Andrea Righi reported a case where an exiting task can race against ksmd::scan_get_next_rmap_item (http://lkml.org/lkml/2011/6/1/742) easily triggering a NULL pointer dereference in ksmd. ksm_scan.mm_slot == &ksm_mm_head with only one registered mm CPU 1 (__ksm_exit) CPU 2 (scan_get_next_rmap_item) list_empty() is false lock slot == &ksm_mm_head list_del(slot->mm_list) (list now empty) unlock lock slot = list_entry(slot->mm_list.next) (list is empty, so slot is still ksm_mm_head) unlock slot->mm == NULL ... Oops Close this race by revalidating that the new slot is not simply the list head again. Andrea's test case: #include #include #include #include #define BUFSIZE getpagesize() int main(int argc, char **argv) { void *ptr; if (posix_memalign(&ptr, getpagesize(), BUFSIZE) < 0) { perror("posix_memalign"); exit(1); } if (madvise(ptr, BUFSIZE, MADV_MERGEABLE) < 0) { perror("madvise"); exit(1); } *(char *)NULL = 0; return 0; } Reported-by: Andrea Righi Tested-by: Andrea Righi Cc: Andrea Arcangeli Signed-off-by: Hugh Dickins Signed-off-by: Chris Wright Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/ksm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mm/ksm.c b/mm/ksm.c index d708b3ef2260..9a68b0cf0a1c 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -1302,6 +1302,12 @@ static struct rmap_item *scan_get_next_rmap_item(struct page **page) slot = list_entry(slot->mm_list.next, struct mm_slot, mm_list); ksm_scan.mm_slot = slot; spin_unlock(&ksm_mmlist_lock); + /* + * Although we tested list_empty() above, a racing __ksm_exit + * of the last mm on the list may have removed it since then. + */ + if (slot == &ksm_mm_head) + return NULL; next_mm: ksm_scan.address = 0; ksm_scan.rmap_list = &slot->rmap_list; From ec8f9ceacef719a844ca269d654502af6a00a273 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 15 Jun 2011 15:08:59 -0700 Subject: [PATCH 457/595] drivers/misc/apds990x.c: apds990x_chip_on() should depend on CONFIG_PM || CONFIG_PM_RUNTIME Fixes this warning: drivers/misc/apds990x.c: At top level: drivers/misc/apds990x.c:613: warning: `apds990x_chip_on' defined but not used Signed-off-by: Geert Uytterhoeven Cc: Samu Onkalo Cc: Jonathan Cameron Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/apds990x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c index 200311fea369..e2a52e5cf449 100644 --- a/drivers/misc/apds990x.c +++ b/drivers/misc/apds990x.c @@ -609,6 +609,7 @@ static int apds990x_detect(struct apds990x_chip *chip) return ret; } +#if defined(CONFIG_PM) || defined(CONFIG_PM_RUNTIME) static int apds990x_chip_on(struct apds990x_chip *chip) { int err = regulator_bulk_enable(ARRAY_SIZE(chip->regs), @@ -624,6 +625,7 @@ static int apds990x_chip_on(struct apds990x_chip *chip) apds990x_mode_on(chip); return 0; } +#endif static int apds990x_chip_off(struct apds990x_chip *chip) { From 21c5977a836e399fc710ff2c5367845ed5c2527f Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 15 Jun 2011 15:09:01 -0700 Subject: [PATCH 458/595] alpha: fix several security issues Fix several security issues in Alpha-specific syscalls. Untested, but mostly trivial. 1. Signedness issue in osf_getdomainname allows copying out-of-bounds kernel memory to userland. 2. Signedness issue in osf_sysinfo allows copying large amounts of kernel memory to userland. 3. Typo (?) in osf_getsysinfo bounds minimum instead of maximum copy size, allowing copying large amounts of kernel memory to userland. 4. Usage of user pointer in osf_wait4 while under KERNEL_DS allows privilege escalation via writing return value of sys_wait4 to kernel memory. Signed-off-by: Dan Rosenberg Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/kernel/osf_sys.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 376f22130791..326f0a2d56e5 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -409,7 +409,7 @@ SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen) return -EFAULT; len = namelen; - if (namelen > 32) + if (len > 32) len = 32; down_read(&uts_sem); @@ -594,7 +594,7 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count) down_read(&uts_sem); res = sysinfo_table[offset]; len = strlen(res)+1; - if (len > count) + if ((unsigned long)len > (unsigned long)count) len = count; if (copy_to_user(buf, res, len)) err = -EFAULT; @@ -649,7 +649,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer, return 1; case GSI_GET_HWRPB: - if (nbytes < sizeof(*hwrpb)) + if (nbytes > sizeof(*hwrpb)) return -EINVAL; if (copy_to_user(buffer, hwrpb, nbytes) != 0) return -EFAULT; @@ -1008,6 +1008,7 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, { struct rusage r; long ret, err; + unsigned int status = 0; mm_segment_t old_fs; if (!ur) @@ -1016,13 +1017,15 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_wait4(pid, ustatus, options, (struct rusage __user *) &r); + ret = sys_wait4(pid, (unsigned int __user *) &status, options, + (struct rusage __user *) &r); set_fs (old_fs); if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur))) return -EFAULT; err = 0; + err |= put_user(status, ustatus); err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec); err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec); From 04c55715cbd5de526046745bca3d3b6ffa6641c6 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 15 Jun 2011 12:57:09 -0700 Subject: [PATCH 459/595] Documentation: update printk-formats.txt This patch updates the incomplete documentation concerning the printk extended format specifiers. Signed-off-by: Andrew Murray Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/printk-formats.txt | 119 ++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-) diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt index 1b5a5ddbc3ef..5df176ed59b8 100644 --- a/Documentation/printk-formats.txt +++ b/Documentation/printk-formats.txt @@ -9,7 +9,121 @@ If variable is of Type, use printk format specifier: size_t %zu or %zx ssize_t %zd or %zx -Raw pointer value SHOULD be printed with %p. +Raw pointer value SHOULD be printed with %p. The kernel supports +the following extended format specifiers for pointer types: + +Symbols/Function Pointers: + + %pF versatile_init+0x0/0x110 + %pf versatile_init + %pS versatile_init+0x0/0x110 + %ps versatile_init + %pB prev_fn_of_versatile_init+0x88/0x88 + + For printing symbols and function pointers. The 'S' and 's' specifiers + result in the symbol name with ('S') or without ('s') offsets. Where + this is used on a kernel without KALLSYMS - the symbol address is + printed instead. + + The 'B' specifier results in the symbol name with offsets and should be + used when printing stack backtraces. The specifier takes into + consideration the effect of compiler optimisations which may occur + when tail-call's are used and marked with the noreturn GCC attribute. + + On ia64, ppc64 and parisc64 architectures function pointers are + actually function descriptors which must first be resolved. The 'F' and + 'f' specifiers perform this resolution and then provide the same + functionality as the 'S' and 's' specifiers. + +Kernel Pointers: + + %pK 0x01234567 or 0x0123456789abcdef + + For printing kernel pointers which should be hidden from unprivileged + users. The behaviour of %pK depends on the kptr_restrict sysctl - see + Documentation/sysctl/kernel.txt for more details. + +Struct Resources: + + %pr [mem 0x60000000-0x6fffffff flags 0x2200] or + [mem 0x0000000060000000-0x000000006fffffff flags 0x2200] + %pR [mem 0x60000000-0x6fffffff pref] or + [mem 0x0000000060000000-0x000000006fffffff pref] + + For printing struct resources. The 'R' and 'r' specifiers result in a + printed resource with ('R') or without ('r') a decoded flags member. + +MAC/FDDI addresses: + + %pM 00:01:02:03:04:05 + %pMF 00-01-02-03-04-05 + %pm 000102030405 + + For printing 6-byte MAC/FDDI addresses in hex notation. The 'M' and 'm' + specifiers result in a printed address with ('M') or without ('m') byte + separators. The default byte separator is the colon (':'). + + Where FDDI addresses are concerned the 'F' specifier can be used after + the 'M' specifier to use dash ('-') separators instead of the default + separator. + +IPv4 addresses: + + %pI4 1.2.3.4 + %pi4 001.002.003.004 + %p[Ii][hnbl] + + For printing IPv4 dot-separated decimal addresses. The 'I4' and 'i4' + specifiers result in a printed address with ('i4') or without ('I4') + leading zeros. + + The additional 'h', 'n', 'b', and 'l' specifiers are used to specify + host, network, big or little endian order addresses respectively. Where + no specifier is provided the default network/big endian order is used. + +IPv6 addresses: + + %pI6 0001:0002:0003:0004:0005:0006:0007:0008 + %pi6 00010002000300040005000600070008 + %pI6c 1:2:3:4:5:6:7:8 + + For printing IPv6 network-order 16-bit hex addresses. The 'I6' and 'i6' + specifiers result in a printed address with ('I6') or without ('i6') + colon-separators. Leading zeros are always used. + + The additional 'c' specifier can be used with the 'I' specifier to + print a compressed IPv6 address as described by + http://tools.ietf.org/html/rfc5952 + +UUID/GUID addresses: + + %pUb 00010203-0405-0607-0809-0a0b0c0d0e0f + %pUB 00010203-0405-0607-0809-0A0B0C0D0E0F + %pUl 03020100-0504-0706-0809-0a0b0c0e0e0f + %pUL 03020100-0504-0706-0809-0A0B0C0E0E0F + + For printing 16-byte UUID/GUIDs addresses. The additional 'l', 'L', + 'b' and 'B' specifiers are used to specify a little endian order in + lower ('l') or upper case ('L') hex characters - and big endian order + in lower ('b') or upper case ('B') hex characters. + + Where no additional specifiers are used the default little endian + order with lower case hex characters will be printed. + +struct va_format: + + %pV + + For printing struct va_format structures. These contain a format string + and va_list as follows: + + struct va_format { + const char *fmt; + va_list *va; + }; + + Do not use this feature without some mechanism to verify the + correctness of the format string and va_list arguments. u64 SHOULD be printed with %llu/%llx, (unsigned long long): @@ -32,4 +146,5 @@ Reminder: sizeof() result is of type size_t. Thank you for your cooperation and attention. -By Randy Dunlap +By Randy Dunlap and +Andrew Murray From 06a2c45d6b4a7586eba7cd20dd656b08d8b63c2f Mon Sep 17 00:00:00 2001 From: "Maxin B. John" Date: Wed, 15 Jun 2011 12:58:29 -0700 Subject: [PATCH 460/595] Documentation: update kmemleak supported archs Instead of listing the architectures that are supported by kmemleak in Documentation/kmemleak.txt, just refer people to the list of supported architecutures in lib/Kconfig.debug so that Documentation/kmemleak.txt does not need more updates for this. Signed-off-by: Maxin B. John Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/kmemleak.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/kmemleak.txt b/Documentation/kmemleak.txt index 090e6ee04536..51063e681ca4 100644 --- a/Documentation/kmemleak.txt +++ b/Documentation/kmemleak.txt @@ -11,7 +11,9 @@ with the difference that the orphan objects are not freed but only reported via /sys/kernel/debug/kmemleak. A similar method is used by the Valgrind tool (memcheck --leak-check) to detect the memory leaks in user-space applications. -Kmemleak is supported on x86, arm, powerpc, sparc, sh, microblaze and tile. + +Please check DEBUG_KMEMLEAK dependencies in lib/Kconfig.debug for supported +architectures. Usage ----- From f6e07d38078e82a6aeaae00bb134591ef5ac1167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Sommer?= Date: Wed, 15 Jun 2011 12:59:45 -0700 Subject: [PATCH 461/595] Documentation: update cgroupfs mount point MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to commit 676db4af0430 ("cgroupfs: create /sys/fs/cgroup to mount cgroupfs on") the canonical mountpoint for the cgroup filesystem is /sys/fs/cgroup. Hence, this should be used in the documentation. Signed-off-by: Jörg Sommer Acked-by: Paul Menage Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/accounting/cgroupstats.txt | 4 +- Documentation/cgroups/blkio-controller.txt | 29 +++++----- Documentation/cgroups/cgroups.txt | 58 ++++++++++++-------- Documentation/cgroups/cpuacct.txt | 21 ++++--- Documentation/cgroups/cpusets.txt | 28 +++++----- Documentation/cgroups/devices.txt | 6 +- Documentation/cgroups/freezer-subsystem.txt | 20 +++---- Documentation/cgroups/memory.txt | 17 +++--- Documentation/scheduler/sched-design-CFS.txt | 7 ++- Documentation/scheduler/sched-rt-group.txt | 7 +-- Documentation/vm/hwpoison.txt | 6 +- 11 files changed, 109 insertions(+), 94 deletions(-) diff --git a/Documentation/accounting/cgroupstats.txt b/Documentation/accounting/cgroupstats.txt index eda40fd39cad..d16a9849e60e 100644 --- a/Documentation/accounting/cgroupstats.txt +++ b/Documentation/accounting/cgroupstats.txt @@ -21,7 +21,7 @@ information will not be available. To extract cgroup statistics a utility very similar to getdelays.c has been developed, the sample output of the utility is shown below -~/balbir/cgroupstats # ./getdelays -C "/cgroup/a" +~/balbir/cgroupstats # ./getdelays -C "/sys/fs/cgroup/a" sleeping 1, blocked 0, running 1, stopped 0, uninterruptible 0 -~/balbir/cgroupstats # ./getdelays -C "/cgroup" +~/balbir/cgroupstats # ./getdelays -C "/sys/fs/cgroup" sleeping 155, blocked 0, running 1, stopped 0, uninterruptible 2 diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt index 465351d4cf85..b1b1bfadc9c0 100644 --- a/Documentation/cgroups/blkio-controller.txt +++ b/Documentation/cgroups/blkio-controller.txt @@ -28,16 +28,19 @@ cgroups. Here is what you can do. - Enable group scheduling in CFQ CONFIG_CFQ_GROUP_IOSCHED=y -- Compile and boot into kernel and mount IO controller (blkio). +- Compile and boot into kernel and mount IO controller (blkio); see + cgroups.txt, Why are cgroups needed?. - mount -t cgroup -o blkio none /cgroup + mount -t tmpfs cgroup_root /sys/fs/cgroup + mkdir /sys/fs/cgroup/blkio + mount -t cgroup -o blkio none /sys/fs/cgroup/blkio - Create two cgroups - mkdir -p /cgroup/test1/ /cgroup/test2 + mkdir -p /sys/fs/cgroup/blkio/test1/ /sys/fs/cgroup/blkio/test2 - Set weights of group test1 and test2 - echo 1000 > /cgroup/test1/blkio.weight - echo 500 > /cgroup/test2/blkio.weight + echo 1000 > /sys/fs/cgroup/blkio/test1/blkio.weight + echo 500 > /sys/fs/cgroup/blkio/test2/blkio.weight - Create two same size files (say 512MB each) on same disk (file1, file2) and launch two dd threads in different cgroup to read those files. @@ -46,12 +49,12 @@ cgroups. Here is what you can do. echo 3 > /proc/sys/vm/drop_caches dd if=/mnt/sdb/zerofile1 of=/dev/null & - echo $! > /cgroup/test1/tasks - cat /cgroup/test1/tasks + echo $! > /sys/fs/cgroup/blkio/test1/tasks + cat /sys/fs/cgroup/blkio/test1/tasks dd if=/mnt/sdb/zerofile2 of=/dev/null & - echo $! > /cgroup/test2/tasks - cat /cgroup/test2/tasks + echo $! > /sys/fs/cgroup/blkio/test2/tasks + cat /sys/fs/cgroup/blkio/test2/tasks - At macro level, first dd should finish first. To get more precise data, keep on looking at (with the help of script), at blkio.disk_time and @@ -68,13 +71,13 @@ Throttling/Upper Limit policy - Enable throttling in block layer CONFIG_BLK_DEV_THROTTLING=y -- Mount blkio controller - mount -t cgroup -o blkio none /cgroup/blkio +- Mount blkio controller (see cgroups.txt, Why are cgroups needed?) + mount -t cgroup -o blkio none /sys/fs/cgroup/blkio - Specify a bandwidth rate on particular device for root group. The format for policy is ": ". - echo "8:16 1048576" > /cgroup/blkio/blkio.read_bps_device + echo "8:16 1048576" > /sys/fs/cgroup/blkio/blkio.read_bps_device Above will put a limit of 1MB/second on reads happening for root group on device having major/minor number 8:16. @@ -149,7 +152,7 @@ Proportional weight policy files Following is the format. - #echo dev_maj:dev_minor weight > /path/to/cgroup/blkio.weight_device + # echo dev_maj:dev_minor weight > blkio.weight_device Configure weight=300 on /dev/sdb (8:16) in this cgroup # echo 8:16 300 > blkio.weight_device # cat blkio.weight_device diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt index 0ed99f08f1f3..15bca101ff62 100644 --- a/Documentation/cgroups/cgroups.txt +++ b/Documentation/cgroups/cgroups.txt @@ -138,7 +138,7 @@ With the ability to classify tasks differently for different resources the admin can easily set up a script which receives exec notifications and depending on who is launching the browser he can - # echo browser_pid > /mnt///tasks + # echo browser_pid > /sys/fs/cgroup///tasks With only a single hierarchy, he now would potentially have to create a separate cgroup for every browser launched and associate it with @@ -153,9 +153,9 @@ apps enhanced CPU power, With ability to write pids directly to resource classes, it's just a matter of : - # echo pid > /mnt/network//tasks + # echo pid > /sys/fs/cgroup/network//tasks (after some time) - # echo pid > /mnt/network//tasks + # echo pid > /sys/fs/cgroup/network//tasks Without this ability, he would have to split the cgroup into multiple separate ones and then associate the new cgroups with the @@ -310,21 +310,24 @@ subsystem, this is the case for the cpuset. To start a new job that is to be contained within a cgroup, using the "cpuset" cgroup subsystem, the steps are something like: - 1) mkdir /dev/cgroup - 2) mount -t cgroup -ocpuset cpuset /dev/cgroup - 3) Create the new cgroup by doing mkdir's and write's (or echo's) in - the /dev/cgroup virtual file system. - 4) Start a task that will be the "founding father" of the new job. - 5) Attach that task to the new cgroup by writing its pid to the - /dev/cgroup tasks file for that cgroup. - 6) fork, exec or clone the job tasks from this founding father task. + 1) mount -t tmpfs cgroup_root /sys/fs/cgroup + 2) mkdir /sys/fs/cgroup/cpuset + 3) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset + 4) Create the new cgroup by doing mkdir's and write's (or echo's) in + the /sys/fs/cgroup virtual file system. + 5) Start a task that will be the "founding father" of the new job. + 6) Attach that task to the new cgroup by writing its pid to the + /sys/fs/cgroup/cpuset/tasks file for that cgroup. + 7) fork, exec or clone the job tasks from this founding father task. For example, the following sequence of commands will setup a cgroup named "Charlie", containing just CPUs 2 and 3, and Memory Node 1, and then start a subshell 'sh' in that cgroup: - mount -t cgroup cpuset -ocpuset /dev/cgroup - cd /dev/cgroup + mount -t tmpfs cgroup_root /sys/fs/cgroup + mkdir /sys/fs/cgroup/cpuset + mount -t cgroup cpuset -ocpuset /sys/fs/cgroup/cpuset + cd /sys/fs/cgroup/cpuset mkdir Charlie cd Charlie /bin/echo 2-3 > cpuset.cpus @@ -345,7 +348,7 @@ Creating, modifying, using the cgroups can be done through the cgroup virtual filesystem. To mount a cgroup hierarchy with all available subsystems, type: -# mount -t cgroup xxx /dev/cgroup +# mount -t cgroup xxx /sys/fs/cgroup The "xxx" is not interpreted by the cgroup code, but will appear in /proc/mounts so may be any useful identifying string that you like. @@ -354,23 +357,32 @@ Note: Some subsystems do not work without some user input first. For instance, if cpusets are enabled the user will have to populate the cpus and mems files for each new cgroup created before that group can be used. +As explained in section `1.2 Why are cgroups needed?' you should create +different hierarchies of cgroups for each single resource or group of +resources you want to control. Therefore, you should mount a tmpfs on +/sys/fs/cgroup and create directories for each cgroup resource or resource +group. + +# mount -t tmpfs cgroup_root /sys/fs/cgroup +# mkdir /sys/fs/cgroup/rg1 + To mount a cgroup hierarchy with just the cpuset and memory subsystems, type: -# mount -t cgroup -o cpuset,memory hier1 /dev/cgroup +# mount -t cgroup -o cpuset,memory hier1 /sys/fs/cgroup/rg1 To change the set of subsystems bound to a mounted hierarchy, just remount with different options: -# mount -o remount,cpuset,blkio hier1 /dev/cgroup +# mount -o remount,cpuset,blkio hier1 /sys/fs/cgroup/rg1 Now memory is removed from the hierarchy and blkio is added. Note this will add blkio to the hierarchy but won't remove memory or cpuset, because the new options are appended to the old ones: -# mount -o remount,blkio /dev/cgroup +# mount -o remount,blkio /sys/fs/cgroup/rg1 To Specify a hierarchy's release_agent: # mount -t cgroup -o cpuset,release_agent="/sbin/cpuset_release_agent" \ - xxx /dev/cgroup + xxx /sys/fs/cgroup/rg1 Note that specifying 'release_agent' more than once will return failure. @@ -379,17 +391,17 @@ when the hierarchy consists of a single (root) cgroup. Supporting the ability to arbitrarily bind/unbind subsystems from an existing cgroup hierarchy is intended to be implemented in the future. -Then under /dev/cgroup you can find a tree that corresponds to the -tree of the cgroups in the system. For instance, /dev/cgroup +Then under /sys/fs/cgroup/rg1 you can find a tree that corresponds to the +tree of the cgroups in the system. For instance, /sys/fs/cgroup/rg1 is the cgroup that holds the whole system. If you want to change the value of release_agent: -# echo "/sbin/new_release_agent" > /dev/cgroup/release_agent +# echo "/sbin/new_release_agent" > /sys/fs/cgroup/rg1/release_agent It can also be changed via remount. -If you want to create a new cgroup under /dev/cgroup: -# cd /dev/cgroup +If you want to create a new cgroup under /sys/fs/cgroup/rg1: +# cd /sys/fs/cgroup/rg1 # mkdir my_cgroup Now you want to do something with this cgroup. diff --git a/Documentation/cgroups/cpuacct.txt b/Documentation/cgroups/cpuacct.txt index 8b930946c52a..9ad85df4b983 100644 --- a/Documentation/cgroups/cpuacct.txt +++ b/Documentation/cgroups/cpuacct.txt @@ -10,26 +10,25 @@ directly present in its group. Accounting groups can be created by first mounting the cgroup filesystem. -# mkdir /cgroups -# mount -t cgroup -ocpuacct none /cgroups - -With the above step, the initial or the parent accounting group -becomes visible at /cgroups. At bootup, this group includes all the -tasks in the system. /cgroups/tasks lists the tasks in this cgroup. -/cgroups/cpuacct.usage gives the CPU time (in nanoseconds) obtained by -this group which is essentially the CPU time obtained by all the tasks +# mount -t cgroup -ocpuacct none /sys/fs/cgroup + +With the above step, the initial or the parent accounting group becomes +visible at /sys/fs/cgroup. At bootup, this group includes all the tasks in +the system. /sys/fs/cgroup/tasks lists the tasks in this cgroup. +/sys/fs/cgroup/cpuacct.usage gives the CPU time (in nanoseconds) obtained +by this group which is essentially the CPU time obtained by all the tasks in the system. -New accounting groups can be created under the parent group /cgroups. +New accounting groups can be created under the parent group /sys/fs/cgroup. -# cd /cgroups +# cd /sys/fs/cgroup # mkdir g1 # echo $$ > g1 The above steps create a new group g1 and move the current shell process (bash) into it. CPU time consumed by this bash and its children can be obtained from g1/cpuacct.usage and the same is accumulated in -/cgroups/cpuacct.usage also. +/sys/fs/cgroup/cpuacct.usage also. cpuacct.stat file lists a few statistics which further divide the CPU time obtained by the cgroup into user and system times. Currently diff --git a/Documentation/cgroups/cpusets.txt b/Documentation/cgroups/cpusets.txt index 98a30829af7a..5b0d78e55ccc 100644 --- a/Documentation/cgroups/cpusets.txt +++ b/Documentation/cgroups/cpusets.txt @@ -661,21 +661,21 @@ than stress the kernel. To start a new job that is to be contained within a cpuset, the steps are: - 1) mkdir /dev/cpuset - 2) mount -t cgroup -ocpuset cpuset /dev/cpuset + 1) mkdir /sys/fs/cgroup/cpuset + 2) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset 3) Create the new cpuset by doing mkdir's and write's (or echo's) in - the /dev/cpuset virtual file system. + the /sys/fs/cgroup/cpuset virtual file system. 4) Start a task that will be the "founding father" of the new job. 5) Attach that task to the new cpuset by writing its pid to the - /dev/cpuset tasks file for that cpuset. + /sys/fs/cgroup/cpuset tasks file for that cpuset. 6) fork, exec or clone the job tasks from this founding father task. For example, the following sequence of commands will setup a cpuset named "Charlie", containing just CPUs 2 and 3, and Memory Node 1, and then start a subshell 'sh' in that cpuset: - mount -t cgroup -ocpuset cpuset /dev/cpuset - cd /dev/cpuset + mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset + cd /sys/fs/cgroup/cpuset mkdir Charlie cd Charlie /bin/echo 2-3 > cpuset.cpus @@ -710,14 +710,14 @@ Creating, modifying, using the cpusets can be done through the cpuset virtual filesystem. To mount it, type: -# mount -t cgroup -o cpuset cpuset /dev/cpuset +# mount -t cgroup -o cpuset cpuset /sys/fs/cgroup/cpuset -Then under /dev/cpuset you can find a tree that corresponds to the -tree of the cpusets in the system. For instance, /dev/cpuset +Then under /sys/fs/cgroup/cpuset you can find a tree that corresponds to the +tree of the cpusets in the system. For instance, /sys/fs/cgroup/cpuset is the cpuset that holds the whole system. -If you want to create a new cpuset under /dev/cpuset: -# cd /dev/cpuset +If you want to create a new cpuset under /sys/fs/cgroup/cpuset: +# cd /sys/fs/cgroup/cpuset # mkdir my_cpuset Now you want to do something with this cpuset. @@ -765,12 +765,12 @@ wrapper around the cgroup filesystem. The command -mount -t cpuset X /dev/cpuset +mount -t cpuset X /sys/fs/cgroup/cpuset is equivalent to -mount -t cgroup -ocpuset,noprefix X /dev/cpuset -echo "/sbin/cpuset_release_agent" > /dev/cpuset/release_agent +mount -t cgroup -ocpuset,noprefix X /sys/fs/cgroup/cpuset +echo "/sbin/cpuset_release_agent" > /sys/fs/cgroup/cpuset/release_agent 2.2 Adding/removing cpus ------------------------ diff --git a/Documentation/cgroups/devices.txt b/Documentation/cgroups/devices.txt index 57ca4c89fe5c..16624a7f8222 100644 --- a/Documentation/cgroups/devices.txt +++ b/Documentation/cgroups/devices.txt @@ -22,16 +22,16 @@ removed from the child(ren). An entry is added using devices.allow, and removed using devices.deny. For instance - echo 'c 1:3 mr' > /cgroups/1/devices.allow + echo 'c 1:3 mr' > /sys/fs/cgroup/1/devices.allow allows cgroup 1 to read and mknod the device usually known as /dev/null. Doing - echo a > /cgroups/1/devices.deny + echo a > /sys/fs/cgroup/1/devices.deny will remove the default 'a *:* rwm' entry. Doing - echo a > /cgroups/1/devices.allow + echo a > /sys/fs/cgroup/1/devices.allow will add the 'a *:* rwm' entry to the whitelist. diff --git a/Documentation/cgroups/freezer-subsystem.txt b/Documentation/cgroups/freezer-subsystem.txt index 41f37fea1276..c21d77742a07 100644 --- a/Documentation/cgroups/freezer-subsystem.txt +++ b/Documentation/cgroups/freezer-subsystem.txt @@ -59,28 +59,28 @@ is non-freezable. * Examples of usage : - # mkdir /containers - # mount -t cgroup -ofreezer freezer /containers - # mkdir /containers/0 - # echo $some_pid > /containers/0/tasks + # mkdir /sys/fs/cgroup/freezer + # mount -t cgroup -ofreezer freezer /sys/fs/cgroup/freezer + # mkdir /sys/fs/cgroup/freezer/0 + # echo $some_pid > /sys/fs/cgroup/freezer/0/tasks to get status of the freezer subsystem : - # cat /containers/0/freezer.state + # cat /sys/fs/cgroup/freezer/0/freezer.state THAWED to freeze all tasks in the container : - # echo FROZEN > /containers/0/freezer.state - # cat /containers/0/freezer.state + # echo FROZEN > /sys/fs/cgroup/freezer/0/freezer.state + # cat /sys/fs/cgroup/freezer/0/freezer.state FREEZING - # cat /containers/0/freezer.state + # cat /sys/fs/cgroup/freezer/0/freezer.state FROZEN to unfreeze all tasks in the container : - # echo THAWED > /containers/0/freezer.state - # cat /containers/0/freezer.state + # echo THAWED > /sys/fs/cgroup/freezer/0/freezer.state + # cat /sys/fs/cgroup/freezer/0/freezer.state THAWED This is the basic mechanism which should do the right thing for user space task diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 510d64570d60..ffec2416aa74 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -264,16 +264,17 @@ b. Enable CONFIG_RESOURCE_COUNTERS c. Enable CONFIG_CGROUP_MEM_RES_CTLR d. Enable CONFIG_CGROUP_MEM_RES_CTLR_SWAP (to use swap extension) -1. Prepare the cgroups -# mkdir -p /cgroups -# mount -t cgroup none /cgroups -o memory +1. Prepare the cgroups (see cgroups.txt, Why are cgroups needed?) +# mount -t tmpfs none /sys/fs/cgroup +# mkdir /sys/fs/cgroup/memory +# mount -t cgroup none /sys/fs/cgroup/memory -o memory 2. Make the new group and move bash into it -# mkdir /cgroups/0 -# echo $$ > /cgroups/0/tasks +# mkdir /sys/fs/cgroup/memory/0 +# echo $$ > /sys/fs/cgroup/memory/0/tasks Since now we're in the 0 cgroup, we can alter the memory limit: -# echo 4M > /cgroups/0/memory.limit_in_bytes +# echo 4M > /sys/fs/cgroup/memory/0/memory.limit_in_bytes NOTE: We can use a suffix (k, K, m, M, g or G) to indicate values in kilo, mega or gigabytes. (Here, Kilo, Mega, Giga are Kibibytes, Mebibytes, Gibibytes.) @@ -281,11 +282,11 @@ mega or gigabytes. (Here, Kilo, Mega, Giga are Kibibytes, Mebibytes, Gibibytes.) NOTE: We can write "-1" to reset the *.limit_in_bytes(unlimited). NOTE: We cannot set limits on the root cgroup any more. -# cat /cgroups/0/memory.limit_in_bytes +# cat /sys/fs/cgroup/memory/0/memory.limit_in_bytes 4194304 We can check the usage: -# cat /cgroups/0/memory.usage_in_bytes +# cat /sys/fs/cgroup/memory/0/memory.usage_in_bytes 1216512 A successful write to this file does not guarantee a successful set of diff --git a/Documentation/scheduler/sched-design-CFS.txt b/Documentation/scheduler/sched-design-CFS.txt index 99961993257a..91ecff07cede 100644 --- a/Documentation/scheduler/sched-design-CFS.txt +++ b/Documentation/scheduler/sched-design-CFS.txt @@ -223,9 +223,10 @@ When CONFIG_FAIR_GROUP_SCHED is defined, a "cpu.shares" file is created for each group created using the pseudo filesystem. See example steps below to create task groups and modify their CPU share using the "cgroups" pseudo filesystem. - # mkdir /dev/cpuctl - # mount -t cgroup -ocpu none /dev/cpuctl - # cd /dev/cpuctl + # mount -t tmpfs cgroup_root /sys/fs/cgroup + # mkdir /sys/fs/cgroup/cpu + # mount -t cgroup -ocpu none /sys/fs/cgroup/cpu + # cd /sys/fs/cgroup/cpu # mkdir multimedia # create "multimedia" group of tasks # mkdir browser # create "browser" group of tasks diff --git a/Documentation/scheduler/sched-rt-group.txt b/Documentation/scheduler/sched-rt-group.txt index 605b0d40329d..71b54d549987 100644 --- a/Documentation/scheduler/sched-rt-group.txt +++ b/Documentation/scheduler/sched-rt-group.txt @@ -129,9 +129,8 @@ priority! Enabling CONFIG_RT_GROUP_SCHED lets you explicitly allocate real CPU bandwidth to task groups. -This uses the /cgroup virtual file system and -"/cgroup//cpu.rt_runtime_us" to control the CPU time reserved for each -control group. +This uses the cgroup virtual file system and "/cpu.rt_runtime_us" +to control the CPU time reserved for each control group. For more information on working with control groups, you should read Documentation/cgroups/cgroups.txt as well. @@ -150,7 +149,7 @@ For now, this can be simplified to just the following (but see Future plans): =============== There is work in progress to make the scheduling period for each group -("/cgroup//cpu.rt_period_us") configurable as well. +("/cpu.rt_period_us") configurable as well. The constraint on the period is that a subgroup must have a smaller or equal period to its parent. But realistically its not very useful _yet_ diff --git a/Documentation/vm/hwpoison.txt b/Documentation/vm/hwpoison.txt index 12f9ba20ccb7..550068466605 100644 --- a/Documentation/vm/hwpoison.txt +++ b/Documentation/vm/hwpoison.txt @@ -129,12 +129,12 @@ Limit injection to pages owned by memgroup. Specified by inode number of the memcg. Example: - mkdir /cgroup/hwpoison + mkdir /sys/fs/cgroup/mem/hwpoison usemem -m 100 -s 1000 & - echo `jobs -p` > /cgroup/hwpoison/tasks + echo `jobs -p` > /sys/fs/cgroup/mem/hwpoison/tasks - memcg_ino=$(ls -id /cgroup/hwpoison | cut -f1 -d' ') + memcg_ino=$(ls -id /sys/fs/cgroup/mem/hwpoison | cut -f1 -d' ') echo $memcg_ino > /debug/hwpoison/corrupt-filter-memcg page-types -p `pidof init` --hwpoison # shall do nothing From 67de0162fbb78713fcb23cb2502b380faa8bde73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Sommer?= Date: Wed, 15 Jun 2011 13:00:47 -0700 Subject: [PATCH 462/595] Documentation: fix cgroup typos and formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix format and spelling. Signed-off-by: Jörg Sommer Acked-by: Paul Menage Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/cgroups/blkio-controller.txt | 2 +- Documentation/cgroups/cgroups.txt | 2 +- Documentation/cgroups/memory.txt | 22 +++++++++++----------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt index b1b1bfadc9c0..cd45c8ea7463 100644 --- a/Documentation/cgroups/blkio-controller.txt +++ b/Documentation/cgroups/blkio-controller.txt @@ -111,7 +111,7 @@ Hierarchical Cgroups CFQ and throttling will practically treat all groups at same level. pivot - / | \ \ + / / \ \ root test1 test2 test3 Down the line we can implement hierarchical accounting/control support diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt index 15bca101ff62..cd67e90003c0 100644 --- a/Documentation/cgroups/cgroups.txt +++ b/Documentation/cgroups/cgroups.txt @@ -142,7 +142,7 @@ and depending on who is launching the browser he can With only a single hierarchy, he now would potentially have to create a separate cgroup for every browser launched and associate it with -approp network and other resource class. This may lead to +appropriate network and other resource class. This may lead to proliferation of such cgroups. Also lets say that the administrator would like to give enhanced network diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index ffec2416aa74..06eb6d957c83 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -1,8 +1,8 @@ Memory Resource Controller -NOTE: The Memory Resource Controller has been generically been referred - to as the memory controller in this document. Do not confuse memory - controller used here with the memory controller that is used in hardware. +NOTE: The Memory Resource Controller has generically been referred to as the + memory controller in this document. Do not confuse memory controller + used here with the memory controller that is used in hardware. (For editors) In this document: @@ -182,7 +182,7 @@ behind this approach is that a cgroup that aggressively uses a shared page will eventually get charged for it (once it is uncharged from the cgroup that brought it in -- this will happen on memory pressure). -Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used.. +Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used. When you do swapoff and make swapped-out pages of shmem(tmpfs) to be backed into memory in force, charges for pages are accounted against the caller of swapoff rather than the users of shmem. @@ -214,7 +214,7 @@ affecting global LRU, memory+swap limit is better than just limiting swap from OS point of view. * What happens when a cgroup hits memory.memsw.limit_in_bytes -When a cgroup his memory.memsw.limit_in_bytes, it's useless to do swap-out +When a cgroup hits memory.memsw.limit_in_bytes, it's useless to do swap-out in this cgroup. Then, swap-out will not be done by cgroup routine and file caches are dropped. But as mentioned above, global LRU can do swapout memory from it for sanity of the system's memory management state. You can't forbid @@ -491,13 +491,13 @@ The hierarchy is created by creating the appropriate cgroups in the cgroup filesystem. Consider for example, the following cgroup filesystem hierarchy - root + root / | \ - / | \ - a b c - | \ - | \ - d e + / | \ + a b c + | \ + | \ + d e In the diagram above, with hierarchical accounting enabled, all memory usage of e, is accounted to its ancestors up until the root (i.e, c and root), From 13fca640bb8ab611a50e0ba120b186faa2994d6c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 15 Jun 2011 21:53:52 -0700 Subject: [PATCH 463/595] Revert "fs/exec.c: use BUILD_BUG_ON for VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP" This reverts commit 7f81c8890c15a10f5220bebae3b6dfae4961962a. It turns out that it's not actually a build-time check on x86-64 UML, which does some seriously crazy stuff with VM_STACK_FLAGS. The VM_STACK_FLAGS define depends on the arch-supplied VM_STACK_DEFAULT_FLAGS value, and on x86-64 UML we have arch/um/sys-x86_64/shared/sysdep/vm-flags.h: #define VM_STACK_DEFAULT_FLAGS \ (test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags) #define VM_STACK_DEFAULT_FLAGS vm_stack_flags (yes, seriously: two different #define's for that thing, with the first one being inside an "#ifdef TIF_IA32") It's possible that it is UML that should just be fixed in this area, but for now let's just undo the (very small) optimization. Reported-by: Randy Dunlap Acked-by: Andrew Morton Cc: Michal Hocko Cc: Richard Weinberger Signed-off-by: Linus Torvalds --- fs/exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/exec.c b/fs/exec.c index b54f74f3cd80..97e0d52d72fd 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -277,7 +277,7 @@ static int __bprm_mm_init(struct linux_binprm *bprm) * use STACK_TOP because that can depend on attributes which aren't * configured yet. */ - BUILD_BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP); + BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP); vma->vm_end = STACK_TOP_MAX; vma->vm_start = vma->vm_end - PAGE_SIZE; vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP; From fb2e73947461d55a3166f94a8a545b78d6635262 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 15 Jun 2011 06:08:18 +0000 Subject: [PATCH 464/595] sh: ecovec: Add renesas_usbhs support Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/sh/boards/mach-ecovec24/setup.c | 48 ++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 3a32741cc0ac..513cb1a2e6c8 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -232,6 +233,52 @@ static struct platform_device usb1_common_device = { .resource = usb1_common_resources, }; +/* + * USBHS + */ +static int usbhs_get_id(struct platform_device *pdev) +{ + return gpio_get_value(GPIO_PTB3); +} + +static struct renesas_usbhs_platform_info usbhs_info = { + .platform_callback = { + .get_id = usbhs_get_id, + }, + .driver_param = { + .buswait_bwait = 4, + .detection_delay = 5, + }, +}; + +static struct resource usbhs_resources[] = { + [0] = { + .start = 0xa4d90000, + .end = 0xa4d90124 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 66, + .end = 66, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usbhs_device = { + .name = "renesas_usbhs", + .id = 1, + .dev = { + .dma_mask = NULL, /* not use dma */ + .coherent_dma_mask = 0xffffffff, + .platform_data = &usbhs_info, + }, + .num_resources = ARRAY_SIZE(usbhs_resources), + .resource = usbhs_resources, + .archdata = { + .hwblk_id = HWBLK_USB1, + }, +}; + /* LCDC */ const static struct fb_videomode ecovec_lcd_modes[] = { { @@ -897,6 +944,7 @@ static struct platform_device *ecovec_devices[] __initdata = { &sh_eth_device, &usb0_host_device, &usb1_common_device, + &usbhs_device, &lcdc_device, &ceu0_device, &ceu1_device, From 261a9af671a79b750cb170bac620601d686535c1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 15 Jun 2011 06:08:28 +0000 Subject: [PATCH 465/595] sh: sh7724: Add USBHS DMAEngine support Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/sh/include/cpu-sh4/cpu/sh7724.h | 8 ++++++ arch/sh/kernel/cpu/sh4a/setup-sh7724.c | 40 ++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/arch/sh/include/cpu-sh4/cpu/sh7724.h b/arch/sh/include/cpu-sh4/cpu/sh7724.h index 3daef8ecbc63..cbc47e6bcab5 100644 --- a/arch/sh/include/cpu-sh4/cpu/sh7724.h +++ b/arch/sh/include/cpu-sh4/cpu/sh7724.h @@ -298,6 +298,14 @@ enum { SHDMA_SLAVE_SCIF4_RX, SHDMA_SLAVE_SCIF5_TX, SHDMA_SLAVE_SCIF5_RX, + SHDMA_SLAVE_USB0D0_TX, + SHDMA_SLAVE_USB0D0_RX, + SHDMA_SLAVE_USB0D1_TX, + SHDMA_SLAVE_USB0D1_RX, + SHDMA_SLAVE_USB1D0_TX, + SHDMA_SLAVE_USB1D0_RX, + SHDMA_SLAVE_USB1D1_TX, + SHDMA_SLAVE_USB1D1_RX, SHDMA_SLAVE_SDHI0_TX, SHDMA_SLAVE_SDHI0_RX, SHDMA_SLAVE_SDHI1_TX, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c index 0333fe9e3881..134a397b1918 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c @@ -92,6 +92,46 @@ static const struct sh_dmae_slave_config sh7724_dmae_slaves[] = { .addr = 0xa4e50024, .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), .mid_rid = 0x36, + }, { + .slave_id = SHDMA_SLAVE_USB0D0_TX, + .addr = 0xA4D80100, + .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0x73, + }, { + .slave_id = SHDMA_SLAVE_USB0D0_RX, + .addr = 0xA4D80100, + .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0x73, + }, { + .slave_id = SHDMA_SLAVE_USB0D1_TX, + .addr = 0xA4D80120, + .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0x77, + }, { + .slave_id = SHDMA_SLAVE_USB0D1_RX, + .addr = 0xA4D80120, + .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0x77, + }, { + .slave_id = SHDMA_SLAVE_USB1D0_TX, + .addr = 0xA4D90100, + .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0xab, + }, { + .slave_id = SHDMA_SLAVE_USB1D0_RX, + .addr = 0xA4D90100, + .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0xab, + }, { + .slave_id = SHDMA_SLAVE_USB1D1_TX, + .addr = 0xA4D90120, + .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0xaf, + }, { + .slave_id = SHDMA_SLAVE_USB1D1_RX, + .addr = 0xA4D90120, + .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .mid_rid = 0xaf, }, { .slave_id = SHDMA_SLAVE_SDHI0_TX, .addr = 0x04ce0030, From a46e0899eec7a3069bcadd45dfba7bf67c6ed016 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 15 Jun 2011 15:47:09 -0700 Subject: [PATCH 466/595] rcu: use softirq instead of kthreads except when RCU_BOOST=y This patch #ifdefs RCU kthreads out of the kernel unless RCU_BOOST=y, thus eliminating context-switch overhead if RCU priority boosting has not been configured. Signed-off-by: Paul E. McKenney --- kernel/rcutree.c | 59 ++++++++++++++++++++++++++++++----------- kernel/rcutree.h | 8 ++++-- kernel/rcutree_plugin.h | 41 +++++++++++++++++----------- kernel/rcutree_trace.c | 32 +++++++++++++++------- 4 files changed, 99 insertions(+), 41 deletions(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index ae5c9ea68662..429d4949f0eb 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -87,6 +87,8 @@ static struct rcu_state *rcu_state; int rcu_scheduler_active __read_mostly; EXPORT_SYMBOL_GPL(rcu_scheduler_active); +#ifdef CONFIG_RCU_BOOST + /* * Control variables for per-CPU and per-rcu_node kthreads. These * handle all flavors of RCU. @@ -98,9 +100,11 @@ DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_loops); DEFINE_PER_CPU(char, rcu_cpu_has_work); static char rcu_kthreads_spawnable; +#endif /* #ifdef CONFIG_RCU_BOOST */ + static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu); -static void invoke_rcu_cpu_kthread(void); -static void __invoke_rcu_cpu_kthread(void); +static void invoke_rcu_core(void); +static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp); #define RCU_KTHREAD_PRIO 1 /* RT priority for per-CPU kthreads. */ @@ -1089,6 +1093,7 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp) int need_report = 0; struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu); struct rcu_node *rnp; +#ifdef CONFIG_RCU_BOOST struct task_struct *t; /* Stop the CPU's kthread. */ @@ -1097,6 +1102,7 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp) per_cpu(rcu_cpu_kthread_task, cpu) = NULL; kthread_stop(t); } +#endif /* #ifdef CONFIG_RCU_BOOST */ /* Exclude any attempts to start a new grace period. */ raw_spin_lock_irqsave(&rsp->onofflock, flags); @@ -1232,7 +1238,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp) /* Re-raise the RCU softirq if there are callbacks remaining. */ if (cpu_has_callbacks_ready_to_invoke(rdp)) - invoke_rcu_cpu_kthread(); + invoke_rcu_core(); } /* @@ -1278,7 +1284,7 @@ void rcu_check_callbacks(int cpu, int user) } rcu_preempt_check_callbacks(cpu); if (rcu_pending(cpu)) - invoke_rcu_cpu_kthread(); + invoke_rcu_core(); } #ifdef CONFIG_SMP @@ -1444,9 +1450,11 @@ __rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp) /* If there are callbacks ready, invoke them. */ if (cpu_has_callbacks_ready_to_invoke(rdp)) - __invoke_rcu_cpu_kthread(); + invoke_rcu_callbacks(rsp, rdp); } +#ifdef CONFIG_RCU_BOOST + static void rcu_kthread_do_work(void) { rcu_do_batch(&rcu_sched_state, &__get_cpu_var(rcu_sched_data)); @@ -1454,6 +1462,8 @@ static void rcu_kthread_do_work(void) rcu_preempt_do_callbacks(); } +#endif /* #ifdef CONFIG_RCU_BOOST */ + /* * Do softirq processing for the current CPU. */ @@ -1474,25 +1484,22 @@ static void rcu_process_callbacks(struct softirq_action *unused) * the current CPU with interrupts disabled, the rcu_cpu_kthread_task * cannot disappear out from under us. */ -static void __invoke_rcu_cpu_kthread(void) +static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp) { - unsigned long flags; - - local_irq_save(flags); - __this_cpu_write(rcu_cpu_has_work, 1); - if (__this_cpu_read(rcu_cpu_kthread_task) == NULL) { - local_irq_restore(flags); + if (likely(!rsp->boost)) { + rcu_do_batch(rsp, rdp); return; } - wake_up_process(__this_cpu_read(rcu_cpu_kthread_task)); - local_irq_restore(flags); + invoke_rcu_callbacks_kthread(); } -static void invoke_rcu_cpu_kthread(void) +static void invoke_rcu_core(void) { raise_softirq(RCU_SOFTIRQ); } +#ifdef CONFIG_RCU_BOOST + /* * Wake up the specified per-rcu_node-structure kthread. * Because the per-rcu_node kthreads are immortal, we don't need @@ -1818,6 +1825,18 @@ static int __init rcu_spawn_kthreads(void) } early_initcall(rcu_spawn_kthreads); +#else /* #ifdef CONFIG_RCU_BOOST */ + +static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) +{ +} + +static void rcu_cpu_kthread_setrt(int cpu, int to_rt) +{ +} + +#endif /* #else #ifdef CONFIG_RCU_BOOST */ + static void __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu), struct rcu_state *rsp) @@ -2224,6 +2243,8 @@ static void __cpuinit rcu_prepare_cpu(int cpu) rcu_preempt_init_percpu_data(cpu); } +#ifdef CONFIG_RCU_BOOST + static void __cpuinit rcu_prepare_kthreads(int cpu) { struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu); @@ -2237,6 +2258,14 @@ static void __cpuinit rcu_prepare_kthreads(int cpu) } } +#else /* #ifdef CONFIG_RCU_BOOST */ + +static void __cpuinit rcu_prepare_kthreads(int cpu) +{ +} + +#endif /* #else #ifdef CONFIG_RCU_BOOST */ + /* * Handle CPU online/offline notification events. */ diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 0fed6b934d2a..434288c7ad88 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -369,6 +369,7 @@ struct rcu_state { /* period because */ /* force_quiescent_state() */ /* was running. */ + u8 boost; /* Subject to priority boost. */ unsigned long gpnum; /* Current gp number. */ unsigned long completed; /* # of last completed gp. */ @@ -439,7 +440,6 @@ static void rcu_preempt_offline_cpu(int cpu); #endif /* #ifdef CONFIG_HOTPLUG_CPU */ static void rcu_preempt_check_callbacks(int cpu); static void rcu_preempt_process_callbacks(void); -static void rcu_preempt_do_callbacks(void); void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU) static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp); @@ -451,11 +451,15 @@ static void rcu_preempt_send_cbs_to_online(void); static void __init __rcu_init_preempt(void); static void rcu_needs_cpu_flush(void); static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags); +static void rcu_preempt_boost_start_gp(struct rcu_node *rnp); +static void invoke_rcu_callbacks_kthread(void); +#ifdef CONFIG_RCU_BOOST +static void rcu_preempt_do_callbacks(void); static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, cpumask_var_t cm); -static void rcu_preempt_boost_start_gp(struct rcu_node *rnp); static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, struct rcu_node *rnp, int rnp_index); +#endif /* #ifdef CONFIG_RCU_BOOST */ #endif /* #ifndef RCU_TREE_NONCORE */ diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 38d09c5f2b41..2772386c0421 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -602,11 +602,15 @@ static void rcu_preempt_process_callbacks(void) &__get_cpu_var(rcu_preempt_data)); } +#ifdef CONFIG_RCU_BOOST + static void rcu_preempt_do_callbacks(void) { rcu_do_batch(&rcu_preempt_state, &__get_cpu_var(rcu_preempt_data)); } +#endif /* #ifdef CONFIG_RCU_BOOST */ + /* * Queue a preemptible-RCU callback for invocation after a grace period. */ @@ -1002,10 +1006,6 @@ static void rcu_preempt_process_callbacks(void) { } -static void rcu_preempt_do_callbacks(void) -{ -} - /* * Wait for an rcu-preempt grace period, but make it happen quickly. * But because preemptible RCU does not exist, map to rcu-sched. @@ -1257,6 +1257,23 @@ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) } } +/* + * Wake up the per-CPU kthread to invoke RCU callbacks. + */ +static void invoke_rcu_callbacks_kthread(void) +{ + unsigned long flags; + + local_irq_save(flags); + __this_cpu_write(rcu_cpu_has_work, 1); + if (__this_cpu_read(rcu_cpu_kthread_task) == NULL) { + local_irq_restore(flags); + return; + } + wake_up_process(__this_cpu_read(rcu_cpu_kthread_task)); + local_irq_restore(flags); +} + /* * Set the affinity of the boost kthread. The CPU-hotplug locks are * held, so no one should be messing with the existence of the boost @@ -1297,6 +1314,7 @@ static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, if (&rcu_preempt_state != rsp) return 0; + rsp->boost = 1; if (rnp->boost_kthread_task != NULL) return 0; t = kthread_create(rcu_boost_kthread, (void *)rnp, @@ -1319,22 +1337,15 @@ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) raw_spin_unlock_irqrestore(&rnp->lock, flags); } -static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, - cpumask_var_t cm) +static void invoke_rcu_callbacks_kthread(void) { + WARN_ON_ONCE(1); } static void rcu_preempt_boost_start_gp(struct rcu_node *rnp) { } -static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, - struct rcu_node *rnp, - int rnp_index) -{ - return 0; -} - #endif /* #else #ifdef CONFIG_RCU_BOOST */ #ifndef CONFIG_SMP @@ -1509,7 +1520,7 @@ static DEFINE_PER_CPU(unsigned long, rcu_dyntick_holdoff); * * Because it is not legal to invoke rcu_process_callbacks() with irqs * disabled, we do one pass of force_quiescent_state(), then do a - * invoke_rcu_cpu_kthread() to cause rcu_process_callbacks() to be invoked + * invoke_rcu_core() to cause rcu_process_callbacks() to be invoked * later. The per-cpu rcu_dyntick_drain variable controls the sequencing. */ int rcu_needs_cpu(int cpu) @@ -1560,7 +1571,7 @@ int rcu_needs_cpu(int cpu) /* If RCU callbacks are still pending, RCU still needs this CPU. */ if (c) - invoke_rcu_cpu_kthread(); + invoke_rcu_core(); return c; } diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c index 9678cc3650f5..4e144876dc68 100644 --- a/kernel/rcutree_trace.c +++ b/kernel/rcutree_trace.c @@ -46,6 +46,8 @@ #define RCU_TREE_NONCORE #include "rcutree.h" +#ifdef CONFIG_RCU_BOOST + DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status); DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_cpu); DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_loops); @@ -58,6 +60,8 @@ static char convert_kthread_status(unsigned int kthread_status) return "SRWOY"[kthread_status]; } +#endif /* #ifdef CONFIG_RCU_BOOST */ + static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) { if (!rdp->beenonline) @@ -76,7 +80,7 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) rdp->dynticks_fqs); #endif /* #ifdef CONFIG_NO_HZ */ seq_printf(m, " of=%lu ri=%lu", rdp->offline_fqs, rdp->resched_ipi); - seq_printf(m, " ql=%ld qs=%c%c%c%c kt=%d/%c/%d ktl=%x b=%ld", + seq_printf(m, " ql=%ld qs=%c%c%c%c", rdp->qlen, ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != rdp->nxttail[RCU_NEXT_TAIL]], @@ -84,13 +88,16 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) rdp->nxttail[RCU_NEXT_READY_TAIL]], ".W"[rdp->nxttail[RCU_DONE_TAIL] != rdp->nxttail[RCU_WAIT_TAIL]], - ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]], + ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]]); +#ifdef CONFIG_RCU_BOOST + seq_printf(m, " kt=%d/%c/%d ktl=%x", per_cpu(rcu_cpu_has_work, rdp->cpu), convert_kthread_status(per_cpu(rcu_cpu_kthread_status, rdp->cpu)), per_cpu(rcu_cpu_kthread_cpu, rdp->cpu), - per_cpu(rcu_cpu_kthread_loops, rdp->cpu) & 0xffff, - rdp->blimit); + per_cpu(rcu_cpu_kthread_loops, rdp->cpu) & 0xffff); +#endif /* #ifdef CONFIG_RCU_BOOST */ + seq_printf(m, " b=%ld", rdp->blimit); seq_printf(m, " ci=%lu co=%lu ca=%lu\n", rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted); } @@ -147,18 +154,21 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp) rdp->dynticks_fqs); #endif /* #ifdef CONFIG_NO_HZ */ seq_printf(m, ",%lu,%lu", rdp->offline_fqs, rdp->resched_ipi); - seq_printf(m, ",%ld,\"%c%c%c%c\",%d,\"%c\",%ld", rdp->qlen, + seq_printf(m, ",%ld,\"%c%c%c%c\"", rdp->qlen, ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != rdp->nxttail[RCU_NEXT_TAIL]], ".R"[rdp->nxttail[RCU_WAIT_TAIL] != rdp->nxttail[RCU_NEXT_READY_TAIL]], ".W"[rdp->nxttail[RCU_DONE_TAIL] != rdp->nxttail[RCU_WAIT_TAIL]], - ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]], + ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]]); +#ifdef CONFIG_RCU_BOOST + seq_printf(m, ",%d,\"%c\"", per_cpu(rcu_cpu_has_work, rdp->cpu), convert_kthread_status(per_cpu(rcu_cpu_kthread_status, - rdp->cpu)), - rdp->blimit); + rdp->cpu))); +#endif /* #ifdef CONFIG_RCU_BOOST */ + seq_printf(m, ",%ld", rdp->blimit); seq_printf(m, ",%lu,%lu,%lu\n", rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted); } @@ -169,7 +179,11 @@ static int show_rcudata_csv(struct seq_file *m, void *unused) #ifdef CONFIG_NO_HZ seq_puts(m, "\"dt\",\"dt nesting\",\"dt NMI nesting\",\"df\","); #endif /* #ifdef CONFIG_NO_HZ */ - seq_puts(m, "\"of\",\"ri\",\"ql\",\"b\",\"ci\",\"co\",\"ca\"\n"); + seq_puts(m, "\"of\",\"ri\",\"ql\",\"qs\""); +#ifdef CONFIG_RCU_BOOST + seq_puts(m, "\"kt\",\"ktl\""); +#endif /* #ifdef CONFIG_RCU_BOOST */ + seq_puts(m, ",\"b\",\"ci\",\"co\",\"ca\"\n"); #ifdef CONFIG_TREE_PREEMPT_RCU seq_puts(m, "\"rcu_preempt:\"\n"); PRINT_RCU_DATA(rcu_preempt_data, print_one_rcu_data_csv, m); From 45e97ab65026a3391cb2c938f834ca5db4d2e5b3 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 15 Jun 2011 11:26:47 +0200 Subject: [PATCH 467/595] drm: populate irq_by_busid-member for pci MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 8410ea (drm: rework PCI/platform driver interface) implemented drm_pci_irq_by_busid() but forgot to make it available in the drm_pci_bus-struct. This caused a freeze on my Radeon9600-equipped laptop when executing glxgears. Thanks to Michel for noticing the flaw. [airlied: made function static also] Reported-by: Michel Dänzer Signed-off-by: Wolfram Sang Cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index e1aee4f6a7c6..b6a19cb07caf 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -251,7 +251,7 @@ int drm_pci_set_unique(struct drm_device *dev, } -int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) +static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) { if ((p->busnum >> 8) != drm_get_pci_domain(dev) || (p->busnum & 0xff) != dev->pdev->bus->number || @@ -292,6 +292,7 @@ static struct drm_bus drm_pci_bus = { .get_name = drm_pci_get_name, .set_busid = drm_pci_set_busid, .set_unique = drm_pci_set_unique, + .irq_by_busid = drm_pci_irq_by_busid, .agp_init = drm_pci_agp_init, }; From 1c88d74f3a0b748b0c7e88e91e9d0503815d5689 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 14 Jun 2011 19:15:53 +0000 Subject: [PATCH 468/595] drm/radeon/kms: signed fix for evergreen thermal temperature is signed. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 86157b172c88..7e3d96e7ac04 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -88,7 +88,8 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) /* get temperature in millidegrees */ int evergreen_get_temp(struct radeon_device *rdev) { - u32 temp, toffset, actual_temp = 0; + u32 temp, toffset; + int actual_temp = 0; if (rdev->family == CHIP_JUNIPER) { toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >> From 7c88d2b80ba5c175398013842782461a3b980130 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 14 Jun 2011 15:27:38 +0000 Subject: [PATCH 469/595] drm/radeon/kms: be more pedantic about the g5 quirk (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I don't think Apple offered any other cards for this mac, so I doubt this will be an issue, but just to be on the safe side, check the pci ids as well. v2: fix spelling in commit message Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher Cc: Joachim Henke Cc: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_combios.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 797c8bcbb6a4..e4594676a07c 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -1553,9 +1553,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) (rdev->pdev->subsystem_device == 0x4a48)) { /* Mac X800 */ rdev->mode_info.connector_table = CT_MAC_X800; - } else if (of_machine_is_compatible("PowerMac7,2") || - of_machine_is_compatible("PowerMac7,3")) { - /* Mac G5 9600 */ + } else if ((of_machine_is_compatible("PowerMac7,2") || + of_machine_is_compatible("PowerMac7,3")) && + (rdev->pdev->device == 0x4150) && + (rdev->pdev->subsystem_vendor == 0x1002) && + (rdev->pdev->subsystem_device == 0x4150)) { + /* Mac G5 tower 9600 */ rdev->mode_info.connector_table = CT_MAC_G5_9600; } else #endif /* CONFIG_PPC_PMAC */ From e6ba759980e65084b0db9f1684d9d65a2a3e1741 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 22:02:51 +0000 Subject: [PATCH 470/595] drm/radeon/kms: clear wb memory by default Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index e680501c78ea..7cfaa7e2f3b5 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -215,6 +215,8 @@ int radeon_wb_init(struct radeon_device *rdev) return r; } + /* clear wb memory */ + memset((char *)rdev->wb.wb, 0, RADEON_GPU_PAGE_SIZE); /* disable event_write fences */ rdev->wb.use_event = false; /* disabled via module param */ From f49dadb82dde88092827b6d058e7164e75e96759 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 14 Jun 2011 06:13:54 +0000 Subject: [PATCH 471/595] drm: make debug levels match in edid failure code. this puts the header and followup at the same loglevel as the hex dump code. Signed-off-by: Dave Airlie Reviewed-by: Alex Deucher --- drivers/gpu/drm/drm_edid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 0a9357c66ff8..3618d29c79a2 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -184,9 +184,9 @@ drm_edid_block_valid(u8 *raw_edid) bad: if (raw_edid) { - DRM_ERROR("Raw EDID:\n"); + printk(KERN_ERR "Raw EDID:\n"); print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH); - printk("\n"); + printk(KERN_ERR "\n"); } return 0; } From 4a9a8b71e12d41abb71c4e741bff524f016cfef4 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 14 Jun 2011 06:13:55 +0000 Subject: [PATCH 472/595] drm/radeon: workaround a hw bug on some radeon chipsets with all-0 EDIDs. Some RS690 chipsets seem to end up with floating connectors, either a DVI connector isn't actually populated, or an add-in HDMI card is available but not installed. In this case we seem to get a NULL byte response for each byte of the i2c transaction, so we detect this case and if we see it we don't do anymore DDC transactions on this connector. I've tested this on my RS690 without the HDMI card installed and it seems to work fine. Signed-off-by: Dave Airlie Reviewed-by: Alex Deucher --- drivers/gpu/drm/drm_edid.c | 15 +++++++++++++++ drivers/gpu/drm/radeon/radeon_connectors.c | 7 +++++++ include/drm/drm_crtc.h | 2 ++ 3 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3618d29c79a2..09292193dafe 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -258,6 +258,17 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, return ret == 2 ? 0 : -1; } +static bool drm_edid_is_zero(u8 *in_edid, int length) +{ + int i; + u32 *raw_edid = (u32 *)in_edid; + + for (i = 0; i < length / 4; i++) + if (*(raw_edid + i) != 0) + return false; + return true; +} + static u8 * drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) { @@ -273,6 +284,10 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) goto out; if (drm_edid_block_valid(block)) break; + if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { + connector->null_edid_counter++; + goto carp; + } } if (i == 4) goto carp; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 9c2929c7e79f..c04e18ee8a87 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -836,6 +836,13 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) if (!radeon_connector->edid) { DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", drm_get_connector_name(connector)); + /* rs690 seems to have a problem with connectors not existing and always + * return a block of 0's. If we see this just stop polling on this output */ + if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) && radeon_connector->base.null_edid_counter) { + ret = connector_status_disconnected; + DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector)); + radeon_connector->ddc_bus = NULL; + } } else { radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 9573e0ce3120..33d12f87f0e0 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -520,6 +520,8 @@ struct drm_connector { uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; uint32_t force_encoder_id; struct drm_encoder *encoder; /* currently active encoder */ + + int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */ }; /** From cafe8d8413399119c3f4cd575e0eb27e2654b9d5 Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Sat, 4 Jun 2011 15:36:43 +0000 Subject: [PATCH 473/595] drivers/gpu/drm: use printk_ratelimited instead of printk_ratelimit Since printk_ratelimit() shouldn't be used anymore (see comment in include/linux/printk.h), replace it with printk_ratelimited. Signed-off-by: Christian Dietrich Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_ioc32.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index d61d185cf040..4a058c7af6c0 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -28,6 +28,7 @@ * IN THE SOFTWARE. */ #include +#include #include "drmP.h" #include "drm_core.h" @@ -253,10 +254,10 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd, return -EFAULT; m32.handle = (unsigned long)handle; - if (m32.handle != (unsigned long)handle && printk_ratelimit()) - printk(KERN_ERR "compat_drm_addmap truncated handle" - " %p for type %d offset %x\n", - handle, m32.type, m32.offset); + if (m32.handle != (unsigned long)handle) + printk_ratelimited(KERN_ERR "compat_drm_addmap truncated handle" + " %p for type %d offset %x\n", + handle, m32.type, m32.offset); if (copy_to_user(argp, &m32, sizeof(m32))) return -EFAULT; From 9be34c9d526c305efb332ad53460b57d5f8edb3e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 16 Jun 2011 00:35:09 -0700 Subject: [PATCH 474/595] mm: get rid of the most spurious find_vma_prev() users We have some users of this function that date back to before the vma list was doubly linked, and just are silly. These days, you can find the previous vma by just following the vma->vm_prev pointer. In some cases you don't need any find_vma() lookup at all, and in other cases you're better off with the regular "find_vma()" that uses the vma cache front-end lookup. Some "find_vma_prev()" users are still valid, though. For example, in the case of a stack that grows up, it can be the case that we don't find any 'vma' at all (because we're looking up an address that is past the last vma), and that the stack that we want to grow is the 'prev' vma. But that kind of special case aside, we generally should prefer to use 'find_vma()'. Noticed due to a totally unrelated POWER memory corruption bug that just happened to hit in 'find_vma_prev()' and made me go "Hmm - why are we using that function here?". Signed-off-by: Linus Torvalds --- mm/mmap.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index bbdc9af5e117..d49736ff8a8d 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -906,14 +906,7 @@ struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *vma) if (anon_vma) return anon_vma; try_prev: - /* - * It is potentially slow to have to call find_vma_prev here. - * But it's only on the first write fault on the vma, not - * every time, and we could devise a way to avoid it later - * (e.g. stash info in next's anon_vma_node when assigning - * an anon_vma, or when trying vma_merge). Another time. - */ - BUG_ON(find_vma_prev(vma->vm_mm, vma->vm_start, &near) != vma); + near = vma->vm_prev; if (!near) goto none; @@ -2044,9 +2037,10 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len) return -EINVAL; /* Find the first overlapping VMA */ - vma = find_vma_prev(mm, start, &prev); + vma = find_vma(mm, start); if (!vma) return 0; + prev = vma->vm_prev; /* we have start < vma->vm_end */ /* if it doesn't overlap, we have nothing.. */ From 203db2952bc87f5d610c9ad53a7d02b85897721f Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Jun 2011 23:03:38 +0200 Subject: [PATCH 475/595] tools/perf: Fix static build of perf tool To build a statically linked version of the perf tool all needed libraries must be added in the correct order to get the symbols resolved. Currently this is broken when, e.g. python or newt support is enabled -- libpython needs libpthread which is an unconditional link dependency of the perf tool; libslang needs libm, another unconditional dependency. To solve the problem in the long run without the need to keep track of transitive library dependencies, simply make the linker look at the EXTLIBS multiple times until it has all symbols resolved. Signed-off-by: Mathias Krause Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Link: http://lkml.kernel.org/r/1308171818-20370-1-git-send-email-minipli@googlemail.com Signed-off-by: Ingo Molnar --- tools/perf/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 032ba6398a5c..940257b5774e 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -633,7 +633,7 @@ prefix_SQ = $(subst ','\'',$(prefix)) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) -LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive $(EXTLIBS) +LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group ALL_CFLAGS += $(BASIC_CFLAGS) ALL_CFLAGS += $(ARCH_CFLAGS) From c3a4924565e2eecf2539871abd123d35be6d76d5 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 16 Jun 2011 12:21:34 +0200 Subject: [PATCH 476/595] Revert "HID: magicmouse: ignore 'ivalid report id' while switching modes" This reverts commit 23746a66d7d9e73402c68ef00d708796b97ebd72. It turned out that the actual reason for failure is not the device firmware, but bug in Bluetooth stack, which will be fixed by patch by Ville Tervo which corrects the mask handling for CSR 1.1 Dongles. Reported-and-tested-by: Ed Tomlinson Reported-and-tested-by: Chase Douglas Signed-off-by: Jiri Kosina --- drivers/hid/hid-magicmouse.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index a5eda4c8127a..0ec91c18a421 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -501,17 +501,9 @@ static int magicmouse_probe(struct hid_device *hdev, } report->size = 6; - /* - * The device reponds with 'invalid report id' when feature - * report switching it into multitouch mode is sent to it. - * - * This results in -EIO from the _raw low-level transport callback, - * but there seems to be no other way of switching the mode. - * Thus the super-ugly hacky success check below. - */ ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), HID_FEATURE_REPORT); - if (ret != -EIO) { + if (ret != sizeof(feature)) { hid_err(hdev, "unable to request touch data (%d)\n", ret); goto err_stop_hw; } From 55b220cafadd71b9f83759f7b396998b2547dc5f Mon Sep 17 00:00:00 2001 From: Ambresh K Date: Wed, 15 Jun 2011 13:40:45 -0700 Subject: [PATCH 477/595] gpio/omap4: Fix missing interrupts during device wakeup due to IOPAD. If gpio pins from bank[2-5] are marked as wakeup enable and if the wake is through gpio IO pad wakeup, then that wakeup gpio interrupt is lost. In the current implementation, GPIO driver stores the context of DATAIN of all the gpio in the bank. During GPIO resuming, it checks DATAIN with wakeup enabled pins of gpio bank. If there is status change, then manually toggle GPIO_LEVELDETECT to generate pseudo interrupt. Reported-by: Philippe Mazet Tested-by: Philippe Mazet Signed-off-by: Ambresh K Signed-off-by: Grant Likely --- drivers/gpio/gpio-omap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 01f74a8459d9..35bebde23e83 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -469,8 +469,9 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, + OMAP24XX_GPIO_CLEARWKUENA); } } - /* This part needs to be executed always for OMAP34xx */ - if (cpu_is_omap34xx() || (bank->non_wakeup_gpios & gpio_bit)) { + /* This part needs to be executed always for OMAP{34xx, 44xx} */ + if (cpu_is_omap34xx() || cpu_is_omap44xx() || + (bank->non_wakeup_gpios & gpio_bit)) { /* * Log the edge gpio and manually trigger the IRQ * after resume if the input level changes From 158f1e95180d01ebfd7cd5c8de23050528303f26 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 14 Jun 2011 17:06:02 -0700 Subject: [PATCH 478/595] gpio: include linux/gpio.h where needed Some files use GPIOF_ macros but don't include the header file for them. These macros are being moved to , so add includes for where needed. Signed-off-by: Randy Dunlap Signed-off-by: Grant Likely --- arch/arm/mach-pxa/spitz_pm.c | 1 + drivers/pcmcia/pxa2xx_vpac270.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c index 7fe74067d85f..094279aefe9c 100644 --- a/arch/arm/mach-pxa/spitz_pm.c +++ b/arch/arm/mach-pxa/spitz_pm.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/pcmcia/pxa2xx_vpac270.c b/drivers/pcmcia/pxa2xx_vpac270.c index 435002dfc3ca..712baab3c83d 100644 --- a/drivers/pcmcia/pxa2xx_vpac270.c +++ b/drivers/pcmcia/pxa2xx_vpac270.c @@ -11,6 +11,7 @@ * */ +#include #include #include From c001fb72a7b705f902bdfdd05b5d2408efe6f848 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 14 Jun 2011 17:05:11 -0700 Subject: [PATCH 479/595] gpio: add GPIOF_ values regardless on kconfig settings Make GPIOF_ defined values available even when GPIOLIB nor GENERIC_GPIO is enabled by moving them to . Fixes these build errors in linux-next: sound/soc/codecs/ak4641.c:524: error: 'GPIOF_OUT_INIT_LOW' undeclared (first use in this function) sound/soc/codecs/wm8915.c:2921: error: 'GPIOF_OUT_INIT_LOW' undeclared (first use in this function) Signed-off-by: Randy Dunlap Signed-off-by: Grant Likely --- include/asm-generic/gpio.h | 10 ---------- include/linux/gpio.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index fcdcb5d5c995..d494001b1226 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -170,16 +170,6 @@ extern int __gpio_cansleep(unsigned gpio); extern int __gpio_to_irq(unsigned gpio); -#define GPIOF_DIR_OUT (0 << 0) -#define GPIOF_DIR_IN (1 << 0) - -#define GPIOF_INIT_LOW (0 << 1) -#define GPIOF_INIT_HIGH (1 << 1) - -#define GPIOF_IN (GPIOF_DIR_IN) -#define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW) -#define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH) - /** * struct gpio - a structure describing a GPIO with configuration * @gpio: the GPIO number diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 32d47e710661..17b5a0d80e42 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -3,6 +3,17 @@ /* see Documentation/gpio.txt */ +/* make these flag values available regardless of GPIO kconfig options */ +#define GPIOF_DIR_OUT (0 << 0) +#define GPIOF_DIR_IN (1 << 0) + +#define GPIOF_INIT_LOW (0 << 1) +#define GPIOF_INIT_HIGH (1 << 1) + +#define GPIOF_IN (GPIOF_DIR_IN) +#define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW) +#define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH) + #ifdef CONFIG_GENERIC_GPIO #include From 63f6fe92c6b3cbf4c0bbbea4b31fdd3d68e21e4d Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 16 Jun 2011 17:16:37 +0200 Subject: [PATCH 480/595] netfilter: ip_tables: fix compile with debug Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ip_tables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 764743843503..24e556e83a3b 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -566,7 +566,7 @@ check_entry(const struct ipt_entry *e, const char *name) const struct xt_entry_target *t; if (!ip_checkentry(&e->ip)) { - duprintf("ip check failed %p %s.\n", e, par->match->name); + duprintf("ip check failed %p %s.\n", e, name); return -EINVAL; } From 58d5a0257d2fd89fbe4451f704193cc95b0a9c97 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 16 Jun 2011 17:24:17 +0200 Subject: [PATCH 481/595] netfilter: ipt_ecn: fix protocol check in ecn_mt_check() Check for protocol inversion in ecn_mt_check() and remove the unnecessary runtime check for IPPROTO_TCP in ecn_mt(). Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ipt_ecn.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c index af6e9c778345..aaa85be1b2d8 100644 --- a/net/ipv4/netfilter/ipt_ecn.c +++ b/net/ipv4/netfilter/ipt_ecn.c @@ -76,8 +76,6 @@ static bool ecn_mt(const struct sk_buff *skb, struct xt_action_param *par) return false; if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { - if (ip_hdr(skb)->protocol != IPPROTO_TCP) - return false; if (!match_tcp(skb, info, &par->hotdrop)) return false; } @@ -97,7 +95,7 @@ static int ecn_mt_check(const struct xt_mtchk_param *par) return -EINVAL; if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) && - ip->proto != IPPROTO_TCP) { + (ip->proto != IPPROTO_TCP || ip->invflags & IPT_INV_PROTO)) { pr_info("cannot match TCP bits in rule for non-tcp packets\n"); return -EINVAL; } From db898aa2ef6529fa80891e754d353063611c77de Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 16 Jun 2011 17:24:55 +0200 Subject: [PATCH 482/595] netfilter: ipt_ecn: fix inversion for IP header ECN match Userspace allows to specify inversion for IP header ECN matches, the kernel silently accepts it, but doesn't invert the match result. Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ipt_ecn.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c index aaa85be1b2d8..2b57e52c746c 100644 --- a/net/ipv4/netfilter/ipt_ecn.c +++ b/net/ipv4/netfilter/ipt_ecn.c @@ -25,7 +25,8 @@ MODULE_LICENSE("GPL"); static inline bool match_ip(const struct sk_buff *skb, const struct ipt_ecn_info *einfo) { - return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect; + return ((ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect) ^ + !!(einfo->invert & IPT_ECN_OP_MATCH_IP); } static inline bool match_tcp(const struct sk_buff *skb, From 2c38de4c1f8da799bdca0e4bb40ca13f2174d3e8 Mon Sep 17 00:00:00 2001 From: Nicolas Cavallari Date: Thu, 16 Jun 2011 17:27:04 +0200 Subject: [PATCH 483/595] netfilter: fix looped (broad|multi)cast's MAC handling By default, when broadcast or multicast packet are sent from a local application, they are sent to the interface then looped by the kernel to other local applications, going throught netfilter hooks in the process. These looped packet have their MAC header removed from the skb by the kernel looping code. This confuse various netfilter's netlink queue, netlink log and the legacy ip_queue, because they try to extract a hardware address from these packets, but extracts a part of the IP header instead. This patch prevent NFQUEUE, NFLOG and ip_QUEUE to include a MAC header if there is none in the packet. Signed-off-by: Nicolas Cavallari Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ip_queue.c | 3 ++- net/ipv6/netfilter/ip6_queue.c | 3 ++- net/netfilter/nfnetlink_log.c | 3 ++- net/netfilter/nfnetlink_queue.c | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index f7f9bd7ba12d..5c9b9d963918 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -203,7 +203,8 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) else pmsg->outdev_name[0] = '\0'; - if (entry->indev && entry->skb->dev) { + if (entry->indev && entry->skb->dev && + entry->skb->mac_header != entry->skb->network_header) { pmsg->hw_type = entry->skb->dev->type; pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addr); diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 065fe405fb58..249394863284 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -204,7 +204,8 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) else pmsg->outdev_name[0] = '\0'; - if (entry->indev && entry->skb->dev) { + if (entry->indev && entry->skb->dev && + entry->skb->mac_header != entry->skb->network_header) { pmsg->hw_type = entry->skb->dev->type; pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addr); } diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index e0ee010935e7..2e7ccbb43ddb 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -456,7 +456,8 @@ __build_packet_message(struct nfulnl_instance *inst, if (skb->mark) NLA_PUT_BE32(inst->skb, NFULA_MARK, htonl(skb->mark)); - if (indev && skb->dev) { + if (indev && skb->dev && + skb->mac_header != skb->network_header) { struct nfulnl_msg_packet_hw phw; int len = dev_parse_header(skb, phw.hw_addr); if (len > 0) { diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index b83123f12b42..fdd2fafe0a14 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -335,7 +335,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, if (entskb->mark) NLA_PUT_BE32(skb, NFQA_MARK, htonl(entskb->mark)); - if (indev && entskb->dev) { + if (indev && entskb->dev && + entskb->mac_header != entskb->network_header) { struct nfqnl_msg_packet_hw phw; int len = dev_parse_header(entskb, phw.hw_addr); if (len) { From 50338b889dc504c69e0cb316ac92d1b9e51f3c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=B6r=C3=B6k=20Edwin?= Date: Thu, 16 Jun 2011 00:06:14 +0300 Subject: [PATCH 484/595] fix wrong iput on d_inode introduced by e6bc45d65d MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Git bisection shows that commit e6bc45d65df8599fdbae73be9cec4ceed274db53 causes BUG_ONs under high I/O load: kernel BUG at fs/inode.c:1368! [ 2862.501007] Call Trace: [ 2862.501007] [] d_kill+0xf8/0x140 [ 2862.501007] [] dput+0xc9/0x190 [ 2862.501007] [] fput+0x15f/0x210 [ 2862.501007] [] filp_close+0x61/0x90 [ 2862.501007] [] sys_close+0xb1/0x110 [ 2862.501007] [] system_call_fastpath+0x16/0x1b A reliable way to reproduce this bug is: Login to KDE, run 'rsnapshot sync', and apt-get install openjdk-6-jdk, and apt-get remove openjdk-6-jdk. The buggy part of the patch is this: struct inode *inode = NULL; ..... - if (nd.last.name[nd.last.len]) - goto slashes; inode = dentry->d_inode; - if (inode) - ihold(inode); + if (nd.last.name[nd.last.len] || !inode) + goto slashes; + ihold(inode) ... if (inode) iput(inode); /* truncate the inode here */ If nd.last.name[nd.last.len] is nonzero (and thus goto slashes branch is taken), and dentry->d_inode is non-NULL, then this code now does an additional iput on the inode, which is wrong. Fix this by only setting the inode variable if nd.last.name[nd.last.len] is 0. Reference: https://lkml.org/lkml/2011/6/15/50 Reported-by: Norbert Preining Reported-by: Török Edwin Cc: "Theodore Ts'o" Cc: Al Viro Signed-off-by: Török Edwin Signed-off-by: Al Viro --- fs/namei.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index 9802345df5e7..6301963b161f 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2713,8 +2713,10 @@ static long do_unlinkat(int dfd, const char __user *pathname) error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { /* Why not before? Because we want correct error value */ + if (nd.last.name[nd.last.len]) + goto slashes; inode = dentry->d_inode; - if (nd.last.name[nd.last.len] || !inode) + if (!inode) goto slashes; ihold(inode); error = mnt_want_write(nd.path.mnt); From 8aef18845266f5c05904c610088f2d1ed58f6be3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 16 Jun 2011 15:10:06 +0100 Subject: [PATCH 485/595] VFS: Fix vfsmount overput on simultaneous automount [Kudos to dhowells for tracking that crap down] If two processes attempt to cause automounting on the same mountpoint at the same time, the vfsmount holding the mountpoint will be left with one too few references on it, causing a BUG when the kernel tries to clean up. The problem is that lock_mount() drops the caller's reference to the mountpoint's vfsmount in the case where it finds something already mounted on the mountpoint as it transits to the mounted filesystem and replaces path->mnt with the new mountpoint vfsmount. During a pathwalk, however, we don't take a reference on the vfsmount if it is the same as the one in the nameidata struct, but do_add_mount() doesn't know this. The fix is to make sure we have a ref on the vfsmount of the mountpoint before calling do_add_mount(). However, if lock_mount() doesn't transit, we're then left with an extra ref on the mountpoint vfsmount which needs releasing. We can handle that in follow_managed() by not making assumptions about what we can and what we cannot get from lookup_mnt() as the current code does. The callers of follow_managed() expect that reference to path->mnt will be grabbed iff path->mnt has been changed. follow_managed() and follow_automount() keep track of whether such reference has been grabbed and assume that it'll happen in those and only those cases that'll have us return with changed path->mnt. That assumption is almost correct - it breaks in case of racing automounts and in even harder to hit race between following a mountpoint and a couple of mount --move. The thing is, we don't need to make that assumption at all - after the end of loop in follow_manage() we can check if path->mnt has ended up unchanged and do mntput() if needed. The BUG can be reproduced with the following test program: #include #include #include #include #include int main(int argc, char **argv) { int pid, ws; struct stat buf; pid = fork(); stat(argv[1], &buf); if (pid > 0) wait(&ws); return 0; } and the following procedure: (1) Mount an NFS volume that on the server has something else mounted on a subdirectory. For instance, I can mount / from my server: mount warthog:/ /mnt -t nfs4 -r On the server /data has another filesystem mounted on it, so NFS will see a change in FSID as it walks down the path, and will mark /mnt/data as being a mountpoint. This will cause the automount code to be triggered. !!! Do not look inside the mounted fs at this point !!! (2) Run the above program on a file within the submount to generate two simultaneous automount requests: /tmp/forkstat /mnt/data/testfile (3) Unmount the automounted submount: umount /mnt/data (4) Unmount the original mount: umount /mnt At this point the kernel should throw a BUG with something like the following: BUG: Dentry ffff880032e3c5c0{i=2,n=} still in use (1) [unmount of nfs4 0:12] Note that the bug appears on the root dentry of the original mount, not the mountpoint and not the submount because sys_umount() hasn't got to its final mntput_no_expire() yet, but this isn't so obvious from the call trace: [] shrink_dcache_for_umount+0x69/0x82 [] generic_shutdown_super+0x37/0x15b [] ? nfs_super_return_all_delegations+0x2e/0x1b1 [nfs] [] kill_anon_super+0x1d/0x7e [] nfs4_kill_super+0x60/0xb6 [nfs] [] deactivate_locked_super+0x34/0x83 [] deactivate_super+0x6f/0x7b [] mntput_no_expire+0x18d/0x199 [] mntput+0x3b/0x44 [] release_mounts+0xa2/0xbf [] sys_umount+0x47a/0x4ba [] ? trace_hardirqs_on_caller+0x1fd/0x22f [] system_call_fastpath+0x16/0x1b as do_umount() is inlined. However, you can see release_mounts() in there. Note also that it may be necessary to have multiple CPU cores to be able to trigger this bug. Tested-by: Jeff Layton Tested-by: Ian Kent Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/namei.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 6301963b161f..9e425e7e6c8f 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -812,6 +812,11 @@ static int follow_automount(struct path *path, unsigned flags, if (!mnt) /* mount collision */ return 0; + if (!*need_mntput) { + /* lock_mount() may release path->mnt on error */ + mntget(path->mnt); + *need_mntput = true; + } err = finish_automount(mnt, path); switch (err) { @@ -819,12 +824,9 @@ static int follow_automount(struct path *path, unsigned flags, /* Someone else made a mount here whilst we were busy */ return 0; case 0: - dput(path->dentry); - if (*need_mntput) - mntput(path->mnt); + path_put(path); path->mnt = mnt; path->dentry = dget(mnt->mnt_root); - *need_mntput = true; return 0; default: return err; @@ -844,9 +846,10 @@ static int follow_automount(struct path *path, unsigned flags, */ static int follow_managed(struct path *path, unsigned flags) { + struct vfsmount *mnt = path->mnt; /* held by caller, must be left alone */ unsigned managed; bool need_mntput = false; - int ret; + int ret = 0; /* Given that we're not holding a lock here, we retain the value in a * local variable for each dentry as we look at it so that we don't see @@ -861,7 +864,7 @@ static int follow_managed(struct path *path, unsigned flags) BUG_ON(!path->dentry->d_op->d_manage); ret = path->dentry->d_op->d_manage(path->dentry, false); if (ret < 0) - return ret == -EISDIR ? 0 : ret; + break; } /* Transit to a mounted filesystem. */ @@ -887,14 +890,19 @@ static int follow_managed(struct path *path, unsigned flags) if (managed & DCACHE_NEED_AUTOMOUNT) { ret = follow_automount(path, flags, &need_mntput); if (ret < 0) - return ret == -EISDIR ? 0 : ret; + break; continue; } /* We didn't change the current path point */ break; } - return 0; + + if (need_mntput && path->mnt == mnt) + mntput(path->mnt); + if (ret == -EISDIR) + ret = 0; + return ret; } int follow_down_one(struct path *path) From e1d76719ea3f3f755d597cef9c2087bdda5fea43 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 14 Jun 2011 15:00:18 -0700 Subject: [PATCH 486/595] staging: fix iio builds when IIO_RING_BUFFER is not enabled Fix build by moving enum list outside of #ifdef CONFIG_IIO_RING_BUFFER. drivers/staging/iio/accel/adis16201_core.c:413: error: 'ADIS16201_SCAN_SUPPLY' undeclared here (not in a function) drivers/staging/iio/accel/adis16201_core.c:417: error: 'ADIS16201_SCAN_TEMP' undeclared here (not in a function) .. drivers/staging/iio/accel/adis16203_core.c:374: error: 'ADIS16203_SCAN_SUPPLY' undeclared here (not in a function) drivers/staging/iio/accel/adis16203_core.c:378: error: 'ADIS16203_SCAN_AUX_ADC' undeclared here (not in a function) .. Signed-off-by: Randy Dunlap Acked-by: Jonathan Cameron Cc: linux-iio@vger.kernel.org Signed-off-by: Linus Torvalds --- drivers/staging/iio/accel/adis16201.h | 2 +- drivers/staging/iio/accel/adis16203.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201.h b/drivers/staging/iio/accel/adis16201.h index 0b9b85424dfa..4cc1a5bfab40 100644 --- a/drivers/staging/iio/accel/adis16201.h +++ b/drivers/staging/iio/accel/adis16201.h @@ -81,7 +81,6 @@ struct adis16201_state { int adis16201_set_irq(struct iio_dev *indio_dev, bool enable); -#ifdef CONFIG_IIO_RING_BUFFER enum adis16201_scan { ADIS16201_SCAN_SUPPLY, ADIS16201_SCAN_ACC_X, @@ -92,6 +91,7 @@ enum adis16201_scan { ADIS16201_SCAN_INCLI_Y, }; +#ifdef CONFIG_IIO_RING_BUFFER void adis16201_remove_trigger(struct iio_dev *indio_dev); int adis16201_probe_trigger(struct iio_dev *indio_dev); diff --git a/drivers/staging/iio/accel/adis16203.h b/drivers/staging/iio/accel/adis16203.h index 8bb8ce50c248..175e21bb9b40 100644 --- a/drivers/staging/iio/accel/adis16203.h +++ b/drivers/staging/iio/accel/adis16203.h @@ -76,7 +76,6 @@ struct adis16203_state { int adis16203_set_irq(struct iio_dev *indio_dev, bool enable); -#ifdef CONFIG_IIO_RING_BUFFER enum adis16203_scan { ADIS16203_SCAN_SUPPLY, ADIS16203_SCAN_AUX_ADC, @@ -85,6 +84,7 @@ enum adis16203_scan { ADIS16203_SCAN_INCLI_Y, }; +#ifdef CONFIG_IIO_RING_BUFFER void adis16203_remove_trigger(struct iio_dev *indio_dev); int adis16203_probe_trigger(struct iio_dev *indio_dev); From 42c1edd345c8412d96e7a362ee06feb7be73bb6c Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Thu, 16 Jun 2011 17:29:22 +0200 Subject: [PATCH 487/595] netfilter: nf_nat: avoid double seq_adjust for loopback Avoid double seq adjustment for loopback traffic because it causes silent repetition of TCP data. One example is passive FTP with DNAT rule and difference in the length of IP addresses. This patch adds check if packet is sent and received via loopback device. As the same conntrack is used both for outgoing and incoming direction, we restrict seq adjustment to happen only in POSTROUTING. Signed-off-by: Julian Anastasov Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack.h | 6 ++++++ net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index c7c42e7acc31..5d4f8e586e32 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -307,6 +307,12 @@ static inline int nf_ct_is_untracked(const struct nf_conn *ct) return test_bit(IPS_UNTRACKED_BIT, &ct->status); } +/* Packet is received from loopback */ +static inline bool nf_is_loopback_packet(const struct sk_buff *skb) +{ + return skb->dev && skb->skb_iif && skb->dev->flags & IFF_LOOPBACK; +} + extern int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp); extern unsigned int nf_conntrack_htable_size; extern unsigned int nf_conntrack_max; diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index db10075dd88e..de9da21113a1 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -121,7 +121,9 @@ static unsigned int ipv4_confirm(unsigned int hooknum, return ret; } - if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { + /* adjust seqs for loopback traffic only in outgoing direction */ + if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) && + !nf_is_loopback_packet(skb)) { typeof(nf_nat_seq_adjust_hook) seq_adjust; seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook); From 5e7f23373bf9a853e9256e81e86724cdd0a33c29 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 13 Jun 2011 22:31:12 +0100 Subject: [PATCH 488/595] afs: afs_fill_page reads too much, or wrong data afs_fill_page should read the page that is about to be written but the current implementation has a number of issues. If we aren't extending the file we always read PAGE_CACHE_SIZE at offset 0. If we are extending the file we try to read the entire file. Change afs_fill_page to read PAGE_CACHE_SIZE at the right offset, clamped to i_size. While here, avoid calling afs_fill_page when we are doing a PAGE_CACHE_SIZE write. Signed-off-by: Anton Blanchard Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/afs/write.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/fs/afs/write.c b/fs/afs/write.c index 789b3afb3423..b806285ff853 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -84,23 +84,21 @@ void afs_put_writeback(struct afs_writeback *wb) * partly or wholly fill a page that's under preparation for writing */ static int afs_fill_page(struct afs_vnode *vnode, struct key *key, - loff_t pos, unsigned len, struct page *page) + loff_t pos, struct page *page) { loff_t i_size; - unsigned eof; int ret; + int len; - _enter(",,%llu,%u", (unsigned long long)pos, len); - - ASSERTCMP(len, <=, PAGE_CACHE_SIZE); + _enter(",,%llu", (unsigned long long)pos); i_size = i_size_read(&vnode->vfs_inode); - if (pos + len > i_size) - eof = i_size; + if (pos + PAGE_CACHE_SIZE > i_size) + len = i_size - pos; else - eof = PAGE_CACHE_SIZE; + len = PAGE_CACHE_SIZE; - ret = afs_vnode_fetch_data(vnode, key, 0, eof, page); + ret = afs_vnode_fetch_data(vnode, key, pos, len, page); if (ret < 0) { if (ret == -ENOENT) { _debug("got NOENT from server" @@ -153,9 +151,8 @@ int afs_write_begin(struct file *file, struct address_space *mapping, *pagep = page; /* page won't leak in error case: it eventually gets cleaned off LRU */ - if (!PageUptodate(page)) { - _debug("not up to date"); - ret = afs_fill_page(vnode, key, pos, len, page); + if (!PageUptodate(page) && len != PAGE_CACHE_SIZE) { + ret = afs_fill_page(vnode, key, index << PAGE_CACHE_SHIFT, page); if (ret < 0) { kfree(candidate); _leave(" = %d [prep]", ret); From f9f07b6c1372b1436aa6b45333445b443ffd8c95 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 14 Jun 2011 00:58:27 +0200 Subject: [PATCH 489/595] vfs: Fix data corruption after failed write in __block_write_begin() I've got a report of a file corruption from fsxlinux on ext3. The important operations to the page were: mapwrite to a hole partial write to the page read - found the page zeroed from the end of the normal write The culprit seems to be that if get_block() fails in __block_write_begin() (e.g. transient ENOSPC in ext3), the function does ClearPageUptodate(page). Thus when we retry the write, the logic in __block_write_begin() thinks zeroing of the page is needed and overwrites old data. In fact, I don't see why we should ever need to zero the uptodate bit here - either the page was uptodate when we entered __block_write_begin() and it should stay so when we leave it, or it was not uptodate and noone had right to set it uptodate during __block_write_begin() so it remains !uptodate when we leave as well. So just remove clearing of the bit. Signed-off-by: Jan Kara Signed-off-by: Al Viro --- fs/buffer.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 49c9aada0374..1a80b048ade8 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1902,10 +1902,8 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len, if (!buffer_uptodate(*wait_bh)) err = -EIO; } - if (unlikely(err)) { + if (unlikely(err)) page_zero_new_buffers(page, from, to); - ClearPageUptodate(page); - } return err; } EXPORT_SYMBOL(__block_write_begin); From 2e41ae225f742ded5b7d9847cd8bd605f27daba8 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 14 Jun 2011 00:38:44 +0100 Subject: [PATCH 490/595] AFS: Set s_id in the superblock to the volume name Set s_id in the superblock to the name of the AFS volume that this superblock corresponds to. Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/afs/super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/afs/super.c b/fs/afs/super.c index b7d48d7eaa1e..356dcf0929e8 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -313,6 +313,7 @@ static int afs_fill_super(struct super_block *sb, sb->s_magic = AFS_FS_MAGIC; sb->s_op = &afs_super_ops; sb->s_bdi = &as->volume->bdi; + strlcpy(sb->s_id, as->volume->vlocation->vldb.name, sizeof(sb->s_id)); /* allocate the root inode and dentry */ fid.vid = as->volume->vid; From d6e43f751f252c68ca69fa6d18665d88d69ef8b7 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 14 Jun 2011 00:45:44 +0100 Subject: [PATCH 491/595] AFS: Use i_generation not i_version for the vnode uniquifier Store the AFS vnode uniquifier in the i_generation field, not the i_version field of the inode struct. i_version can then be given the AFS data version number. Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/afs/dir.c | 8 ++++---- fs/afs/fsclient.c | 3 ++- fs/afs/inode.c | 10 +++++----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 20c106f24927..1b0b19550015 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -584,11 +584,11 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, success: d_add(dentry, inode); - _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%llu }", + _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%u }", fid.vnode, fid.unique, dentry->d_inode->i_ino, - (unsigned long long)dentry->d_inode->i_version); + dentry->d_inode->i_generation); return NULL; } @@ -671,10 +671,10 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) * been deleted and replaced, and the original vnode ID has * been reused */ if (fid.unique != vnode->fid.unique) { - _debug("%s: file deleted (uq %u -> %u I:%llu)", + _debug("%s: file deleted (uq %u -> %u I:%u)", dentry->d_name.name, fid.unique, vnode->fid.unique, - (unsigned long long)dentry->d_inode->i_version); + dentry->d_inode->i_generation); spin_lock(&vnode->lock); set_bit(AFS_VNODE_DELETED, &vnode->flags); spin_unlock(&vnode->lock); diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 4bd0218473a9..346e3289abd7 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c @@ -89,7 +89,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, i_size_write(&vnode->vfs_inode, size); vnode->vfs_inode.i_uid = status->owner; vnode->vfs_inode.i_gid = status->group; - vnode->vfs_inode.i_version = vnode->fid.unique; + vnode->vfs_inode.i_generation = vnode->fid.unique; vnode->vfs_inode.i_nlink = status->nlink; mode = vnode->vfs_inode.i_mode; @@ -102,6 +102,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, vnode->vfs_inode.i_ctime.tv_sec = status->mtime_server; vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime; vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime; + vnode->vfs_inode.i_version = data_version; } expected_version = status->data_version; diff --git a/fs/afs/inode.c b/fs/afs/inode.c index db66c5201474..0fdab6e03d87 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -75,7 +75,8 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key) inode->i_ctime.tv_nsec = 0; inode->i_atime = inode->i_mtime = inode->i_ctime; inode->i_blocks = 0; - inode->i_version = vnode->fid.unique; + inode->i_generation = vnode->fid.unique; + inode->i_version = vnode->status.data_version; inode->i_mapping->a_ops = &afs_fs_aops; /* check to see whether a symbolic link is really a mountpoint */ @@ -100,7 +101,7 @@ static int afs_iget5_test(struct inode *inode, void *opaque) struct afs_iget_data *data = opaque; return inode->i_ino == data->fid.vnode && - inode->i_version == data->fid.unique; + inode->i_generation == data->fid.unique; } /* @@ -122,7 +123,7 @@ static int afs_iget5_set(struct inode *inode, void *opaque) struct afs_vnode *vnode = AFS_FS_I(inode); inode->i_ino = data->fid.vnode; - inode->i_version = data->fid.unique; + inode->i_generation = data->fid.unique; vnode->fid = data->fid; vnode->volume = data->volume; @@ -380,8 +381,7 @@ int afs_getattr(struct vfsmount *mnt, struct dentry *dentry, inode = dentry->d_inode; - _enter("{ ino=%lu v=%llu }", inode->i_ino, - (unsigned long long)inode->i_version); + _enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation); generic_fillattr(inode, stat); return 0; From a27a263bae072a499acc77b632238a6dacccf888 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 16 Jun 2011 12:02:23 +0000 Subject: [PATCH 492/595] xfs: make log devices with write back caches work There's no reason not to support cache flushing on external log devices. The only thing this really requires is flushing the data device first both in fsync and log commits. A side effect is that we also have to remove the barrier write test during mount, which has been superflous since the new FLUSH+FUA code anyway. Also use the chance to flush the RT subvolume write cache before the fsync commit, which is required for correct semantics. Signed-off-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/linux-2.6/xfs_file.c | 50 +++++++++++++++--------- fs/xfs/linux-2.6/xfs_super.c | 75 ------------------------------------ fs/xfs/xfs_log.c | 11 +++++- 3 files changed, 41 insertions(+), 95 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index f4213ba1ff85..7f782af286bf 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -131,19 +131,34 @@ xfs_file_fsync( { struct inode *inode = file->f_mapping->host; struct xfs_inode *ip = XFS_I(inode); + struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; int error = 0; int log_flushed = 0; trace_xfs_file_fsync(ip); - if (XFS_FORCED_SHUTDOWN(ip->i_mount)) + if (XFS_FORCED_SHUTDOWN(mp)) return -XFS_ERROR(EIO); xfs_iflags_clear(ip, XFS_ITRUNCATED); xfs_ioend_wait(ip); + if (mp->m_flags & XFS_MOUNT_BARRIER) { + /* + * If we have an RT and/or log subvolume we need to make sure + * to flush the write cache the device used for file data + * first. This is to ensure newly written file data make + * it to disk before logging the new inode size in case of + * an extending write. + */ + if (XFS_IS_REALTIME_INODE(ip)) + xfs_blkdev_issue_flush(mp->m_rtdev_targp); + else if (mp->m_logdev_targp != mp->m_ddev_targp) + xfs_blkdev_issue_flush(mp->m_ddev_targp); + } + /* * We always need to make sure that the required inode state is safe on * disk. The inode might be clean but we still might need to force the @@ -175,9 +190,9 @@ xfs_file_fsync( * updates. The sync transaction will also force the log. */ xfs_iunlock(ip, XFS_ILOCK_SHARED); - tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS); + tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); error = xfs_trans_reserve(tp, 0, - XFS_FSYNC_TS_LOG_RES(ip->i_mount), 0, 0, 0); + XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); if (error) { xfs_trans_cancel(tp, 0); return -error; @@ -209,28 +224,25 @@ xfs_file_fsync( * force the log. */ if (xfs_ipincount(ip)) { - error = _xfs_log_force_lsn(ip->i_mount, + error = _xfs_log_force_lsn(mp, ip->i_itemp->ili_last_lsn, XFS_LOG_SYNC, &log_flushed); } xfs_iunlock(ip, XFS_ILOCK_SHARED); } - if (ip->i_mount->m_flags & XFS_MOUNT_BARRIER) { - /* - * If the log write didn't issue an ordered tag we need - * to flush the disk cache for the data device now. - */ - if (!log_flushed) - xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp); - - /* - * If this inode is on the RT dev we need to flush that - * cache as well. - */ - if (XFS_IS_REALTIME_INODE(ip)) - xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp); - } + /* + * If we only have a single device, and the log force about was + * a no-op we might have to flush the data device cache here. + * This can only happen for fdatasync/O_DSYNC if we were overwriting + * an already allocated file and thus do not have any metadata to + * commit. + */ + if ((mp->m_flags & XFS_MOUNT_BARRIER) && + mp->m_logdev_targp == mp->m_ddev_targp && + !XFS_IS_REALTIME_INODE(ip) && + !log_flushed) + xfs_blkdev_issue_flush(mp->m_ddev_targp); return -error; } diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 1e3a7ce804dc..a1a881e68a9a 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -627,68 +627,6 @@ xfs_blkdev_put( blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); } -/* - * Try to write out the superblock using barriers. - */ -STATIC int -xfs_barrier_test( - xfs_mount_t *mp) -{ - xfs_buf_t *sbp = xfs_getsb(mp, 0); - int error; - - XFS_BUF_UNDONE(sbp); - XFS_BUF_UNREAD(sbp); - XFS_BUF_UNDELAYWRITE(sbp); - XFS_BUF_WRITE(sbp); - XFS_BUF_UNASYNC(sbp); - XFS_BUF_ORDERED(sbp); - - xfsbdstrat(mp, sbp); - error = xfs_buf_iowait(sbp); - - /* - * Clear all the flags we set and possible error state in the - * buffer. We only did the write to try out whether barriers - * worked and shouldn't leave any traces in the superblock - * buffer. - */ - XFS_BUF_DONE(sbp); - XFS_BUF_ERROR(sbp, 0); - XFS_BUF_UNORDERED(sbp); - - xfs_buf_relse(sbp); - return error; -} - -STATIC void -xfs_mountfs_check_barriers(xfs_mount_t *mp) -{ - int error; - - if (mp->m_logdev_targp != mp->m_ddev_targp) { - xfs_notice(mp, - "Disabling barriers, not supported with external log device"); - mp->m_flags &= ~XFS_MOUNT_BARRIER; - return; - } - - if (xfs_readonly_buftarg(mp->m_ddev_targp)) { - xfs_notice(mp, - "Disabling barriers, underlying device is readonly"); - mp->m_flags &= ~XFS_MOUNT_BARRIER; - return; - } - - error = xfs_barrier_test(mp); - if (error) { - xfs_notice(mp, - "Disabling barriers, trial barrier write failed"); - mp->m_flags &= ~XFS_MOUNT_BARRIER; - return; - } -} - void xfs_blkdev_issue_flush( xfs_buftarg_t *buftarg) @@ -1240,14 +1178,6 @@ xfs_fs_remount( switch (token) { case Opt_barrier: mp->m_flags |= XFS_MOUNT_BARRIER; - - /* - * Test if barriers are actually working if we can, - * else delay this check until the filesystem is - * marked writeable. - */ - if (!(mp->m_flags & XFS_MOUNT_RDONLY)) - xfs_mountfs_check_barriers(mp); break; case Opt_nobarrier: mp->m_flags &= ~XFS_MOUNT_BARRIER; @@ -1282,8 +1212,6 @@ xfs_fs_remount( /* ro -> rw */ if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) { mp->m_flags &= ~XFS_MOUNT_RDONLY; - if (mp->m_flags & XFS_MOUNT_BARRIER) - xfs_mountfs_check_barriers(mp); /* * If this is the first remount to writeable state we @@ -1465,9 +1393,6 @@ xfs_fs_fill_super( if (error) goto out_free_sb; - if (mp->m_flags & XFS_MOUNT_BARRIER) - xfs_mountfs_check_barriers(mp); - error = xfs_filestream_mount(mp); if (error) goto out_free_sb; diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 211930246f20..41d5b8f2bf92 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -1372,8 +1372,17 @@ xlog_sync(xlog_t *log, XFS_BUF_ASYNC(bp); bp->b_flags |= XBF_LOG_BUFFER; - if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) + if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) { + /* + * If we have an external log device, flush the data device + * before flushing the log to make sure all meta data + * written back from the AIL actually made it to disk + * before writing out the new log tail LSN in the log buffer. + */ + if (log->l_mp->m_logdev_targp != log->l_mp->m_ddev_targp) + xfs_blkdev_issue_flush(log->l_mp->m_ddev_targp); XFS_BUF_ORDERED(bp); + } ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize); From b5199515c25cca622495eb9c6a8a1d275e775088 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 16 Jun 2011 16:22:08 +0200 Subject: [PATCH 493/595] clocksource: Make watchdog robust vs. interruption The clocksource watchdog code is interruptible and it has been observed that this can trigger false positives which disable the TSC. The reason is that an interrupt storm or a long running interrupt handler between the read of the watchdog source and the read of the TSC brings the two far enough apart that the delta is larger than the unstable treshold. Move both reads into a short interrupt disabled region to avoid that. Reported-and-tested-by: Vernon Mauery Signed-off-by: Thomas Gleixner Cc: stable@kernel.org --- include/linux/clocksource.h | 1 + kernel/time/clocksource.c | 24 +++++++++++++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index d4646b48dc4a..18a1baf31f2d 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -188,6 +188,7 @@ struct clocksource { #ifdef CONFIG_CLOCKSOURCE_WATCHDOG /* Watchdog related data, used by the framework */ struct list_head wd_list; + cycle_t cs_last; cycle_t wd_last; #endif } ____cacheline_aligned; diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 1c95fd677328..e0980f0d9a0a 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -185,7 +185,6 @@ static struct clocksource *watchdog; static struct timer_list watchdog_timer; static DECLARE_WORK(watchdog_work, clocksource_watchdog_work); static DEFINE_SPINLOCK(watchdog_lock); -static cycle_t watchdog_last; static int watchdog_running; static int clocksource_watchdog_kthread(void *data); @@ -254,11 +253,6 @@ static void clocksource_watchdog(unsigned long data) if (!watchdog_running) goto out; - wdnow = watchdog->read(watchdog); - wd_nsec = clocksource_cyc2ns((wdnow - watchdog_last) & watchdog->mask, - watchdog->mult, watchdog->shift); - watchdog_last = wdnow; - list_for_each_entry(cs, &watchdog_list, wd_list) { /* Clocksource already marked unstable? */ @@ -268,19 +262,28 @@ static void clocksource_watchdog(unsigned long data) continue; } + local_irq_disable(); csnow = cs->read(cs); + wdnow = watchdog->read(watchdog); + local_irq_enable(); /* Clocksource initialized ? */ if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) { cs->flags |= CLOCK_SOURCE_WATCHDOG; - cs->wd_last = csnow; + cs->wd_last = wdnow; + cs->cs_last = csnow; continue; } - /* Check the deviation from the watchdog clocksource. */ - cs_nsec = clocksource_cyc2ns((csnow - cs->wd_last) & + wd_nsec = clocksource_cyc2ns((wdnow - cs->wd_last) & watchdog->mask, + watchdog->mult, watchdog->shift); + + cs_nsec = clocksource_cyc2ns((csnow - cs->cs_last) & cs->mask, cs->mult, cs->shift); - cs->wd_last = csnow; + cs->cs_last = csnow; + cs->wd_last = wdnow; + + /* Check the deviation from the watchdog clocksource. */ if (abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) { clocksource_unstable(cs, cs_nsec - wd_nsec); continue; @@ -318,7 +321,6 @@ static inline void clocksource_start_watchdog(void) return; init_timer(&watchdog_timer); watchdog_timer.function = clocksource_watchdog; - watchdog_last = watchdog->read(watchdog); watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL; add_timer_on(&watchdog_timer, cpumask_first(cpu_online_mask)); watchdog_running = 1; From acd049c6e99d2ad1195666195230f6881d1c1588 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 16 Jun 2011 13:07:19 -0400 Subject: [PATCH 494/595] xen/setup: Fix for incorrect xen_extra_mem_start. The earlier attempts (24bdb0b62cc82120924762ae6bc85afc8c3f2b26) at fixing this problem caused other problems to surface (PV guests with no PCI passthrough would have SWIOTLB turned on - which meant 64MB of precious contingous DMA32 memory being eaten up per guest). The problem was: "on xen we add an extra memory region at the end of the e820, and on this particular machine this extra memory region would start below 4g and cross over the 4g boundary: [0xfee01000-0x192655000) Unfortunately e820_end_of_low_ram_pfn does not expect an e820 layout like that so it returns 4g, therefore initial_memory_mapping will map [0 - 0x100000000), that is a memory range that includes some reserved memory regions." The memory range was the IOAPIC regions, and with the 1-1 mapping turned on, it would map them as RAM, not as MMIO regions. This caused the hypervisor to complain. Fortunately this is experienced only under the initial domain so we guard for it. Acked-by: Stefano Stabellini Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/setup.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index be1a464f6d66..60aeeb56948f 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -227,11 +227,7 @@ char * __init xen_memory_setup(void) memcpy(map_raw, map, sizeof(map)); e820.nr_map = 0; -#ifdef CONFIG_X86_32 xen_extra_mem_start = mem_end; -#else - xen_extra_mem_start = max((1ULL << 32), mem_end); -#endif for (i = 0; i < memmap.nr_entries; i++) { unsigned long long end; @@ -266,6 +262,12 @@ char * __init xen_memory_setup(void) if (map[i].size > 0) e820_add_region(map[i].addr, map[i].size, map[i].type); } + /* Align the balloon area so that max_low_pfn does not get set + * to be at the _end_ of the PCI gap at the far end (fee01000). + * Note that xen_extra_mem_start gets set in the loop above to be + * past the last E820 region. */ + if (xen_initial_domain() && (xen_extra_mem_start < (1ULL<<32))) + xen_extra_mem_start = (1ULL<<32); /* * In domU, the ISA region is normal, usable memory, but we From 0ec5258d68c626922d92e2f0e4e5c689e5360a5d Mon Sep 17 00:00:00 2001 From: Torsten Schenk Date: Thu, 16 Jun 2011 21:06:27 +0200 Subject: [PATCH 495/595] ALSA: 6fire - Fix signedness bug Fixed remaining issues of the signedness bug discovered by Dan Carpenter. A check was remaining that tests if unsigned rt->rate is >= 0. Changed that so that rt->rate now consistently uses ARRAY_SIZE(rates) as invalid rate value and not -1. Signed-off-by: Torsten Schenk Signed-off-by: Takashi Iwai --- sound/usb/6fire/pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index b137b25865cc..d144cdb2f159 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c @@ -395,12 +395,12 @@ static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub) alsa_rt->hw = pcm_hw; if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (rt->rate >= 0) + if (rt->rate < ARRAY_SIZE(rates)) alsa_rt->hw.rates = rates_alsaid[rt->rate]; alsa_rt->hw.channels_max = OUT_N_CHANNELS; sub = &rt->playback; } else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) { - if (rt->rate >= 0) + if (rt->rate < ARRAY_SIZE(rates)) alsa_rt->hw.rates = rates_alsaid[rt->rate]; alsa_rt->hw.channels_max = IN_N_CHANNELS; sub = &rt->capture; From 46a310b80bc2c9ccc019649c9da91194cbc10944 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 16 Jun 2011 15:36:38 -0400 Subject: [PATCH 496/595] [CPUFREQ] Don't set stat->last_index to -1 if the pol->cur has incorrect value. If the driver submitted an non-existing pol>cur value (say it used the default initialized value of zero), when the cpufreq stats tries to setup its initial values it incorrectly sets stat->last_index to -1 (or 0xfffff...). And cpufreq_stats_update tries to update at that index location and fails. This can be caused by: stat->last_index = freq_table_get_index(stat, policy->cur); not finding the appropiate frequency in the table (b/c the policy->cur is wrong) and we end up crashing. The fix however is concentrated in the 'cpufreq_stats_update' as the last_index (and old_index) are updated there. Which means it can reset the last_index to -1 again and on the next iteration cause a crash. Without this patch, the following crash is observed: powernow-k8: Found 1 AMD Athlon(tm) 64 Processor 3700+ (1 cpu cores) (version 2.20.00) powernow-k8: fid 0x2 (1000 MHz), vid 0x12 powernow-k8: fid 0xa (1800 MHz), vid 0xa powernow-k8: fid 0xc (2000 MHz), vid 0x8 powernow-k8: fid 0xe (2200 MHz), vid 0x8 Marking TSC unstable due to cpufreq changes powernow-k8: fid trans failed, fid 0x2, curr 0x0 BUG: unable to handle kernel paging request at ffff880807e07b78 IP: [] cpufreq_stats_update+0x46/0x5b .. snip.. Pid: 1, comm: swapper Not tainted 3.0.0-rc2 #45 MICRO-STAR INTERNATIONAL CO., LTD MS-7094/MS-7094 ..snip.. Call Trace: [] cpufreq_stat_notifier_trans+0x48/0x7c [] notifier_call_chain+0x32/0x5e [] __srcu_notifier_call_chain+0x47/0x63 [] srcu_notifier_call_chain+0xf/0x11 [] cpufreq_notify_transition+0x111/0x134 [] powernowk8_target+0x53b/0x617 [] __cpufreq_driver_target+0x2e/0x30 [] cpufreq_governor_dbs+0x339/0x356 [] __cpufreq_governor+0xa8/0xe9 [] __cpufreq_set_policy+0x132/0x13e [] cpufreq_add_dev_interface+0x272/0x28c Reported-by: Tobias Diedrich Tested-by: Tobias Diedrich Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_stats.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 853f92d23ddb..faf7c5217848 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -298,11 +298,13 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb, old_index = stat->last_index; new_index = freq_table_get_index(stat, freq->new); - cpufreq_stats_update(freq->cpu); - if (old_index == new_index) + /* We can't do stat->time_in_state[-1]= .. */ + if (old_index == -1 || new_index == -1) return 0; - if (old_index == -1 || new_index == -1) + cpufreq_stats_update(freq->cpu); + + if (old_index == new_index) return 0; spin_lock(&cpufreq_stats_lock); From a9d3d2068064b7a6395871a49616d3784f802d50 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 16 Jun 2011 15:36:39 -0400 Subject: [PATCH 497/595] [CPUFREQ] powernow-k8: Don't notify of successful transition if we failed (vid case). Before this patch if we failed the vid transition would still try to submit the "new" frequencies to cpufreq. That is incorrect - also we could submit a non-existing frequency value which would cause cpufreq to crash. The ultimate fix is in cpufreq to deal with incorrect values, but this patch improves the error recovery in the AMD powernowk8 driver. The failure that was reported was as follows: powernow-k8: Found 1 AMD Athlon(tm) 64 Processor 3700+ (1 cpu cores) (version 2.20.00) powernow-k8: fid 0x2 (1000 MHz), vid 0x12 powernow-k8: fid 0xa (1800 MHz), vid 0xa powernow-k8: fid 0xc (2000 MHz), vid 0x8 powernow-k8: fid 0xe (2200 MHz), vid 0x8 Marking TSC unstable due to cpufreq changes powernow-k8: fid trans failed, fid 0x2, curr 0x0 BUG: unable to handle kernel paging request at ffff880807e07b78 IP: [] cpufreq_stats_update+0x46/0x5b ... And transition fails and data->currfid ends up with 0. Since the machine does not support 800Mhz value when the calculation is done ('find_khz_freq_from_fid(data->currfid);') it reports the new frequency as 800000 which is bogus. This patch fixes the issue during target setting. The patch however does not fix the issue in 'powernowk8_cpu_init' where the pol->cur can also be set with the 800000 value: pol->cur = find_khz_freq_from_fid(data->currfid); dprintk("policy current frequency %d kHz\n", pol->cur); /* min/max the cpu is capable of */ if (cpufreq_frequency_table_cpuinfo(pol, data->powernow_table)) { The fix for that looks to update cpufreq_frequency_table_cpuinfo to check pol->cur.... but that would cause an regression in how the acpi-cpufreq driver works (it sets cpu->cur after calling cpufreq_frequency_table_cpuinfo). Instead the fix will be to let cpufreq gracefully handle bogus data (another patch). Acked-by: Borislav Petkov CC: andre.przywara@amd.com CC: Mark.Langsdorf@amd.com Reported-by: Tobias Diedrich Tested-by: Tobias Diedrich [v1: Rebased on v3.0-rc2, reduced patch to deal with vid case] Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Dave Jones --- drivers/cpufreq/powernow-k8.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 83479b6fb9a1..287c56f6749a 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1079,6 +1079,9 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, } res = transition_fid_vid(data, fid, vid); + if (res) + return res; + freqs.new = find_khz_freq_from_fid(data->currfid); for_each_cpu(i, data->available_cores) { From fbb5b89eabea5ae7d621b7861863159560d8faa4 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 16 Jun 2011 15:36:40 -0400 Subject: [PATCH 498/595] [CPUFREQ] powernow-k8: Don't try to transition if the pstate is incorrect This patch augments the pstate transition code to error out (instead of returning 0) when an incorrect pstate is provided. Suggested-by: Borislav Petkov CC: andre.przywara@amd.com CC: Mark.Langsdorf@amd.com Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Dave Jones --- drivers/cpufreq/powernow-k8.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 287c56f6749a..bce576d7478e 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1104,7 +1104,8 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, /* get MSR index for hardware pstate transition */ pstate = index & HW_PSTATE_MASK; if (pstate > data->max_hw_pstate) - return 0; + return -EINVAL; + freqs.old = find_khz_freq_from_pstate(data->powernow_table, data->currpstate); freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate); From 99a15e21d96f6857dafab1e5167e5e8183215c9c Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Thu, 16 Jun 2011 12:56:19 -0700 Subject: [PATCH 499/595] migrate: don't account swapcache as shmem swapcache will reach the below code path in migrate_page_move_mapping, and swapcache is accounted as NR_FILE_PAGES but it's not accounted as NR_SHMEM. Hugh pointed out we must use PageSwapCache instead of comparing mapping to &swapper_space, to avoid build failure with CONFIG_SWAP=n. Signed-off-by: Andrea Arcangeli Acked-by: Hugh Dickins Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- mm/migrate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/migrate.c b/mm/migrate.c index e4a5c912983d..666e4e677414 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -288,7 +288,7 @@ static int migrate_page_move_mapping(struct address_space *mapping, */ __dec_zone_page_state(page, NR_FILE_PAGES); __inc_zone_page_state(newpage, NR_FILE_PAGES); - if (PageSwapBacked(page)) { + if (!PageSwapCache(page) && PageSwapBacked(page)) { __dec_zone_page_state(page, NR_SHMEM); __inc_zone_page_state(newpage, NR_SHMEM); } From f8b7fc6b514f34a51875dd48dff70d4d17a54f38 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 16 Jun 2011 08:26:32 -0700 Subject: [PATCH 500/595] rcu: Move RCU_BOOST #ifdefs to header file The commit "use softirq instead of kthreads except when RCU_BOOST=y" just applied #ifdef in place. This commit is a cleanup that moves the newly #ifdef'ed code to the header file kernel/rcutree_plugin.h. Signed-off-by: Paul E. McKenney Signed-off-by: Paul E. McKenney --- kernel/rcutree.c | 383 +-------------------------------------- kernel/rcutree.h | 5 + kernel/rcutree_plugin.h | 384 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 390 insertions(+), 382 deletions(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 429d4949f0eb..7e59ffb3d0ba 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1093,16 +1093,8 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp) int need_report = 0; struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu); struct rcu_node *rnp; -#ifdef CONFIG_RCU_BOOST - struct task_struct *t; - /* Stop the CPU's kthread. */ - t = per_cpu(rcu_cpu_kthread_task, cpu); - if (t != NULL) { - per_cpu(rcu_cpu_kthread_task, cpu) = NULL; - kthread_stop(t); - } -#endif /* #ifdef CONFIG_RCU_BOOST */ + rcu_stop_cpu_kthread(cpu); /* Exclude any attempts to start a new grace period. */ raw_spin_lock_irqsave(&rsp->onofflock, flags); @@ -1453,17 +1445,6 @@ __rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp) invoke_rcu_callbacks(rsp, rdp); } -#ifdef CONFIG_RCU_BOOST - -static void rcu_kthread_do_work(void) -{ - rcu_do_batch(&rcu_sched_state, &__get_cpu_var(rcu_sched_data)); - rcu_do_batch(&rcu_bh_state, &__get_cpu_var(rcu_bh_data)); - rcu_preempt_do_callbacks(); -} - -#endif /* #ifdef CONFIG_RCU_BOOST */ - /* * Do softirq processing for the current CPU. */ @@ -1498,345 +1479,6 @@ static void invoke_rcu_core(void) raise_softirq(RCU_SOFTIRQ); } -#ifdef CONFIG_RCU_BOOST - -/* - * Wake up the specified per-rcu_node-structure kthread. - * Because the per-rcu_node kthreads are immortal, we don't need - * to do anything to keep them alive. - */ -static void invoke_rcu_node_kthread(struct rcu_node *rnp) -{ - struct task_struct *t; - - t = rnp->node_kthread_task; - if (t != NULL) - wake_up_process(t); -} - -/* - * Set the specified CPU's kthread to run RT or not, as specified by - * the to_rt argument. The CPU-hotplug locks are held, so the task - * is not going away. - */ -static void rcu_cpu_kthread_setrt(int cpu, int to_rt) -{ - int policy; - struct sched_param sp; - struct task_struct *t; - - t = per_cpu(rcu_cpu_kthread_task, cpu); - if (t == NULL) - return; - if (to_rt) { - policy = SCHED_FIFO; - sp.sched_priority = RCU_KTHREAD_PRIO; - } else { - policy = SCHED_NORMAL; - sp.sched_priority = 0; - } - sched_setscheduler_nocheck(t, policy, &sp); -} - -/* - * Timer handler to initiate the waking up of per-CPU kthreads that - * have yielded the CPU due to excess numbers of RCU callbacks. - * We wake up the per-rcu_node kthread, which in turn will wake up - * the booster kthread. - */ -static void rcu_cpu_kthread_timer(unsigned long arg) -{ - struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, arg); - struct rcu_node *rnp = rdp->mynode; - - atomic_or(rdp->grpmask, &rnp->wakemask); - invoke_rcu_node_kthread(rnp); -} - -/* - * Drop to non-real-time priority and yield, but only after posting a - * timer that will cause us to regain our real-time priority if we - * remain preempted. Either way, we restore our real-time priority - * before returning. - */ -static void rcu_yield(void (*f)(unsigned long), unsigned long arg) -{ - struct sched_param sp; - struct timer_list yield_timer; - - setup_timer_on_stack(&yield_timer, f, arg); - mod_timer(&yield_timer, jiffies + 2); - sp.sched_priority = 0; - sched_setscheduler_nocheck(current, SCHED_NORMAL, &sp); - set_user_nice(current, 19); - schedule(); - sp.sched_priority = RCU_KTHREAD_PRIO; - sched_setscheduler_nocheck(current, SCHED_FIFO, &sp); - del_timer(&yield_timer); -} - -/* - * Handle cases where the rcu_cpu_kthread() ends up on the wrong CPU. - * This can happen while the corresponding CPU is either coming online - * or going offline. We cannot wait until the CPU is fully online - * before starting the kthread, because the various notifier functions - * can wait for RCU grace periods. So we park rcu_cpu_kthread() until - * the corresponding CPU is online. - * - * Return 1 if the kthread needs to stop, 0 otherwise. - * - * Caller must disable bh. This function can momentarily enable it. - */ -static int rcu_cpu_kthread_should_stop(int cpu) -{ - while (cpu_is_offline(cpu) || - !cpumask_equal(¤t->cpus_allowed, cpumask_of(cpu)) || - smp_processor_id() != cpu) { - if (kthread_should_stop()) - return 1; - per_cpu(rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU; - per_cpu(rcu_cpu_kthread_cpu, cpu) = raw_smp_processor_id(); - local_bh_enable(); - schedule_timeout_uninterruptible(1); - if (!cpumask_equal(¤t->cpus_allowed, cpumask_of(cpu))) - set_cpus_allowed_ptr(current, cpumask_of(cpu)); - local_bh_disable(); - } - per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu; - return 0; -} - -/* - * Per-CPU kernel thread that invokes RCU callbacks. This replaces the - * earlier RCU softirq. - */ -static int rcu_cpu_kthread(void *arg) -{ - int cpu = (int)(long)arg; - unsigned long flags; - int spincnt = 0; - unsigned int *statusp = &per_cpu(rcu_cpu_kthread_status, cpu); - char work; - char *workp = &per_cpu(rcu_cpu_has_work, cpu); - - for (;;) { - *statusp = RCU_KTHREAD_WAITING; - rcu_wait(*workp != 0 || kthread_should_stop()); - local_bh_disable(); - if (rcu_cpu_kthread_should_stop(cpu)) { - local_bh_enable(); - break; - } - *statusp = RCU_KTHREAD_RUNNING; - per_cpu(rcu_cpu_kthread_loops, cpu)++; - local_irq_save(flags); - work = *workp; - *workp = 0; - local_irq_restore(flags); - if (work) - rcu_kthread_do_work(); - local_bh_enable(); - if (*workp != 0) - spincnt++; - else - spincnt = 0; - if (spincnt > 10) { - *statusp = RCU_KTHREAD_YIELDING; - rcu_yield(rcu_cpu_kthread_timer, (unsigned long)cpu); - spincnt = 0; - } - } - *statusp = RCU_KTHREAD_STOPPED; - return 0; -} - -/* - * Spawn a per-CPU kthread, setting up affinity and priority. - * Because the CPU hotplug lock is held, no other CPU will be attempting - * to manipulate rcu_cpu_kthread_task. There might be another CPU - * attempting to access it during boot, but the locking in kthread_bind() - * will enforce sufficient ordering. - * - * Please note that we cannot simply refuse to wake up the per-CPU - * kthread because kthreads are created in TASK_UNINTERRUPTIBLE state, - * which can result in softlockup complaints if the task ends up being - * idle for more than a couple of minutes. - * - * However, please note also that we cannot bind the per-CPU kthread to its - * CPU until that CPU is fully online. We also cannot wait until the - * CPU is fully online before we create its per-CPU kthread, as this would - * deadlock the system when CPU notifiers tried waiting for grace - * periods. So we bind the per-CPU kthread to its CPU only if the CPU - * is online. If its CPU is not yet fully online, then the code in - * rcu_cpu_kthread() will wait until it is fully online, and then do - * the binding. - */ -static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu) -{ - struct sched_param sp; - struct task_struct *t; - - if (!rcu_kthreads_spawnable || - per_cpu(rcu_cpu_kthread_task, cpu) != NULL) - return 0; - t = kthread_create(rcu_cpu_kthread, (void *)(long)cpu, "rcuc%d", cpu); - if (IS_ERR(t)) - return PTR_ERR(t); - if (cpu_online(cpu)) - kthread_bind(t, cpu); - per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu; - WARN_ON_ONCE(per_cpu(rcu_cpu_kthread_task, cpu) != NULL); - sp.sched_priority = RCU_KTHREAD_PRIO; - sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); - per_cpu(rcu_cpu_kthread_task, cpu) = t; - wake_up_process(t); /* Get to TASK_INTERRUPTIBLE quickly. */ - return 0; -} - -/* - * Per-rcu_node kthread, which is in charge of waking up the per-CPU - * kthreads when needed. We ignore requests to wake up kthreads - * for offline CPUs, which is OK because force_quiescent_state() - * takes care of this case. - */ -static int rcu_node_kthread(void *arg) -{ - int cpu; - unsigned long flags; - unsigned long mask; - struct rcu_node *rnp = (struct rcu_node *)arg; - struct sched_param sp; - struct task_struct *t; - - for (;;) { - rnp->node_kthread_status = RCU_KTHREAD_WAITING; - rcu_wait(atomic_read(&rnp->wakemask) != 0); - rnp->node_kthread_status = RCU_KTHREAD_RUNNING; - raw_spin_lock_irqsave(&rnp->lock, flags); - mask = atomic_xchg(&rnp->wakemask, 0); - rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */ - for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) { - if ((mask & 0x1) == 0) - continue; - preempt_disable(); - t = per_cpu(rcu_cpu_kthread_task, cpu); - if (!cpu_online(cpu) || t == NULL) { - preempt_enable(); - continue; - } - per_cpu(rcu_cpu_has_work, cpu) = 1; - sp.sched_priority = RCU_KTHREAD_PRIO; - sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); - preempt_enable(); - } - } - /* NOTREACHED */ - rnp->node_kthread_status = RCU_KTHREAD_STOPPED; - return 0; -} - -/* - * Set the per-rcu_node kthread's affinity to cover all CPUs that are - * served by the rcu_node in question. The CPU hotplug lock is still - * held, so the value of rnp->qsmaskinit will be stable. - * - * We don't include outgoingcpu in the affinity set, use -1 if there is - * no outgoing CPU. If there are no CPUs left in the affinity set, - * this function allows the kthread to execute on any CPU. - */ -static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) -{ - cpumask_var_t cm; - int cpu; - unsigned long mask = rnp->qsmaskinit; - - if (rnp->node_kthread_task == NULL) - return; - if (!alloc_cpumask_var(&cm, GFP_KERNEL)) - return; - cpumask_clear(cm); - for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) - if ((mask & 0x1) && cpu != outgoingcpu) - cpumask_set_cpu(cpu, cm); - if (cpumask_weight(cm) == 0) { - cpumask_setall(cm); - for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++) - cpumask_clear_cpu(cpu, cm); - WARN_ON_ONCE(cpumask_weight(cm) == 0); - } - set_cpus_allowed_ptr(rnp->node_kthread_task, cm); - rcu_boost_kthread_setaffinity(rnp, cm); - free_cpumask_var(cm); -} - -/* - * Spawn a per-rcu_node kthread, setting priority and affinity. - * Called during boot before online/offline can happen, or, if - * during runtime, with the main CPU-hotplug locks held. So only - * one of these can be executing at a time. - */ -static int __cpuinit rcu_spawn_one_node_kthread(struct rcu_state *rsp, - struct rcu_node *rnp) -{ - unsigned long flags; - int rnp_index = rnp - &rsp->node[0]; - struct sched_param sp; - struct task_struct *t; - - if (!rcu_kthreads_spawnable || - rnp->qsmaskinit == 0) - return 0; - if (rnp->node_kthread_task == NULL) { - t = kthread_create(rcu_node_kthread, (void *)rnp, - "rcun%d", rnp_index); - if (IS_ERR(t)) - return PTR_ERR(t); - raw_spin_lock_irqsave(&rnp->lock, flags); - rnp->node_kthread_task = t; - raw_spin_unlock_irqrestore(&rnp->lock, flags); - sp.sched_priority = 99; - sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); - wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */ - } - return rcu_spawn_one_boost_kthread(rsp, rnp, rnp_index); -} - -/* - * Spawn all kthreads -- called as soon as the scheduler is running. - */ -static int __init rcu_spawn_kthreads(void) -{ - int cpu; - struct rcu_node *rnp; - - rcu_kthreads_spawnable = 1; - for_each_possible_cpu(cpu) { - per_cpu(rcu_cpu_has_work, cpu) = 0; - if (cpu_online(cpu)) - (void)rcu_spawn_one_cpu_kthread(cpu); - } - rnp = rcu_get_root(rcu_state); - (void)rcu_spawn_one_node_kthread(rcu_state, rnp); - if (NUM_RCU_NODES > 1) { - rcu_for_each_leaf_node(rcu_state, rnp) - (void)rcu_spawn_one_node_kthread(rcu_state, rnp); - } - return 0; -} -early_initcall(rcu_spawn_kthreads); - -#else /* #ifdef CONFIG_RCU_BOOST */ - -static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) -{ -} - -static void rcu_cpu_kthread_setrt(int cpu, int to_rt) -{ -} - -#endif /* #else #ifdef CONFIG_RCU_BOOST */ - static void __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu), struct rcu_state *rsp) @@ -2243,29 +1885,6 @@ static void __cpuinit rcu_prepare_cpu(int cpu) rcu_preempt_init_percpu_data(cpu); } -#ifdef CONFIG_RCU_BOOST - -static void __cpuinit rcu_prepare_kthreads(int cpu) -{ - struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu); - struct rcu_node *rnp = rdp->mynode; - - /* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */ - if (rcu_kthreads_spawnable) { - (void)rcu_spawn_one_cpu_kthread(cpu); - if (rnp->node_kthread_task == NULL) - (void)rcu_spawn_one_node_kthread(rcu_state, rnp); - } -} - -#else /* #ifdef CONFIG_RCU_BOOST */ - -static void __cpuinit rcu_prepare_kthreads(int cpu) -{ -} - -#endif /* #else #ifdef CONFIG_RCU_BOOST */ - /* * Handle CPU online/offline notification events. */ diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 434288c7ad88..01b2ccda26fb 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -427,6 +427,7 @@ static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp); #ifdef CONFIG_HOTPLUG_CPU static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags); +static void rcu_stop_cpu_kthread(int cpu); #endif /* #ifdef CONFIG_HOTPLUG_CPU */ static void rcu_print_detail_task_stall(struct rcu_state *rsp); static void rcu_print_task_stall(struct rcu_node *rnp); @@ -460,6 +461,10 @@ static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, struct rcu_node *rnp, int rnp_index); +static void invoke_rcu_node_kthread(struct rcu_node *rnp); +static void rcu_yield(void (*f)(unsigned long), unsigned long arg); #endif /* #ifdef CONFIG_RCU_BOOST */ +static void rcu_cpu_kthread_setrt(int cpu, int to_rt); +static void __cpuinit rcu_prepare_kthreads(int cpu); #endif /* #ifndef RCU_TREE_NONCORE */ diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 2772386c0421..14dc7dd00902 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -1330,6 +1330,370 @@ static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, return 0; } +#ifdef CONFIG_HOTPLUG_CPU + +/* + * Stop the RCU's per-CPU kthread when its CPU goes offline,. + */ +static void rcu_stop_cpu_kthread(int cpu) +{ + struct task_struct *t; + + /* Stop the CPU's kthread. */ + t = per_cpu(rcu_cpu_kthread_task, cpu); + if (t != NULL) { + per_cpu(rcu_cpu_kthread_task, cpu) = NULL; + kthread_stop(t); + } +} + +#endif /* #ifdef CONFIG_HOTPLUG_CPU */ + +static void rcu_kthread_do_work(void) +{ + rcu_do_batch(&rcu_sched_state, &__get_cpu_var(rcu_sched_data)); + rcu_do_batch(&rcu_bh_state, &__get_cpu_var(rcu_bh_data)); + rcu_preempt_do_callbacks(); +} + +/* + * Wake up the specified per-rcu_node-structure kthread. + * Because the per-rcu_node kthreads are immortal, we don't need + * to do anything to keep them alive. + */ +static void invoke_rcu_node_kthread(struct rcu_node *rnp) +{ + struct task_struct *t; + + t = rnp->node_kthread_task; + if (t != NULL) + wake_up_process(t); +} + +/* + * Set the specified CPU's kthread to run RT or not, as specified by + * the to_rt argument. The CPU-hotplug locks are held, so the task + * is not going away. + */ +static void rcu_cpu_kthread_setrt(int cpu, int to_rt) +{ + int policy; + struct sched_param sp; + struct task_struct *t; + + t = per_cpu(rcu_cpu_kthread_task, cpu); + if (t == NULL) + return; + if (to_rt) { + policy = SCHED_FIFO; + sp.sched_priority = RCU_KTHREAD_PRIO; + } else { + policy = SCHED_NORMAL; + sp.sched_priority = 0; + } + sched_setscheduler_nocheck(t, policy, &sp); +} + +/* + * Timer handler to initiate the waking up of per-CPU kthreads that + * have yielded the CPU due to excess numbers of RCU callbacks. + * We wake up the per-rcu_node kthread, which in turn will wake up + * the booster kthread. + */ +static void rcu_cpu_kthread_timer(unsigned long arg) +{ + struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, arg); + struct rcu_node *rnp = rdp->mynode; + + atomic_or(rdp->grpmask, &rnp->wakemask); + invoke_rcu_node_kthread(rnp); +} + +/* + * Drop to non-real-time priority and yield, but only after posting a + * timer that will cause us to regain our real-time priority if we + * remain preempted. Either way, we restore our real-time priority + * before returning. + */ +static void rcu_yield(void (*f)(unsigned long), unsigned long arg) +{ + struct sched_param sp; + struct timer_list yield_timer; + + setup_timer_on_stack(&yield_timer, f, arg); + mod_timer(&yield_timer, jiffies + 2); + sp.sched_priority = 0; + sched_setscheduler_nocheck(current, SCHED_NORMAL, &sp); + set_user_nice(current, 19); + schedule(); + sp.sched_priority = RCU_KTHREAD_PRIO; + sched_setscheduler_nocheck(current, SCHED_FIFO, &sp); + del_timer(&yield_timer); +} + +/* + * Handle cases where the rcu_cpu_kthread() ends up on the wrong CPU. + * This can happen while the corresponding CPU is either coming online + * or going offline. We cannot wait until the CPU is fully online + * before starting the kthread, because the various notifier functions + * can wait for RCU grace periods. So we park rcu_cpu_kthread() until + * the corresponding CPU is online. + * + * Return 1 if the kthread needs to stop, 0 otherwise. + * + * Caller must disable bh. This function can momentarily enable it. + */ +static int rcu_cpu_kthread_should_stop(int cpu) +{ + while (cpu_is_offline(cpu) || + !cpumask_equal(¤t->cpus_allowed, cpumask_of(cpu)) || + smp_processor_id() != cpu) { + if (kthread_should_stop()) + return 1; + per_cpu(rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU; + per_cpu(rcu_cpu_kthread_cpu, cpu) = raw_smp_processor_id(); + local_bh_enable(); + schedule_timeout_uninterruptible(1); + if (!cpumask_equal(¤t->cpus_allowed, cpumask_of(cpu))) + set_cpus_allowed_ptr(current, cpumask_of(cpu)); + local_bh_disable(); + } + per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu; + return 0; +} + +/* + * Per-CPU kernel thread that invokes RCU callbacks. This replaces the + * earlier RCU softirq. + */ +static int rcu_cpu_kthread(void *arg) +{ + int cpu = (int)(long)arg; + unsigned long flags; + int spincnt = 0; + unsigned int *statusp = &per_cpu(rcu_cpu_kthread_status, cpu); + char work; + char *workp = &per_cpu(rcu_cpu_has_work, cpu); + + for (;;) { + *statusp = RCU_KTHREAD_WAITING; + rcu_wait(*workp != 0 || kthread_should_stop()); + local_bh_disable(); + if (rcu_cpu_kthread_should_stop(cpu)) { + local_bh_enable(); + break; + } + *statusp = RCU_KTHREAD_RUNNING; + per_cpu(rcu_cpu_kthread_loops, cpu)++; + local_irq_save(flags); + work = *workp; + *workp = 0; + local_irq_restore(flags); + if (work) + rcu_kthread_do_work(); + local_bh_enable(); + if (*workp != 0) + spincnt++; + else + spincnt = 0; + if (spincnt > 10) { + *statusp = RCU_KTHREAD_YIELDING; + rcu_yield(rcu_cpu_kthread_timer, (unsigned long)cpu); + spincnt = 0; + } + } + *statusp = RCU_KTHREAD_STOPPED; + return 0; +} + +/* + * Spawn a per-CPU kthread, setting up affinity and priority. + * Because the CPU hotplug lock is held, no other CPU will be attempting + * to manipulate rcu_cpu_kthread_task. There might be another CPU + * attempting to access it during boot, but the locking in kthread_bind() + * will enforce sufficient ordering. + * + * Please note that we cannot simply refuse to wake up the per-CPU + * kthread because kthreads are created in TASK_UNINTERRUPTIBLE state, + * which can result in softlockup complaints if the task ends up being + * idle for more than a couple of minutes. + * + * However, please note also that we cannot bind the per-CPU kthread to its + * CPU until that CPU is fully online. We also cannot wait until the + * CPU is fully online before we create its per-CPU kthread, as this would + * deadlock the system when CPU notifiers tried waiting for grace + * periods. So we bind the per-CPU kthread to its CPU only if the CPU + * is online. If its CPU is not yet fully online, then the code in + * rcu_cpu_kthread() will wait until it is fully online, and then do + * the binding. + */ +static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu) +{ + struct sched_param sp; + struct task_struct *t; + + if (!rcu_kthreads_spawnable || + per_cpu(rcu_cpu_kthread_task, cpu) != NULL) + return 0; + t = kthread_create(rcu_cpu_kthread, (void *)(long)cpu, "rcuc%d", cpu); + if (IS_ERR(t)) + return PTR_ERR(t); + if (cpu_online(cpu)) + kthread_bind(t, cpu); + per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu; + WARN_ON_ONCE(per_cpu(rcu_cpu_kthread_task, cpu) != NULL); + sp.sched_priority = RCU_KTHREAD_PRIO; + sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + per_cpu(rcu_cpu_kthread_task, cpu) = t; + wake_up_process(t); /* Get to TASK_INTERRUPTIBLE quickly. */ + return 0; +} + +/* + * Per-rcu_node kthread, which is in charge of waking up the per-CPU + * kthreads when needed. We ignore requests to wake up kthreads + * for offline CPUs, which is OK because force_quiescent_state() + * takes care of this case. + */ +static int rcu_node_kthread(void *arg) +{ + int cpu; + unsigned long flags; + unsigned long mask; + struct rcu_node *rnp = (struct rcu_node *)arg; + struct sched_param sp; + struct task_struct *t; + + for (;;) { + rnp->node_kthread_status = RCU_KTHREAD_WAITING; + rcu_wait(atomic_read(&rnp->wakemask) != 0); + rnp->node_kthread_status = RCU_KTHREAD_RUNNING; + raw_spin_lock_irqsave(&rnp->lock, flags); + mask = atomic_xchg(&rnp->wakemask, 0); + rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */ + for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) { + if ((mask & 0x1) == 0) + continue; + preempt_disable(); + t = per_cpu(rcu_cpu_kthread_task, cpu); + if (!cpu_online(cpu) || t == NULL) { + preempt_enable(); + continue; + } + per_cpu(rcu_cpu_has_work, cpu) = 1; + sp.sched_priority = RCU_KTHREAD_PRIO; + sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + preempt_enable(); + } + } + /* NOTREACHED */ + rnp->node_kthread_status = RCU_KTHREAD_STOPPED; + return 0; +} + +/* + * Set the per-rcu_node kthread's affinity to cover all CPUs that are + * served by the rcu_node in question. The CPU hotplug lock is still + * held, so the value of rnp->qsmaskinit will be stable. + * + * We don't include outgoingcpu in the affinity set, use -1 if there is + * no outgoing CPU. If there are no CPUs left in the affinity set, + * this function allows the kthread to execute on any CPU. + */ +static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) +{ + cpumask_var_t cm; + int cpu; + unsigned long mask = rnp->qsmaskinit; + + if (rnp->node_kthread_task == NULL) + return; + if (!alloc_cpumask_var(&cm, GFP_KERNEL)) + return; + cpumask_clear(cm); + for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) + if ((mask & 0x1) && cpu != outgoingcpu) + cpumask_set_cpu(cpu, cm); + if (cpumask_weight(cm) == 0) { + cpumask_setall(cm); + for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++) + cpumask_clear_cpu(cpu, cm); + WARN_ON_ONCE(cpumask_weight(cm) == 0); + } + set_cpus_allowed_ptr(rnp->node_kthread_task, cm); + rcu_boost_kthread_setaffinity(rnp, cm); + free_cpumask_var(cm); +} + +/* + * Spawn a per-rcu_node kthread, setting priority and affinity. + * Called during boot before online/offline can happen, or, if + * during runtime, with the main CPU-hotplug locks held. So only + * one of these can be executing at a time. + */ +static int __cpuinit rcu_spawn_one_node_kthread(struct rcu_state *rsp, + struct rcu_node *rnp) +{ + unsigned long flags; + int rnp_index = rnp - &rsp->node[0]; + struct sched_param sp; + struct task_struct *t; + + if (!rcu_kthreads_spawnable || + rnp->qsmaskinit == 0) + return 0; + if (rnp->node_kthread_task == NULL) { + t = kthread_create(rcu_node_kthread, (void *)rnp, + "rcun%d", rnp_index); + if (IS_ERR(t)) + return PTR_ERR(t); + raw_spin_lock_irqsave(&rnp->lock, flags); + rnp->node_kthread_task = t; + raw_spin_unlock_irqrestore(&rnp->lock, flags); + sp.sched_priority = 99; + sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); + wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */ + } + return rcu_spawn_one_boost_kthread(rsp, rnp, rnp_index); +} + +/* + * Spawn all kthreads -- called as soon as the scheduler is running. + */ +static int __init rcu_spawn_kthreads(void) +{ + int cpu; + struct rcu_node *rnp; + + rcu_kthreads_spawnable = 1; + for_each_possible_cpu(cpu) { + per_cpu(rcu_cpu_has_work, cpu) = 0; + if (cpu_online(cpu)) + (void)rcu_spawn_one_cpu_kthread(cpu); + } + rnp = rcu_get_root(rcu_state); + (void)rcu_spawn_one_node_kthread(rcu_state, rnp); + if (NUM_RCU_NODES > 1) { + rcu_for_each_leaf_node(rcu_state, rnp) + (void)rcu_spawn_one_node_kthread(rcu_state, rnp); + } + return 0; +} +early_initcall(rcu_spawn_kthreads); + +static void __cpuinit rcu_prepare_kthreads(int cpu) +{ + struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu); + struct rcu_node *rnp = rdp->mynode; + + /* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */ + if (rcu_kthreads_spawnable) { + (void)rcu_spawn_one_cpu_kthread(cpu); + if (rnp->node_kthread_task == NULL) + (void)rcu_spawn_one_node_kthread(rcu_state, rnp); + } +} + #else /* #ifdef CONFIG_RCU_BOOST */ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) @@ -1346,6 +1710,26 @@ static void rcu_preempt_boost_start_gp(struct rcu_node *rnp) { } +#ifdef CONFIG_HOTPLUG_CPU + +static void rcu_stop_cpu_kthread(int cpu) +{ +} + +#endif /* #ifdef CONFIG_HOTPLUG_CPU */ + +static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) +{ +} + +static void rcu_cpu_kthread_setrt(int cpu, int to_rt) +{ +} + +static void __cpuinit rcu_prepare_kthreads(int cpu) +{ +} + #endif /* #else #ifdef CONFIG_RCU_BOOST */ #ifndef CONFIG_SMP From 826c7e4147f902737b281e8a5a7d7aa33fd63316 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 4 Jun 2011 19:34:56 +0000 Subject: [PATCH 501/595] Revert "drm/i915: Enable GMBUS for post-gen2 chipsets" Revert commit 8f9a3f9b63b8cd3f03be9dc53533f90bd4120e5f. This fixes a hang when loading the eeprom driver (see bug #35572.) GMBUS will be re-enabled later, differently. Signed-off-by: Jean Delvare Reported-by: Marek Otahal Tested-by: Yermandu Patapitafious Tested-by: Andrew Lutomirski Acked-by: Chris Wilson Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/intel_i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index d3b903bce7c5..d98cee60b602 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -401,8 +401,7 @@ int intel_setup_gmbus(struct drm_device *dev) bus->reg0 = i | GMBUS_RATE_100KHZ; /* XXX force bit banging until GMBUS is fully debugged */ - if (IS_GEN2(dev)) - bus->force_bit = intel_gpio_create(dev_priv, i); + bus->force_bit = intel_gpio_create(dev_priv, i); } intel_i2c_reset(dev_priv->dev); From ba7e05e95880ad80f012555fb8e925cb1f9a5d63 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 16 Jun 2011 18:14:22 +0000 Subject: [PATCH 502/595] drm/radeon/kms: fix num crtcs for Cedar and Caicos Only support 4 rather than 6. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_asic.c | 31 +++++++++++++++++----------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 9bd162fc9b0c..b2449629537d 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -938,6 +938,13 @@ static struct radeon_asic cayman_asic = { int radeon_asic_init(struct radeon_device *rdev) { radeon_register_accessor_init(rdev); + + /* set the number of crtcs */ + if (rdev->flags & RADEON_SINGLE_CRTC) + rdev->num_crtc = 1; + else + rdev->num_crtc = 2; + switch (rdev->family) { case CHIP_R100: case CHIP_RV100: @@ -1017,6 +1024,11 @@ int radeon_asic_init(struct radeon_device *rdev) case CHIP_JUNIPER: case CHIP_CYPRESS: case CHIP_HEMLOCK: + /* set num crtcs */ + if (rdev->family == CHIP_CEDAR) + rdev->num_crtc = 4; + else + rdev->num_crtc = 6; rdev->asic = &evergreen_asic; break; case CHIP_PALM: @@ -1027,10 +1039,17 @@ int radeon_asic_init(struct radeon_device *rdev) case CHIP_BARTS: case CHIP_TURKS: case CHIP_CAICOS: + /* set num crtcs */ + if (rdev->family == CHIP_CAICOS) + rdev->num_crtc = 4; + else + rdev->num_crtc = 6; rdev->asic = &btc_asic; break; case CHIP_CAYMAN: rdev->asic = &cayman_asic; + /* set num crtcs */ + rdev->num_crtc = 6; break; default: /* FIXME: not supported yet */ @@ -1042,18 +1061,6 @@ int radeon_asic_init(struct radeon_device *rdev) rdev->asic->set_memory_clock = NULL; } - /* set the number of crtcs */ - if (rdev->flags & RADEON_SINGLE_CRTC) - rdev->num_crtc = 1; - else { - if (ASIC_IS_DCE41(rdev)) - rdev->num_crtc = 2; - else if (ASIC_IS_DCE4(rdev)) - rdev->num_crtc = 6; - else - rdev->num_crtc = 2; - } - return 0; } From fbb87773655e7b0292756f9533c3fc21aca0797f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:13:31 -0400 Subject: [PATCH 503/595] drm/radeon/kms: rework atombios_get_encoder_mode() This should give us more reliable results if the table is called before an active device is set. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 03f124d626c2..39fa2258f235 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -660,21 +660,16 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) if (radeon_encoder_is_dp_bridge(encoder)) return ATOM_ENCODER_MODE_DP; + /* DVO is always DVO */ + if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO) + return ATOM_ENCODER_MODE_DVO; + connector = radeon_get_connector_for_encoder(encoder); - if (!connector) { - switch (radeon_encoder->encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: - return ATOM_ENCODER_MODE_DVI; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: - default: - return ATOM_ENCODER_MODE_CRT; - } - } + /* if we don't have an active device yet, just use one of + * the connectors tied to the encoder. + */ + if (!connector) + connector = radeon_get_connector_for_encoder_init(encoder); radeon_connector = to_radeon_connector(connector); switch (connector->connector_type) { From 7ec478f835a391d27491493ebfd91f2bed98dbd9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:13:32 -0400 Subject: [PATCH 504/595] drm/radeon/kms: add missing external encoder action required for ddc. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 49611e2365d9..1b50ad8919d5 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -1200,6 +1200,7 @@ typedef struct _EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 #define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF 0x10 #define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING 0x11 #define EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION 0x12 +#define EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP 0x14 // ucConfig #define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_MASK 0x03 From d629a3ceb4fc1ab5aab737b964100d114aba1173 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:13:33 -0400 Subject: [PATCH 505/595] drm/radeon/kms: add support for load detection on dp bridges dp to vga bridges for example. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 20 +++++++++ drivers/gpu/drm/radeon/radeon_encoders.c | 49 +++++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index c04e18ee8a87..dc7852b3c5ca 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1235,6 +1235,16 @@ radeon_dp_detect(struct drm_connector *connector, bool force) ret = connector_status_connected; } } + + if ((ret == connector_status_disconnected) && + radeon_connector->dac_load_detect) { + struct drm_encoder *encoder = radeon_best_single_encoder(connector); + struct drm_encoder_helper_funcs *encoder_funcs; + if (encoder) { + encoder_funcs = encoder->helper_private; + ret = encoder_funcs->detect(encoder, connector); + } + } } radeon_connector_update_scratch_regs(connector, ret); @@ -1408,6 +1418,10 @@ radeon_add_atom_connector(struct drm_device *dev, default: connector->interlace_allowed = true; connector->doublescan_allowed = true; + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); break; case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_DVID: @@ -1429,6 +1443,12 @@ radeon_add_atom_connector(struct drm_device *dev, connector->doublescan_allowed = true; else connector->doublescan_allowed = false; + if (connector_type == DRM_MODE_CONNECTOR_DVII) { + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + } break; case DRM_MODE_CONNECTOR_LVDS: case DRM_MODE_CONNECTOR_eDP: diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 39fa2258f235..d3449443aa1f 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1999,6 +1999,53 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec return connector_status_disconnected; } +static enum drm_connector_status +radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); + u32 bios_0_scratch; + + if (!ASIC_IS_DCE4(rdev)) + return connector_status_unknown; + + if (!ext_encoder) + return connector_status_unknown; + + if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0) + return connector_status_unknown; + + /* load detect on the dp bridge */ + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION); + + bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); + + DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); + if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { + if (bios_0_scratch & ATOM_S0_CRT1_MASK) + return connector_status_connected; + } + if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { + if (bios_0_scratch & ATOM_S0_CRT2_MASK) + return connector_status_connected; + } + if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { + if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) + return connector_status_connected; + } + if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { + if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) + return connector_status_connected; /* CTV */ + else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) + return connector_status_connected; /* STV */ + } + return connector_status_disconnected; +} + static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); @@ -2162,7 +2209,7 @@ static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { .mode_set = radeon_atom_encoder_mode_set, .commit = radeon_atom_encoder_commit, .disable = radeon_atom_encoder_disable, - /* no detect for TMDS/LVDS yet */ + .detect = radeon_atom_dig_detect, }; static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { From 591a10e16c2a43f6f2ea5f307ab2a5afecfb9ed9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:13:34 -0400 Subject: [PATCH 506/595] drm/radeon/kms: fix support for DDC on dp bridges Need to set up the bridge for DDC prior to the i2c over aux transaction. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 20 ++++++++++++++++---- drivers/gpu/drm/radeon/radeon_encoders.c | 12 ++++++++++++ drivers/gpu/drm/radeon/radeon_mode.h | 1 + 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index dc7852b3c5ca..613e36f83b71 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -44,6 +44,8 @@ extern void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder, struct drm_connector *drm_connector); +bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector); + void radeon_connector_hotplug(struct drm_connector *connector) { struct drm_device *dev = connector->dev; @@ -1070,10 +1072,10 @@ static int radeon_dp_get_modes(struct drm_connector *connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; + struct drm_encoder *encoder = radeon_best_single_encoder(connector); int ret; if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { - struct drm_encoder *encoder; struct drm_display_mode *mode; if (!radeon_dig_connector->edp_on) @@ -1085,7 +1087,6 @@ static int radeon_dp_get_modes(struct drm_connector *connector) ATOM_TRANSMITTER_ACTION_POWER_OFF); if (ret > 0) { - encoder = radeon_best_single_encoder(connector); if (encoder) { radeon_fixup_lvds_native_mode(encoder, connector); /* add scaled modes */ @@ -1109,8 +1110,14 @@ static int radeon_dp_get_modes(struct drm_connector *connector) /* add scaled modes */ radeon_add_common_modes(encoder, connector); } - } else + } else { + /* need to setup ddc on the bridge */ + if (radeon_connector_encoder_is_dp_bridge(connector)) { + if (encoder) + radeon_atom_ext_encoder_setup_ddc(encoder); + } ret = radeon_ddc_get_modes(radeon_connector); + } return ret; } @@ -1194,6 +1201,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force) struct radeon_connector *radeon_connector = to_radeon_connector(connector); enum drm_connector_status ret = connector_status_disconnected; struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; + struct drm_encoder *encoder = radeon_best_single_encoder(connector); if (radeon_connector->edid) { kfree(radeon_connector->edid); @@ -1201,7 +1209,6 @@ radeon_dp_detect(struct drm_connector *connector, bool force) } if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { - struct drm_encoder *encoder = radeon_best_single_encoder(connector); if (encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_display_mode *native_mode = &radeon_encoder->native_mode; @@ -1221,6 +1228,11 @@ radeon_dp_detect(struct drm_connector *connector, bool force) atombios_set_edp_panel_power(connector, ATOM_TRANSMITTER_ACTION_POWER_OFF); } else { + /* need to setup ddc on the bridge */ + if (radeon_connector_encoder_is_dp_bridge(connector)) { + if (encoder) + radeon_atom_ext_encoder_setup_ddc(encoder); + } radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { ret = connector_status_connected; diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index d3449443aa1f..8e058f1f46d6 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -2046,6 +2046,18 @@ radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connec return connector_status_disconnected; } +void +radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder) +{ + struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); + + if (ext_encoder) + /* ddc_setup on the dp bridge */ + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP); + +} + static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 977a341266b6..f734b3737dce 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -483,6 +483,7 @@ extern void radeon_atom_encoder_init(struct radeon_device *rdev); extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set); +extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, u8 write_byte, u8 *read_byte); From d6c669528a5367aaa5f4e712acef990b7148aee8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:13:36 -0400 Subject: [PATCH 507/595] drm/radeon/kms: issue blank/unblank commands for ext encoders Required for DPMS on some systems. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 25 +++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 8e058f1f46d6..aa2450ba0ff8 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1521,26 +1521,29 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) } if (ext_encoder) { - int action; - switch (mode) { case DRM_MODE_DPMS_ON: default: - if (ASIC_IS_DCE41(rdev)) - action = EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT; - else - action = ATOM_ENABLE; + if (ASIC_IS_DCE41(rdev)) { + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT); + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF); + } else + atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - if (ASIC_IS_DCE41(rdev)) - action = EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT; - else - action = ATOM_DISABLE; + if (ASIC_IS_DCE41(rdev)) { + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING); + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT); + } else + atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE); break; } - atombios_external_encoder_setup(encoder, ext_encoder, action); } radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); From f89931f345f26c43b109191fbfcfa506781111c0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:13:35 -0400 Subject: [PATCH 508/595] drm/radeon/kms: fix handling of DP to LVDS bridges They need to be treated like eDP rather than DP. May fix: https://bugzilla.kernel.org/show_bug.cgi?id=34822 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 613e36f83b71..cbfca3a24fdf 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1075,7 +1075,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) struct drm_encoder *encoder = radeon_best_single_encoder(connector); int ret; - if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || + (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { struct drm_display_mode *mode; if (!radeon_dig_connector->edp_on) @@ -1208,7 +1209,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force) radeon_connector->edid = NULL; } - if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || + (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { if (encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_display_mode *native_mode = &radeon_encoder->native_mode; @@ -1271,7 +1273,8 @@ static int radeon_dp_mode_valid(struct drm_connector *connector, /* XXX check mode bandwidth */ - if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || + (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { struct drm_encoder *encoder = radeon_best_single_encoder(connector); if ((mode->hdisplay < 320) || (mode->vdisplay < 240)) @@ -1281,7 +1284,7 @@ static int radeon_dp_mode_valid(struct drm_connector *connector, struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_display_mode *native_mode = &radeon_encoder->native_mode; - /* AVIVO hardware supports downscaling modes larger than the panel + /* AVIVO hardware supports downscaling modes larger than the panel * to the panel size, but I'm not sure this is desirable. */ if ((mode->hdisplay > native_mode->hdisplay) || From cc9f67a0a0b076b82ab1af3b2add82e19a33d5de Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 16 Jun 2011 10:06:16 -0400 Subject: [PATCH 509/595] drm/radeon/kms/atom: AdjustPixelClock fixes for DP bridges Need to set the external transmitter type properly in AdjustPixelClock to get the properly output. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 7 +++++++ drivers/gpu/drm/radeon/radeon_mode.h | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 84a69e7fa11e..9541995e4b21 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -671,6 +671,13 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, DISPPLL_CONFIG_DUAL_LINK; } } + if (radeon_encoder_is_dp_bridge(encoder)) { + struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); + struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder); + args.v3.sInput.ucExtTransmitterID = ext_radeon_encoder->encoder_id; + } else + args.v3.sInput.ucExtTransmitterID = 0; + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index f734b3737dce..6df4e3cec0c2 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -484,6 +484,7 @@ extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set); extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); +extern struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder); extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, u8 write_byte, u8 *read_byte); From 11b0a5b89adbfaf4e7d31f2482f49471dd983692 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 16 Jun 2011 10:06:17 -0400 Subject: [PATCH 510/595] drm/radeon/kms: set DP link config properly for DP bridges DP clock and lanes were not set properly for DP bridges. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index aa2450ba0ff8..f55b64cb59d1 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -367,7 +367,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, } if (ASIC_IS_DCE3(rdev) && - (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT))) { + ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || + radeon_encoder_is_dp_bridge(encoder))) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); radeon_dp_set_link_config(connector, mode); } From b81157d016a48b8025ccfcb286827679b35f16aa Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jun 2011 17:39:06 -0400 Subject: [PATCH 511/595] drm/radeon/kms: use helper functions for fence read/write The existing code assumed scratch registers in a number of places while in most cases we are be using writeback and events rather than scratch registers. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_fence.c | 51 +++++++++++++++++++-------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 1f8229436570..021d2b6b556f 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -40,6 +40,35 @@ #include "radeon.h" #include "radeon_trace.h" +static void radeon_fence_write(struct radeon_device *rdev, u32 seq) +{ + if (rdev->wb.enabled) { + u32 scratch_index; + if (rdev->wb.use_event) + scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; + else + scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; + rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);; + } else + WREG32(rdev->fence_drv.scratch_reg, seq); +} + +static u32 radeon_fence_read(struct radeon_device *rdev) +{ + u32 seq; + + if (rdev->wb.enabled) { + u32 scratch_index; + if (rdev->wb.use_event) + scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; + else + scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; + seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]); + } else + seq = RREG32(rdev->fence_drv.scratch_reg); + return seq; +} + int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) { unsigned long irq_flags; @@ -50,12 +79,12 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) return 0; } fence->seq = atomic_add_return(1, &rdev->fence_drv.seq); - if (!rdev->cp.ready) { + if (!rdev->cp.ready) /* FIXME: cp is not running assume everythings is done right * away */ - WREG32(rdev->fence_drv.scratch_reg, fence->seq); - } else + radeon_fence_write(rdev, fence->seq); + else radeon_fence_ring_emit(rdev, fence); trace_radeon_fence_emit(rdev->ddev, fence->seq); @@ -73,15 +102,7 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev) bool wake = false; unsigned long cjiffies; - if (rdev->wb.enabled) { - u32 scratch_index; - if (rdev->wb.use_event) - scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; - else - scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; - seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]); - } else - seq = RREG32(rdev->fence_drv.scratch_reg); + seq = radeon_fence_read(rdev); if (seq != rdev->fence_drv.last_seq) { rdev->fence_drv.last_seq = seq; rdev->fence_drv.last_jiffies = jiffies; @@ -251,7 +272,7 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr) r = radeon_gpu_reset(rdev); if (r) return r; - WREG32(rdev->fence_drv.scratch_reg, fence->seq); + radeon_fence_write(rdev, fence->seq); rdev->gpu_lockup = false; } timeout = RADEON_FENCE_JIFFIES_TIMEOUT; @@ -351,7 +372,7 @@ int radeon_fence_driver_init(struct radeon_device *rdev) write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); return r; } - WREG32(rdev->fence_drv.scratch_reg, 0); + radeon_fence_write(rdev, 0); atomic_set(&rdev->fence_drv.seq, 0); INIT_LIST_HEAD(&rdev->fence_drv.created); INIT_LIST_HEAD(&rdev->fence_drv.emited); @@ -391,7 +412,7 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data) struct radeon_fence *fence; seq_printf(m, "Last signaled fence 0x%08X\n", - RREG32(rdev->fence_drv.scratch_reg)); + radeon_fence_read(rdev)); if (!list_empty(&rdev->fence_drv.emited)) { fence = list_entry(rdev->fence_drv.emited.prev, struct radeon_fence, list); From d40261236e8e278cb1936cb5e934262971692b10 Mon Sep 17 00:00:00 2001 From: "Marius B. Kotsbak" Date: Sun, 12 Jun 2011 02:35:02 +0000 Subject: [PATCH 512/595] net/usb: Add Samsung Kalmia driver for Samsung GT-B3730 Introducing driver for the network port of Samsung Kalmia based USB LTE modems. It has also an ACM interface that previous patches associates with the "option" module. To access those interfaces, the modem must first be switched from modem mode using a tool like usb_modeswitch. As the proprietary protocol has been discovered by watching the MS Windows driver behavior, there might be errors in the protocol handling, but stable and fast connection has been established for hours with Norwegian operator NetCom that distributes this modem with their LTE/4G subscription. More and updated information about how to use this driver is available here: http://www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?t=465 https://github.com/mkotsbak/Samsung-GT-B3730-linux-driver Signed-off-by: Marius B. Kotsbak Signed-off-by: David S. Miller --- drivers/net/usb/Kconfig | 10 + drivers/net/usb/Makefile | 1 + drivers/net/usb/kalmia.c | 384 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 395 insertions(+) create mode 100644 drivers/net/usb/kalmia.c diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 9d4f9117260f..84d4608153c9 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -385,6 +385,16 @@ config USB_NET_CX82310_ETH router with USB ethernet port. This driver is for routers only, it will not work with ADSL modems (use cxacru driver instead). +config USB_NET_KALMIA + tristate "Samsung Kalmia based LTE USB modem" + depends on USB_USBNET + help + Choose this option if you have a Samsung Kalmia based USB modem + as Samsung GT-B3730. + + To compile this driver as a module, choose M here: the + module will be called kalmia. + config USB_HSO tristate "Option USB High Speed Mobile Devices" depends on USB && RFKILL diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index c7ec8a5f0a90..c203fa21f6b1 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o obj-$(CONFIG_USB_USBNET) += usbnet.o obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o obj-$(CONFIG_USB_CDC_PHONET) += cdc-phonet.o +obj-$(CONFIG_USB_NET_KALMIA) += kalmia.o obj-$(CONFIG_USB_IPHETH) += ipheth.o obj-$(CONFIG_USB_SIERRA_NET) += sierra_net.o obj-$(CONFIG_USB_NET_CX82310_ETH) += cx82310_eth.o diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c new file mode 100644 index 000000000000..d965fb1e013e --- /dev/null +++ b/drivers/net/usb/kalmia.c @@ -0,0 +1,384 @@ +/* + * USB network interface driver for Samsung Kalmia based LTE USB modem like the + * Samsung GT-B3730 and GT-B3710. + * + * Copyright (C) 2011 Marius Bjoernstad Kotsbak + * + * Sponsored by Quicklink Video Distribution Services Ltd. + * + * Based on the cdc_eem module. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The Samsung Kalmia based LTE USB modems have a CDC ACM port for modem control + * handled by the "option" module and an ethernet data port handled by this + * module. + * + * The stick must first be switched into modem mode by usb_modeswitch + * or similar tool. Then the modem gets sent two initialization packets by + * this module, which gives the MAC address of the device. User space can then + * connect the modem using AT commands through the ACM port and then use + * DHCP on the network interface exposed by this module. Network packets are + * sent to and from the modem in a proprietary format discovered after watching + * the behavior of the windows driver for the modem. + * + * More information about the use of the modem is available in usb_modeswitch + * forum and the project page: + * + * http://www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?t=465 + * https://github.com/mkotsbak/Samsung-GT-B3730-linux-driver + */ + +/* #define DEBUG */ +/* #define VERBOSE */ + +#define KALMIA_HEADER_LENGTH 6 +#define KALMIA_ALIGN_SIZE 4 +#define KALMIA_USB_TIMEOUT 10000 + +/*-------------------------------------------------------------------------*/ + +static int +kalmia_send_init_packet(struct usbnet *dev, u8 *init_msg, u8 init_msg_len, + u8 *buffer, u8 expected_len) +{ + int act_len; + int status; + + netdev_dbg(dev->net, "Sending init packet"); + + status = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 0x02), + init_msg, init_msg_len, &act_len, KALMIA_USB_TIMEOUT); + if (status != 0) { + netdev_err(dev->net, + "Error sending init packet. Status %i, length %i\n", + status, act_len); + return status; + } + else if (act_len != init_msg_len) { + netdev_err(dev->net, + "Did not send all of init packet. Bytes sent: %i", + act_len); + } + else { + netdev_dbg(dev->net, "Successfully sent init packet."); + } + + status = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, 0x81), + buffer, expected_len, &act_len, KALMIA_USB_TIMEOUT); + + if (status != 0) + netdev_err(dev->net, + "Error receiving init result. Status %i, length %i\n", + status, act_len); + else if (act_len != expected_len) + netdev_err(dev->net, "Unexpected init result length: %i\n", + act_len); + + return status; +} + +static int +kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr) +{ + char init_msg_1[] = + { 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00 }; + char init_msg_2[] = + { 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf4, + 0x00, 0x00 }; + char receive_buf[28]; + int status; + + status = kalmia_send_init_packet(dev, init_msg_1, sizeof(init_msg_1) + / sizeof(init_msg_1[0]), receive_buf, 24); + if (status != 0) + return status; + + status = kalmia_send_init_packet(dev, init_msg_2, sizeof(init_msg_2) + / sizeof(init_msg_2[0]), receive_buf, 28); + if (status != 0) + return status; + + memcpy(ethernet_addr, receive_buf + 10, ETH_ALEN); + + return status; +} + +static int +kalmia_bind(struct usbnet *dev, struct usb_interface *intf) +{ + u8 status; + u8 ethernet_addr[ETH_ALEN]; + + /* Don't bind to AT command interface */ + if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) + return -EINVAL; + + dev->in = usb_rcvbulkpipe(dev->udev, 0x81 & USB_ENDPOINT_NUMBER_MASK); + dev->out = usb_sndbulkpipe(dev->udev, 0x02 & USB_ENDPOINT_NUMBER_MASK); + dev->status = NULL; + + dev->net->hard_header_len += KALMIA_HEADER_LENGTH; + dev->hard_mtu = 1400; + dev->rx_urb_size = dev->hard_mtu * 10; // Found as optimal after testing + + status = kalmia_init_and_get_ethernet_addr(dev, ethernet_addr); + + if (status < 0) { + usb_set_intfdata(intf, NULL); + usb_driver_release_interface(driver_of(intf), intf); + return status; + } + + memcpy(dev->net->dev_addr, ethernet_addr, ETH_ALEN); + memcpy(dev->net->perm_addr, ethernet_addr, ETH_ALEN); + + return status; +} + +static struct sk_buff * +kalmia_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) +{ + struct sk_buff *skb2 = NULL; + u16 content_len; + unsigned char *header_start; + unsigned char ether_type_1, ether_type_2; + u8 remainder, padlen = 0; + + if (!skb_cloned(skb)) { + int headroom = skb_headroom(skb); + int tailroom = skb_tailroom(skb); + + if ((tailroom >= KALMIA_ALIGN_SIZE) && (headroom + >= KALMIA_HEADER_LENGTH)) + goto done; + + if ((headroom + tailroom) > (KALMIA_HEADER_LENGTH + + KALMIA_ALIGN_SIZE)) { + skb->data = memmove(skb->head + KALMIA_HEADER_LENGTH, + skb->data, skb->len); + skb_set_tail_pointer(skb, skb->len); + goto done; + } + } + + skb2 = skb_copy_expand(skb, KALMIA_HEADER_LENGTH, + KALMIA_ALIGN_SIZE, flags); + if (!skb2) + return NULL; + + dev_kfree_skb_any(skb); + skb = skb2; + + done: header_start = skb_push(skb, KALMIA_HEADER_LENGTH); + ether_type_1 = header_start[KALMIA_HEADER_LENGTH + 12]; + ether_type_2 = header_start[KALMIA_HEADER_LENGTH + 13]; + + netdev_dbg(dev->net, "Sending etherType: %02x%02x", ether_type_1, + ether_type_2); + + /* According to empiric data for data packages */ + header_start[0] = 0x57; + header_start[1] = 0x44; + content_len = skb->len - KALMIA_HEADER_LENGTH; + header_start[2] = (content_len & 0xff); /* low byte */ + header_start[3] = (content_len >> 8); /* high byte */ + + header_start[4] = ether_type_1; + header_start[5] = ether_type_2; + + /* Align to 4 bytes by padding with zeros */ + remainder = skb->len % KALMIA_ALIGN_SIZE; + if (remainder > 0) { + padlen = KALMIA_ALIGN_SIZE - remainder; + memset(skb_put(skb, padlen), 0, padlen); + } + + netdev_dbg( + dev->net, + "Sending package with length %i and padding %i. Header: %02x:%02x:%02x:%02x:%02x:%02x.", + content_len, padlen, header_start[0], header_start[1], + header_start[2], header_start[3], header_start[4], + header_start[5]); + + return skb; +} + +static int +kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + /* + * Our task here is to strip off framing, leaving skb with one + * data frame for the usbnet framework code to process. + */ + const u8 HEADER_END_OF_USB_PACKET[] = + { 0x57, 0x5a, 0x00, 0x00, 0x08, 0x00 }; + const u8 EXPECTED_UNKNOWN_HEADER_1[] = + { 0x57, 0x43, 0x1e, 0x00, 0x15, 0x02 }; + const u8 EXPECTED_UNKNOWN_HEADER_2[] = + { 0x57, 0x50, 0x0e, 0x00, 0x00, 0x00 }; + u8 i = 0; + + /* incomplete header? */ + if (skb->len < KALMIA_HEADER_LENGTH) + return 0; + + do { + struct sk_buff *skb2 = NULL; + u8 *header_start; + u16 usb_packet_length, ether_packet_length; + int is_last; + + header_start = skb->data; + + if (unlikely(header_start[0] != 0x57 || header_start[1] != 0x44)) { + if (!memcmp(header_start, EXPECTED_UNKNOWN_HEADER_1, + sizeof(EXPECTED_UNKNOWN_HEADER_1)) || !memcmp( + header_start, EXPECTED_UNKNOWN_HEADER_2, + sizeof(EXPECTED_UNKNOWN_HEADER_2))) { + netdev_dbg( + dev->net, + "Received expected unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", + header_start[0], header_start[1], + header_start[2], header_start[3], + header_start[4], header_start[5], + skb->len - KALMIA_HEADER_LENGTH); + } + else { + netdev_err( + dev->net, + "Received unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", + header_start[0], header_start[1], + header_start[2], header_start[3], + header_start[4], header_start[5], + skb->len - KALMIA_HEADER_LENGTH); + return 0; + } + } + else + netdev_dbg( + dev->net, + "Received header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", + header_start[0], header_start[1], header_start[2], + header_start[3], header_start[4], header_start[5], + skb->len - KALMIA_HEADER_LENGTH); + + /* subtract start header and end header */ + usb_packet_length = skb->len - (2 * KALMIA_HEADER_LENGTH); + ether_packet_length = header_start[2] + (header_start[3] << 8); + skb_pull(skb, KALMIA_HEADER_LENGTH); + + /* Some small packets misses end marker */ + if (usb_packet_length < ether_packet_length) { + ether_packet_length = usb_packet_length + + KALMIA_HEADER_LENGTH; + is_last = true; + } + else { + netdev_dbg(dev->net, "Correct package length #%i", i + + 1); + + is_last = (memcmp(skb->data + ether_packet_length, + HEADER_END_OF_USB_PACKET, + sizeof(HEADER_END_OF_USB_PACKET)) == 0); + if (!is_last) { + header_start = skb->data + ether_packet_length; + netdev_dbg( + dev->net, + "End header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", + header_start[0], header_start[1], + header_start[2], header_start[3], + header_start[4], header_start[5], + skb->len - KALMIA_HEADER_LENGTH); + } + } + + if (is_last) { + skb2 = skb; + } + else { + skb2 = skb_clone(skb, GFP_ATOMIC); + if (unlikely(!skb2)) + return 0; + } + + skb_trim(skb2, ether_packet_length); + + if (is_last) { + return 1; + } + else { + usbnet_skb_return(dev, skb2); + skb_pull(skb, ether_packet_length); + } + + i++; + } + while (skb->len); + + return 1; +} + +static const struct driver_info kalmia_info = { + .description = "Samsung Kalmia LTE USB dongle", + .flags = FLAG_WWAN, + .bind = kalmia_bind, + .rx_fixup = kalmia_rx_fixup, + .tx_fixup = kalmia_tx_fixup +}; + +/*-------------------------------------------------------------------------*/ + +static const struct usb_device_id products[] = { + /* The unswitched USB ID, to get the module auto loaded: */ + { USB_DEVICE(0x04e8, 0x689a) }, + /* The stick swithed into modem (by e.g. usb_modeswitch): */ + { USB_DEVICE(0x04e8, 0x6889), + .driver_info = (unsigned long) &kalmia_info, }, + { /* EMPTY == end of list */} }; +MODULE_DEVICE_TABLE( usb, products); + +static struct usb_driver kalmia_driver = { + .name = "kalmia", + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume +}; + +static int __init kalmia_init(void) +{ + return usb_register(&kalmia_driver); +} +module_init( kalmia_init); + +static void __exit kalmia_exit(void) +{ + usb_deregister(&kalmia_driver); +} +module_exit( kalmia_exit); + +MODULE_AUTHOR("Marius Bjoernstad Kotsbak "); +MODULE_DESCRIPTION("Samsung Kalmia USB network driver"); +MODULE_LICENSE("GPL"); From 62b2bcb49cca72f6d3f39f831127a6ab315a475d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Luis=20V=C3=A1zquez=20Cao?= Date: Mon, 13 Jun 2011 15:04:43 +0000 Subject: [PATCH 513/595] IGMP snooping: set mrouters_only flag for IPv4 traffic properly Upon reception of a IGMP/IGMPv2 membership report the kernel sets the mrouters_only flag in a skb that may be a clone of the original skb, which means that sometimes the bridge loses track of membership report packets (cb buffers are tied to a specific skb and not shared) and it ends up forwading join requests to the bridge interface. This can cause unexpected membership timeouts and intermitent/permanent loss of connectivity as described in RFC 4541 [2.1.1. IGMP Forwarding Rules]: A snooping switch should forward IGMP Membership Reports only to those ports where multicast routers are attached. [...] Sending membership reports to other hosts can result, for IGMPv1 and IGMPv2, in unintentionally preventing a host from joining a specific multicast group. Signed-off-by: Fernando Luis Vazquez Cao Tested-by: Hayato Kakuta Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 2f14eafdeeab..a6d87c17bb03 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1424,7 +1424,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, switch (ih->type) { case IGMP_HOST_MEMBERSHIP_REPORT: case IGMPV2_HOST_MEMBERSHIP_REPORT: - BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; + BR_INPUT_SKB_CB(skb)->mrouters_only = 1; err = br_ip4_multicast_add_group(br, port, ih->group); break; case IGMPV3_HOST_MEMBERSHIP_REPORT: From fc2af6c73fc9449cd5894a36bb76b8f8c0e49fd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Luis=20V=C3=A1zquez=20Cao?= Date: Mon, 13 Jun 2011 15:06:58 +0000 Subject: [PATCH 514/595] IGMP snooping: set mrouters_only flag for IPv6 traffic properly Upon reception of a MGM report packet the kernel sets the mrouters_only flag in a skb that is a clone of the original skb, which means that the bridge loses track of MGM packets (cb buffers are tied to a specific skb and not shared) and it ends up forwading join requests to the bridge interface. This can cause unexpected membership timeouts and intermitent/permanent loss of connectivity as described in RFC 4541 [2.1.1. IGMP Forwarding Rules]: A snooping switch should forward IGMP Membership Reports only to those ports where multicast routers are attached. [...] Sending membership reports to other hosts can result, for IGMPv1 and IGMPv2, in unintentionally preventing a host from joining a specific multicast group. Signed-off-by: Fernando Luis Vazquez Cao Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index a6d87c17bb03..29b9812c8da0 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1543,7 +1543,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, goto out; } mld = (struct mld_msg *)skb_transport_header(skb2); - BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; + BR_INPUT_SKB_CB(skb)->mrouters_only = 1; err = br_ip6_multicast_add_group(br, port, &mld->mld_mca); break; } From d3ab6fde14b69c346939cd00765b3826a4760e5c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 13 Jun 2011 16:26:22 +0000 Subject: [PATCH 515/595] MAINTAINERS: Update EBTABLES mailing list It moved to netfilter-devel@vger.kernel.org. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- MAINTAINERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6a1c430d2821..0f1515a9780d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2292,8 +2292,7 @@ F: drivers/scsi/eata_pio.* EBTABLES M: Bart De Schuymer -L: ebtables-user@lists.sourceforge.net -L: ebtables-devel@lists.sourceforge.net +L: netfilter-devel@vger.kernel.org W: http://ebtables.sourceforge.net/ S: Maintained F: include/linux/netfilter_bridge/ebt_*.h From e6539e2b7aee117619153daaf61566dba1e04205 Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Tue, 14 Jun 2011 21:58:13 +0000 Subject: [PATCH 516/595] ppp: use PPP_TRANS instead of the magic number 0x20 Signed-off-by: Changli Gao Signed-off-by: David S. Miller --- drivers/net/ppp_async.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index a1b82c9c67d2..c554a397e558 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -523,7 +523,7 @@ static void ppp_async_process(unsigned long arg) #define PUT_BYTE(ap, buf, c, islcp) do { \ if ((islcp && c < 0x20) || (ap->xaccm[c >> 5] & (1 << (c & 0x1f)))) {\ *buf++ = PPP_ESCAPE; \ - *buf++ = c ^ 0x20; \ + *buf++ = c ^ PPP_TRANS; \ } else \ *buf++ = c; \ } while (0) @@ -896,7 +896,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf, sp = skb_put(skb, n); memcpy(sp, buf, n); if (ap->state & SC_ESCAPE) { - sp[0] ^= 0x20; + sp[0] ^= PPP_TRANS; ap->state &= ~SC_ESCAPE; } } From f1dc045e685ea5424b3445c1ccaa0a25b3d661ec Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 14 Jun 2011 22:07:58 +0000 Subject: [PATCH 517/595] phylib: Allow BCM63XX PHY to be selected only on BCM63XX. This PHY is available integrated into BCM63xx series SOCs only. Signed-off-by: Ralf Baechle drivers/net/phy/Kconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 392a6c4b72e5..a70244306c94 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -58,6 +58,7 @@ config BROADCOM_PHY config BCM63XX_PHY tristate "Drivers for Broadcom 63xx SOCs internal PHY" + depends on BCM63XX ---help--- Currently supports the 6348 and 6358 PHYs. From 2331038a96ecdad76c50ab223fd48d656d8a1184 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Tue, 14 Jun 2011 23:55:19 +0000 Subject: [PATCH 518/595] dp83640: fix phy status frame event parsing If two eternal time stamp events occur at nearly the same time, the phyter will add an extra word into the status frame. This commit fixes the parsing code to recognize and skip over the extra word. Signed-off-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index b0c9522bb535..ead323e56739 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -543,11 +543,20 @@ static void recalibrate(struct dp83640_clock *clock) /* time stamping methods */ -static void decode_evnt(struct dp83640_private *dp83640, - struct phy_txts *phy_txts, u16 ests) +static int decode_evnt(struct dp83640_private *dp83640, + void *data, u16 ests) { + struct phy_txts *phy_txts; struct ptp_clock_event event; int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK; + u16 ext_status = 0; + + if (ests & MULT_EVNT) { + ext_status = *(u16 *) data; + data += sizeof(ext_status); + } + + phy_txts = data; switch (words) { /* fall through in every case */ case 3: @@ -565,6 +574,9 @@ static void decode_evnt(struct dp83640_private *dp83640, event.timestamp = phy2txts(&dp83640->edata); ptp_clock_event(dp83640->clock->ptp_clock, &event); + + words = ext_status ? words + 2 : words + 1; + return words * sizeof(u16); } static void decode_rxts(struct dp83640_private *dp83640, @@ -643,9 +655,7 @@ static void decode_status_frame(struct dp83640_private *dp83640, } else if (PSF_EVNT == type && len >= sizeof(*phy_txts)) { - phy_txts = (struct phy_txts *) ptr; - decode_evnt(dp83640, phy_txts, ests); - size = sizeof(*phy_txts); + size = decode_evnt(dp83640, ptr, ests); } else { size = 0; From ae6e86b7fb15520ac64513ad643de63e0b077aa5 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Tue, 14 Jun 2011 23:55:20 +0000 Subject: [PATCH 519/595] dp83640: drop PHY status frames in the driver. The dp83640 PHY provides time stamp and other information via special PHY status frames. Previously, the driver decoded the frames and then let the network stack drop them. This works fine when the PTP messages come over UDP. However, when receiving PTP messages via L2 packets, this creates a problem. The status frames use the official PTP destination MAC address, and so they are delivered to user space along with the "real" frames, causing confusion for applications. This commit fixes the issue by simply dropping the PHY status frames in the driver. Signed-off-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index ead323e56739..2cd8dc5847b4 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -1044,8 +1044,8 @@ static bool dp83640_rxtstamp(struct phy_device *phydev, if (is_status_frame(skb, type)) { decode_status_frame(dp83640, skb); - /* Let the stack drop this frame. */ - return false; + kfree_skb(skb); + return true; } SKB_PTP_TYPE(skb) = type; From bebd097a0af8bd6c51f50a65f3a435019b0e906a Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 15 Jun 2011 05:25:01 +0000 Subject: [PATCH 520/595] tun: teach the tun/tap driver to support netpoll Commit 8d8fc29d02a33e4bd5f4fa47823c1fd386346093 changed the behavior of slave devices in regards to netpoll. Specifically it created a mutually exclusive relationship between being a slave and a netpoll-capable device. This creates problems for KVM because guests relied on needing netconsole active on a slave device to a bridge. Ideally libvirtd could just attach netconsole to the bridge device instead, but thats currently infeasible, because while the bridge device supports netpoll, it requires that all slave interface also support it, but the tun/tap driver currently does not. The most direct solution is to teach tun/tap to support netpoll, which is implemented by the patch below. I've not tested this yet, but its pretty straightforward. Signed-off-by: Neil Horman Reported-by: Rik van Riel CC: Rik van Riel CC: Maxim Krasnyansky CC: Cong Wang CC: "David S. Miller" Reviewed-by: Rik van Riel Tested-by: Rik van Riel Reviewed-by: WANG Cong Signed-off-by: David S. Miller --- drivers/net/tun.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 74e94054ab1a..5235f48be1be 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -460,7 +460,23 @@ static u32 tun_net_fix_features(struct net_device *dev, u32 features) return (features & tun->set_features) | (features & ~TUN_USER_FEATURES); } - +#ifdef CONFIG_NET_POLL_CONTROLLER +static void tun_poll_controller(struct net_device *dev) +{ + /* + * Tun only receives frames when: + * 1) the char device endpoint gets data from user space + * 2) the tun socket gets a sendmsg call from user space + * Since both of those are syncronous operations, we are guaranteed + * never to have pending data when we poll for it + * so theres nothing to do here but return. + * We need this though so netpoll recognizes us as an interface that + * supports polling, which enables bridge devices in virt setups to + * still use netconsole + */ + return; +} +#endif static const struct net_device_ops tun_netdev_ops = { .ndo_uninit = tun_net_uninit, .ndo_open = tun_net_open, @@ -468,6 +484,9 @@ static const struct net_device_ops tun_netdev_ops = { .ndo_start_xmit = tun_net_xmit, .ndo_change_mtu = tun_net_change_mtu, .ndo_fix_features = tun_net_fix_features, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tun_poll_controller, +#endif }; static const struct net_device_ops tap_netdev_ops = { @@ -480,6 +499,9 @@ static const struct net_device_ops tap_netdev_ops = { .ndo_set_multicast_list = tun_net_mclist, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tun_poll_controller, +#endif }; /* Initialize net device. */ From a1b7f85e4f632f9cc342d8a34a3903feaf47a261 Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Wed, 15 Jun 2011 12:38:25 +0000 Subject: [PATCH 521/595] caif: Bugfix - XOFF removed channel from caif-mux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit XOFF was mixed up with DOWN indication, causing causing CAIF channel to be removed from mux and all incoming traffic to be lost after receiving flow-off. Fix this by replacing FLOW_OFF with DOWN notification. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- net/caif/cfmuxl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c index 3a66b8c10e09..c23979e79dfa 100644 --- a/net/caif/cfmuxl.c +++ b/net/caif/cfmuxl.c @@ -255,7 +255,7 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, if (cfsrvl_phyid_match(layer, phyid) && layer->ctrlcmd) { - if ((ctrl == _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND || + if ((ctrl == _CAIF_CTRLCMD_PHYIF_DOWN_IND || ctrl == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND) && layer->id != 0) { From e3cb78c772de593afa720687ce3abbed8d93b0c3 Mon Sep 17 00:00:00 2001 From: Antoine Reversat Date: Thu, 16 Jun 2011 10:47:13 +0000 Subject: [PATCH 522/595] vlan: don't call ndo_vlan_rx_register on hardware that doesn't have vlan support This patch removes the call to ndo_vlan_rx_register if the underlying device doesn't have hardware support for VLAN. Signed-off-by: Antoine Reversat Signed-off-by: David S. Miller --- net/8021q/vlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index c7a581a96894..917ecb93ea28 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -205,7 +205,7 @@ int register_vlan_dev(struct net_device *dev) grp->nr_vlans++; if (ngrp) { - if (ops->ndo_vlan_rx_register) + if (ops->ndo_vlan_rx_register && (real_dev->features & NETIF_F_HW_VLAN_RX)) ops->ndo_vlan_rx_register(real_dev, ngrp); rcu_assign_pointer(real_dev->vlgrp, ngrp); } From 118133e6580a0c912cda86109b6468b5ffe73f1c Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 16 Jun 2011 12:31:58 +0000 Subject: [PATCH 523/595] netdev: bfin_mac: fix memory leak when freeing dma descriptors The size of the desc array is not the size of the desc structure, so when we try to free up things, we leak some parts. Reported-by: Regis Dargent Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger Signed-off-by: David S. Miller --- drivers/net/bfin_mac.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 68d45ba2d9b9..6c019e148546 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -52,13 +52,13 @@ MODULE_DESCRIPTION(DRV_DESC); MODULE_ALIAS("platform:bfin_mac"); #if defined(CONFIG_BFIN_MAC_USE_L1) -# define bfin_mac_alloc(dma_handle, size) l1_data_sram_zalloc(size) -# define bfin_mac_free(dma_handle, ptr) l1_data_sram_free(ptr) +# define bfin_mac_alloc(dma_handle, size, num) l1_data_sram_zalloc(size*num) +# define bfin_mac_free(dma_handle, ptr, num) l1_data_sram_free(ptr) #else -# define bfin_mac_alloc(dma_handle, size) \ - dma_alloc_coherent(NULL, size, dma_handle, GFP_KERNEL) -# define bfin_mac_free(dma_handle, ptr) \ - dma_free_coherent(NULL, sizeof(*ptr), ptr, dma_handle) +# define bfin_mac_alloc(dma_handle, size, num) \ + dma_alloc_coherent(NULL, size*num, dma_handle, GFP_KERNEL) +# define bfin_mac_free(dma_handle, ptr, num) \ + dma_free_coherent(NULL, sizeof(*ptr)*num, ptr, dma_handle) #endif #define PKT_BUF_SZ 1580 @@ -95,7 +95,7 @@ static void desc_list_free(void) t = t->next; } } - bfin_mac_free(dma_handle, tx_desc); + bfin_mac_free(dma_handle, tx_desc, CONFIG_BFIN_TX_DESC_NUM); } if (rx_desc) { @@ -109,7 +109,7 @@ static void desc_list_free(void) r = r->next; } } - bfin_mac_free(dma_handle, rx_desc); + bfin_mac_free(dma_handle, rx_desc, CONFIG_BFIN_RX_DESC_NUM); } } @@ -126,13 +126,13 @@ static int desc_list_init(void) #endif tx_desc = bfin_mac_alloc(&dma_handle, - sizeof(struct net_dma_desc_tx) * + sizeof(struct net_dma_desc_tx), CONFIG_BFIN_TX_DESC_NUM); if (tx_desc == NULL) goto init_error; rx_desc = bfin_mac_alloc(&dma_handle, - sizeof(struct net_dma_desc_rx) * + sizeof(struct net_dma_desc_rx), CONFIG_BFIN_RX_DESC_NUM); if (rx_desc == NULL) goto init_error; From d8ad7d1123a960cc9f276bd499f9325c6f5e1bd1 Mon Sep 17 00:00:00 2001 From: Takao Indoh Date: Tue, 29 Mar 2011 12:35:04 -0400 Subject: [PATCH 524/595] generic-ipi: Fix kexec boot crash by initializing call_single_queue before enabling interrupts There is a problem that kdump(2nd kernel) sometimes hangs up due to a pending IPI from 1st kernel. Kernel panic occurs because IPI comes before call_single_queue is initialized. To fix the crash, rename init_call_single_data() to call_function_init() and call it in start_kernel() so that call_single_queue can be initialized before enabling interrupts. The details of the crash are: (1) 2nd kernel boots up (2) A pending IPI from 1st kernel comes when irqs are first enabled in start_kernel(). (3) Kernel tries to handle the interrupt, but call_single_queue is not initialized yet at this point. As a result, in the generic_smp_call_function_single_interrupt(), NULL pointer dereference occurs when list_replace_init() tries to access &q->list.next. Therefore this patch changes the name of init_call_single_data() to call_function_init() and calls it before local_irq_enable() in start_kernel(). Signed-off-by: Takao Indoh Reviewed-by: WANG Cong Acked-by: Neil Horman Acked-by: Vivek Goyal Acked-by: Peter Zijlstra Cc: Milton Miller Cc: Jens Axboe Cc: Paul E. McKenney Cc: kexec@lists.infradead.org Link: http://lkml.kernel.org/r/D6CBEE2F420741indou.takao@jp.fujitsu.com Signed-off-by: Ingo Molnar --- include/linux/smp.h | 5 ++++- init/main.c | 1 + kernel/smp.c | 5 +---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/linux/smp.h b/include/linux/smp.h index 7ad824d510a2..8cc38d3bab0c 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -85,12 +85,15 @@ int smp_call_function_any(const struct cpumask *mask, * Generic and arch helpers */ #ifdef CONFIG_USE_GENERIC_SMP_HELPERS +void __init call_function_init(void); void generic_smp_call_function_single_interrupt(void); void generic_smp_call_function_interrupt(void); void ipi_call_lock(void); void ipi_call_unlock(void); void ipi_call_lock_irq(void); void ipi_call_unlock_irq(void); +#else +static inline void call_function_init(void) { } #endif /* @@ -134,7 +137,7 @@ static inline void smp_send_reschedule(int cpu) { } #define smp_prepare_boot_cpu() do {} while (0) #define smp_call_function_many(mask, func, info, wait) \ (up_smp_call_function(func, info)) -static inline void init_call_single_data(void) { } +static inline void call_function_init(void) { } static inline int smp_call_function_any(const struct cpumask *mask, smp_call_func_t func, diff --git a/init/main.c b/init/main.c index cafba67c13bf..d7211faed2ad 100644 --- a/init/main.c +++ b/init/main.c @@ -542,6 +542,7 @@ asmlinkage void __init start_kernel(void) timekeeping_init(); time_init(); profile_init(); + call_function_init(); if (!irqs_disabled()) printk(KERN_CRIT "start_kernel(): bug: interrupts were " "enabled early\n"); diff --git a/kernel/smp.c b/kernel/smp.c index 73a195193558..fb67dfa8394e 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -74,7 +74,7 @@ static struct notifier_block __cpuinitdata hotplug_cfd_notifier = { .notifier_call = hotplug_cfd, }; -static int __cpuinit init_call_single_data(void) +void __init call_function_init(void) { void *cpu = (void *)(long)smp_processor_id(); int i; @@ -88,10 +88,7 @@ static int __cpuinit init_call_single_data(void) hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu); register_cpu_notifier(&hotplug_cfd_notifier); - - return 0; } -early_initcall(init_call_single_data); /* * csd_lock/csd_unlock used to serialize access to per-cpu csd resources From cf6f1ff17f56c275424c5a341fc4d27ccbbfa71c Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Fri, 17 Jun 2011 08:18:35 +0200 Subject: [PATCH 525/595] ALSA: isight: adjust for new queueing API Since commit 13882a82ee16 (optimize iso queueing by setting wake only after the last packet), drivers are required to call fw_iso_context_queue_flush() after queueing a batch of packets. The missing call would have an effect only if the controller queue underruns, but then the DMA would stop completely. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/firewire/isight.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index 86ee16ca365e..440030818db7 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c @@ -209,6 +209,7 @@ static void isight_packet(struct fw_iso_context *context, u32 cycle, isight->packet_index = -1; return; } + fw_iso_context_queue_flush(isight->context); if (++index >= QUEUE_LENGTH) index = 0; From ad2409413d09fca763be1ac5161f2a9d82367903 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 17 Jun 2011 14:23:46 +0200 Subject: [PATCH 526/595] ALSA: hda - Fix no NID error with VIA codecs The via driver spews warnigs like hda-codec: no NID for mapping control Independent HP:0:0 with some codecs because snd_hda_add_nid() is called with nid=0. This patch fixes it by skipping the call when no corresponding widget is found. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 605c99e1e520..c952582fb218 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -832,10 +832,13 @@ static int via_hp_build(struct hda_codec *codec) knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; knew->private_value = nid; - knew = via_clone_control(spec, &via_hp_mixer[1]); - if (knew == NULL) - return -ENOMEM; - knew->subdevice = side_mute_channel(spec); + nid = side_mute_channel(spec); + if (nid) { + knew = via_clone_control(spec, &via_hp_mixer[1]); + if (knew == NULL) + return -ENOMEM; + knew->subdevice = nid; + } return 0; } From e479c60456ef22b0869432887216186aabaed086 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 17 Jun 2011 04:35:37 -0400 Subject: [PATCH 527/595] spi/bfin_spi: fix handling of default bits per word setting The default bits per word setting should be 8 bits, but since most of our devices have been explicitly setting this up, we didn't notice when the default stopped working. At the moment, any default transfers without an explicit bit size setting error out with: bfin-spi bfin-spi.0: transfer: unsupported bits_per_word So in the transfer logic, have a bits_per_word setting of 0 fall into the 8 bit transfer logic. Signed-off-by: Mike Frysinger Signed-off-by: Grant Likely --- drivers/spi/spi_bfin5xx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index f706dba165cf..cc880c95e7de 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c @@ -681,13 +681,14 @@ static void bfin_spi_pump_transfers(unsigned long data) drv_data->cs_change = transfer->cs_change; /* Bits per word setup */ - bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word; - if ((bits_per_word > 0) && (bits_per_word % 16 == 0)) { + bits_per_word = transfer->bits_per_word ? : + message->spi->bits_per_word ? : 8; + if (bits_per_word % 16 == 0) { drv_data->n_bytes = bits_per_word/8; drv_data->len = (transfer->len) >> 1; cr_width = BIT_CTL_WORDSIZE; drv_data->ops = &bfin_bfin_spi_transfer_ops_u16; - } else if ((bits_per_word > 0) && (bits_per_word % 8 == 0)) { + } else if (bits_per_word % 8 == 0) { drv_data->n_bytes = bits_per_word/8; drv_data->len = transfer->len; cr_width = 0; From 879669961b11e7f40b518784863a259f735a72bf Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 17 Jun 2011 11:25:59 +0100 Subject: [PATCH 528/595] KEYS/DNS: Fix ____call_usermodehelper() to not lose the session keyring ____call_usermodehelper() now erases any credentials set by the subprocess_inf::init() function. The problem is that commit 17f60a7da150 ("capabilites: allow the application of capability limits to usermode helpers") creates and commits new credentials with prepare_kernel_cred() after the call to the init() function. This wipes all keyrings after umh_keys_init() is called. The best way to deal with this is to put the init() call just prior to the commit_creds() call, and pass the cred pointer to init(). That means that umh_keys_init() and suchlike can modify the credentials _before_ they are published and potentially in use by the rest of the system. This prevents request_key() from working as it is prevented from passing the session keyring it set up with the authorisation token to /sbin/request-key, and so the latter can't assume the authority to instantiate the key. This causes the in-kernel DNS resolver to fail with ENOKEY unconditionally. Signed-off-by: David Howells Acked-by: Eric Paris Tested-by: Jeff Layton Signed-off-by: Linus Torvalds --- fs/exec.c | 2 +- include/linux/kmod.h | 8 ++++---- kernel/kmod.c | 16 +++++++++------- security/keys/request_key.c | 3 +-- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 97e0d52d72fd..6075a1e727ae 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1996,7 +1996,7 @@ static void wait_for_dump_helpers(struct file *file) * is a special value that we use to trap recursive * core dumps */ -static int umh_pipe_setup(struct subprocess_info *info) +static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) { struct file *rp, *wp; struct fdtable *fdt; diff --git a/include/linux/kmod.h b/include/linux/kmod.h index d4a5c84c503d..0da38cf7db7b 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -45,7 +45,7 @@ static inline int request_module_nowait(const char *name, ...) { return -ENOSYS; #endif -struct key; +struct cred; struct file; enum umh_wait { @@ -62,7 +62,7 @@ struct subprocess_info { char **envp; enum umh_wait wait; int retval; - int (*init)(struct subprocess_info *info); + int (*init)(struct subprocess_info *info, struct cred *new); void (*cleanup)(struct subprocess_info *info); void *data; }; @@ -73,7 +73,7 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, /* Set various pieces of state into the subprocess_info structure */ void call_usermodehelper_setfns(struct subprocess_info *info, - int (*init)(struct subprocess_info *info), + int (*init)(struct subprocess_info *info, struct cred *new), void (*cleanup)(struct subprocess_info *info), void *data); @@ -87,7 +87,7 @@ void call_usermodehelper_freeinfo(struct subprocess_info *info); static inline int call_usermodehelper_fns(char *path, char **argv, char **envp, enum umh_wait wait, - int (*init)(struct subprocess_info *info), + int (*init)(struct subprocess_info *info, struct cred *new), void (*cleanup)(struct subprocess_info *), void *data) { struct subprocess_info *info; diff --git a/kernel/kmod.c b/kernel/kmod.c index ad6a81c58b44..47613dfb7b28 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -156,12 +156,6 @@ static int ____call_usermodehelper(void *data) */ set_user_nice(current, 0); - if (sub_info->init) { - retval = sub_info->init(sub_info); - if (retval) - goto fail; - } - retval = -ENOMEM; new = prepare_kernel_cred(current); if (!new) @@ -173,6 +167,14 @@ static int ____call_usermodehelper(void *data) new->cap_inheritable); spin_unlock(&umh_sysctl_lock); + if (sub_info->init) { + retval = sub_info->init(sub_info, new); + if (retval) { + abort_creds(new); + goto fail; + } + } + commit_creds(new); retval = kernel_execve(sub_info->path, @@ -388,7 +390,7 @@ EXPORT_SYMBOL(call_usermodehelper_setup); * context in which call_usermodehelper_exec is called. */ void call_usermodehelper_setfns(struct subprocess_info *info, - int (*init)(struct subprocess_info *info), + int (*init)(struct subprocess_info *info, struct cred *new), void (*cleanup)(struct subprocess_info *info), void *data) { diff --git a/security/keys/request_key.c b/security/keys/request_key.c index d31862e0aa1c..8e319a416eec 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -71,9 +71,8 @@ EXPORT_SYMBOL(complete_request_key); * This is called in context of freshly forked kthread before kernel_execve(), * so we can simply install the desired session_keyring at this point. */ -static int umh_keys_init(struct subprocess_info *info) +static int umh_keys_init(struct subprocess_info *info, struct cred *cred) { - struct cred *cred = (struct cred*)current_cred(); struct key *keyring = info->data; return install_session_keyring_to_cred(cred, keyring); From 7585717f304f5ed005cc4ad933a69aab3efbd136 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 13 Jun 2011 20:00:16 -0400 Subject: [PATCH 529/595] Btrfs: fix relocation races The recent commit to get rid of our trans_mutex introduced some races with block group relocation. The problem is that relocation needs to do some record keeping about each root, and it was relying on the transaction mutex to coordinate things in subtle ways. This fix adds a mutex just for the relocation code and makes sure it doesn't have a big impact on normal operations. The race is really fixed in btrfs_record_root_in_trans, which is where we step back and wait for the relocation code to finish accounting setup. Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 14 ++++++++ fs/btrfs/disk-io.c | 1 + fs/btrfs/relocation.c | 30 +++++++++++------ fs/btrfs/transaction.c | 73 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 105 insertions(+), 13 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 8490ee063709..a2c91a102b72 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -967,6 +967,12 @@ struct btrfs_fs_info { struct srcu_struct subvol_srcu; spinlock_t trans_lock; + /* + * the reloc mutex goes with the trans lock, it is taken + * during commit to protect us from the relocation code + */ + struct mutex reloc_mutex; + struct list_head trans_list; struct list_head hashers; struct list_head dead_roots; @@ -1172,6 +1178,14 @@ struct btrfs_root { u32 type; u64 highest_objectid; + + /* btrfs_record_root_in_trans is a multi-step process, + * and it can race with the balancing code. But the + * race is very small, and only the first time the root + * is added to each transaction. So in_trans_setup + * is used to tell us when more checks are required + */ + unsigned long in_trans_setup; int ref_cows; int track_dirty; int in_radix; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 20c111b3fa0d..0b2b4b759136 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1620,6 +1620,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, spin_lock_init(&fs_info->fs_roots_radix_lock); spin_lock_init(&fs_info->delayed_iput_lock); spin_lock_init(&fs_info->defrag_inodes_lock); + mutex_init(&fs_info->reloc_mutex); init_completion(&fs_info->kobj_unregister); fs_info->tree_root = tree_root; diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index f25b10a22a0a..086b1e6b8614 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1368,7 +1368,7 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, int ret; if (!root->reloc_root) - return 0; + goto out; reloc_root = root->reloc_root; root_item = &reloc_root->root_item; @@ -1390,6 +1390,8 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, ret = btrfs_update_root(trans, root->fs_info->tree_root, &reloc_root->root_key, root_item); BUG_ON(ret); + +out: return 0; } @@ -2142,10 +2144,11 @@ int prepare_to_merge(struct reloc_control *rc, int err) u64 num_bytes = 0; int ret; - spin_lock(&root->fs_info->trans_lock); + mutex_lock(&root->fs_info->reloc_mutex); rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2; rc->merging_rsv_size += rc->nodes_relocated * 2; - spin_unlock(&root->fs_info->trans_lock); + mutex_unlock(&root->fs_info->reloc_mutex); + again: if (!err) { num_bytes = rc->merging_rsv_size; @@ -2214,9 +2217,16 @@ int merge_reloc_roots(struct reloc_control *rc) int ret; again: root = rc->extent_root; - spin_lock(&root->fs_info->trans_lock); + + /* + * this serializes us with btrfs_record_root_in_transaction, + * we have to make sure nobody is in the middle of + * adding their roots to the list while we are + * doing this splice + */ + mutex_lock(&root->fs_info->reloc_mutex); list_splice_init(&rc->reloc_roots, &reloc_roots); - spin_unlock(&root->fs_info->trans_lock); + mutex_unlock(&root->fs_info->reloc_mutex); while (!list_empty(&reloc_roots)) { found = 1; @@ -3590,17 +3600,19 @@ int find_next_extent(struct btrfs_trans_handle *trans, static void set_reloc_control(struct reloc_control *rc) { struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; - spin_lock(&fs_info->trans_lock); + + mutex_lock(&fs_info->reloc_mutex); fs_info->reloc_ctl = rc; - spin_unlock(&fs_info->trans_lock); + mutex_unlock(&fs_info->reloc_mutex); } static void unset_reloc_control(struct reloc_control *rc) { struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; - spin_lock(&fs_info->trans_lock); + + mutex_lock(&fs_info->reloc_mutex); fs_info->reloc_ctl = NULL; - spin_unlock(&fs_info->trans_lock); + mutex_unlock(&fs_info->reloc_mutex); } static int check_extent_flags(u64 flags) diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 2b3590b9fe98..833996a0c628 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -126,28 +126,85 @@ static noinline int join_transaction(struct btrfs_root *root, int nofail) * to make sure the old root from before we joined the transaction is deleted * when the transaction commits */ -int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, +static int record_root_in_trans(struct btrfs_trans_handle *trans, struct btrfs_root *root) { if (root->ref_cows && root->last_trans < trans->transid) { WARN_ON(root == root->fs_info->extent_root); WARN_ON(root->commit_root != root->node); + /* + * see below for in_trans_setup usage rules + * we have the reloc mutex held now, so there + * is only one writer in this function + */ + root->in_trans_setup = 1; + + /* make sure readers find in_trans_setup before + * they find our root->last_trans update + */ + smp_wmb(); + spin_lock(&root->fs_info->fs_roots_radix_lock); if (root->last_trans == trans->transid) { spin_unlock(&root->fs_info->fs_roots_radix_lock); return 0; } - root->last_trans = trans->transid; radix_tree_tag_set(&root->fs_info->fs_roots_radix, (unsigned long)root->root_key.objectid, BTRFS_ROOT_TRANS_TAG); spin_unlock(&root->fs_info->fs_roots_radix_lock); + root->last_trans = trans->transid; + + /* this is pretty tricky. We don't want to + * take the relocation lock in btrfs_record_root_in_trans + * unless we're really doing the first setup for this root in + * this transaction. + * + * Normally we'd use root->last_trans as a flag to decide + * if we want to take the expensive mutex. + * + * But, we have to set root->last_trans before we + * init the relocation root, otherwise, we trip over warnings + * in ctree.c. The solution used here is to flag ourselves + * with root->in_trans_setup. When this is 1, we're still + * fixing up the reloc trees and everyone must wait. + * + * When this is zero, they can trust root->last_trans and fly + * through btrfs_record_root_in_trans without having to take the + * lock. smp_wmb() makes sure that all the writes above are + * done before we pop in the zero below + */ btrfs_init_reloc_root(trans, root); + smp_wmb(); + root->in_trans_setup = 0; } return 0; } + +int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, + struct btrfs_root *root) +{ + if (!root->ref_cows) + return 0; + + /* + * see record_root_in_trans for comments about in_trans_setup usage + * and barriers + */ + smp_rmb(); + if (root->last_trans == trans->transid && + !root->in_trans_setup) + return 0; + + mutex_lock(&root->fs_info->reloc_mutex); + record_root_in_trans(trans, root); + mutex_unlock(&root->fs_info->reloc_mutex); + + return 0; +} + /* wait for commit against the current transaction to become unblocked * when this is done, it is safe to start a new transaction, but the current * transaction might not be fully on disk. @@ -882,7 +939,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, parent = dget_parent(dentry); parent_inode = parent->d_inode; parent_root = BTRFS_I(parent_inode)->root; - btrfs_record_root_in_trans(trans, parent_root); + record_root_in_trans(trans, parent_root); /* * insert the directory item @@ -900,7 +957,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, ret = btrfs_update_inode(trans, parent_root, parent_inode); BUG_ON(ret); - btrfs_record_root_in_trans(trans, root); + record_root_in_trans(trans, root); btrfs_set_root_last_snapshot(&root->root_item, trans->transid); memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); btrfs_check_and_init_root_item(new_root_item); @@ -1247,6 +1304,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, } while (atomic_read(&cur_trans->num_writers) > 1 || (should_grow && cur_trans->num_joined != joined)); + /* + * the reloc mutex makes sure that we stop + * the balancing code from coming in and moving + * extents around in the middle of the commit + */ + mutex_lock(&root->fs_info->reloc_mutex); + ret = create_pending_snapshots(trans, root->fs_info); BUG_ON(ret); @@ -1312,6 +1376,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, root->fs_info->running_transaction = NULL; root->fs_info->trans_no_join = 0; spin_unlock(&root->fs_info->trans_lock); + mutex_unlock(&root->fs_info->reloc_mutex); wake_up(&root->fs_info->transaction_wait); From 3ed4498caf381a73d6259d3ffacc914b17a507ec Mon Sep 17 00:00:00 2001 From: David Sterba Date: Mon, 13 Jun 2011 17:54:22 +0000 Subject: [PATCH 530/595] btrfs: fix dereference of ERR_PTR value smatch reports: btrfs_recover_log_trees error: 'wc.replay_dest' dereferencing possible ERR_PTR() Signed-off-by: David Sterba Signed-off-by: Chris Mason --- fs/btrfs/tree-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 592396c6dc47..4ce8a9f41d1e 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -3177,7 +3177,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) tmp_key.offset = (u64)-1; wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key); - BUG_ON(!wc.replay_dest); + BUG_ON(IS_ERR_OR_NULL(wc.replay_dest)); wc.replay_dest->log_root = log; btrfs_record_root_in_trans(trans, wc.replay_dest); From 9fe6a50fb764f508dd2de47a66e62e51388791fb Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 16 Jun 2011 09:04:57 +0000 Subject: [PATCH 531/595] btrfs: Remove unused sysfs code Removes code no longer used. The sysfs file itself is kept, because the btrfs developers expressed interest in putting new entries to sysfs. Signed-off-by: Maarten Lankhorst Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 1 - fs/btrfs/disk-io.c | 1 - fs/btrfs/sysfs.c | 146 --------------------------------------------- 3 files changed, 148 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index a2c91a102b72..8e948ec1ee6b 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1195,7 +1195,6 @@ struct btrfs_root { struct btrfs_key defrag_max; int defrag_running; char *name; - int in_sysfs; /* the dirty list is only used by non-reference counted roots */ struct list_head dirty_list; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 0b2b4b759136..c25ef5a0ccd6 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1044,7 +1044,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, root->last_trans = 0; root->highest_objectid = 0; root->name = NULL; - root->in_sysfs = 0; root->inode_tree = RB_ROOT; INIT_RADIX_TREE(&root->delayed_nodes_tree, GFP_ATOMIC); root->block_rsv = NULL; diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index c3c223ae6691..daac9ae6d731 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -28,152 +28,6 @@ #include "disk-io.h" #include "transaction.h" -static ssize_t root_blocks_used_show(struct btrfs_root *root, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%llu\n", - (unsigned long long)btrfs_root_used(&root->root_item)); -} - -static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%llu\n", - (unsigned long long)btrfs_root_limit(&root->root_item)); -} - -static ssize_t super_blocks_used_show(struct btrfs_fs_info *fs, char *buf) -{ - - return snprintf(buf, PAGE_SIZE, "%llu\n", - (unsigned long long)btrfs_super_bytes_used(&fs->super_copy)); -} - -static ssize_t super_total_blocks_show(struct btrfs_fs_info *fs, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%llu\n", - (unsigned long long)btrfs_super_total_bytes(&fs->super_copy)); -} - -static ssize_t super_blocksize_show(struct btrfs_fs_info *fs, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%llu\n", - (unsigned long long)btrfs_super_sectorsize(&fs->super_copy)); -} - -/* this is for root attrs (subvols/snapshots) */ -struct btrfs_root_attr { - struct attribute attr; - ssize_t (*show)(struct btrfs_root *, char *); - ssize_t (*store)(struct btrfs_root *, const char *, size_t); -}; - -#define ROOT_ATTR(name, mode, show, store) \ -static struct btrfs_root_attr btrfs_root_attr_##name = __ATTR(name, mode, \ - show, store) - -ROOT_ATTR(blocks_used, 0444, root_blocks_used_show, NULL); -ROOT_ATTR(block_limit, 0644, root_block_limit_show, NULL); - -static struct attribute *btrfs_root_attrs[] = { - &btrfs_root_attr_blocks_used.attr, - &btrfs_root_attr_block_limit.attr, - NULL, -}; - -/* this is for super attrs (actual full fs) */ -struct btrfs_super_attr { - struct attribute attr; - ssize_t (*show)(struct btrfs_fs_info *, char *); - ssize_t (*store)(struct btrfs_fs_info *, const char *, size_t); -}; - -#define SUPER_ATTR(name, mode, show, store) \ -static struct btrfs_super_attr btrfs_super_attr_##name = __ATTR(name, mode, \ - show, store) - -SUPER_ATTR(blocks_used, 0444, super_blocks_used_show, NULL); -SUPER_ATTR(total_blocks, 0444, super_total_blocks_show, NULL); -SUPER_ATTR(blocksize, 0444, super_blocksize_show, NULL); - -static struct attribute *btrfs_super_attrs[] = { - &btrfs_super_attr_blocks_used.attr, - &btrfs_super_attr_total_blocks.attr, - &btrfs_super_attr_blocksize.attr, - NULL, -}; - -static ssize_t btrfs_super_attr_show(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, - super_kobj); - struct btrfs_super_attr *a = container_of(attr, - struct btrfs_super_attr, - attr); - - return a->show ? a->show(fs, buf) : 0; -} - -static ssize_t btrfs_super_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, size_t len) -{ - struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, - super_kobj); - struct btrfs_super_attr *a = container_of(attr, - struct btrfs_super_attr, - attr); - - return a->store ? a->store(fs, buf, len) : 0; -} - -static ssize_t btrfs_root_attr_show(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct btrfs_root *root = container_of(kobj, struct btrfs_root, - root_kobj); - struct btrfs_root_attr *a = container_of(attr, - struct btrfs_root_attr, - attr); - - return a->show ? a->show(root, buf) : 0; -} - -static ssize_t btrfs_root_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, size_t len) -{ - struct btrfs_root *root = container_of(kobj, struct btrfs_root, - root_kobj); - struct btrfs_root_attr *a = container_of(attr, - struct btrfs_root_attr, - attr); - return a->store ? a->store(root, buf, len) : 0; -} - -static void btrfs_super_release(struct kobject *kobj) -{ - struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, - super_kobj); - complete(&fs->kobj_unregister); -} - -static void btrfs_root_release(struct kobject *kobj) -{ - struct btrfs_root *root = container_of(kobj, struct btrfs_root, - root_kobj); - complete(&root->kobj_unregister); -} - -static const struct sysfs_ops btrfs_super_attr_ops = { - .show = btrfs_super_attr_show, - .store = btrfs_super_attr_store, -}; - -static const struct sysfs_ops btrfs_root_attr_ops = { - .show = btrfs_root_attr_show, - .store = btrfs_root_attr_store, -}; - /* /sys/fs/btrfs/ entry */ static struct kset *btrfs_kset; From 19fd294957e426bfdd8e19085096467ec18df5c4 Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Wed, 15 Jun 2011 10:47:30 +0000 Subject: [PATCH 532/595] btrfs: fix wrong reservation when doing delayed inode operations We have migrated the space for the delayed inode items from trans_block_rsv to global_block_rsv, but we forgot to set trans->block_rsv to global_block_rsv when we doing delayed inode operations, and the following Oops happened: [ 9792.654889] ------------[ cut here ]------------ [ 9792.654898] WARNING: at fs/btrfs/extent-tree.c:5681 btrfs_alloc_free_block+0xca/0x27c [btrfs]() [ 9792.654899] Hardware name: To Be Filled By O.E.M. [ 9792.654900] Modules linked in: btrfs zlib_deflate libcrc32c ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 ip6table_filter ip6_tables arc4 rt61pci rt2x00pci rt2x00lib snd_hda_codec_hdmi mac80211 snd_hda_codec_realtek cfg80211 snd_hda_intel edac_core snd_seq rfkill pcspkr serio_raw snd_hda_codec eeprom_93cx6 edac_mce_amd sp5100_tco i2c_piix4 k10temp snd_hwdep snd_seq_device snd_pcm floppy r8169 xhci_hcd mii snd_timer snd soundcore snd_page_alloc ipv6 firewire_ohci pata_acpi ata_generic firewire_core pata_via crc_itu_t radeon ttm drm_kms_helper drm i2c_algo_bit i2c_core [last unloaded: scsi_wait_scan] [ 9792.654919] Pid: 2762, comm: rm Tainted: G W 2.6.39+ #1 [ 9792.654920] Call Trace: [ 9792.654922] [] warn_slowpath_common+0x83/0x9b [ 9792.654925] [] warn_slowpath_null+0x1a/0x1c [ 9792.654933] [] btrfs_alloc_free_block+0xca/0x27c [btrfs] [ 9792.654945] [] ? map_extent_buffer+0x6e/0xa8 [btrfs] [ 9792.654953] [] __btrfs_cow_block+0xfc/0x30c [btrfs] [ 9792.654963] [] ? btrfs_buffer_uptodate+0x47/0x58 [btrfs] [ 9792.654970] [] ? read_block_for_search+0x94/0x368 [btrfs] [ 9792.654978] [] btrfs_cow_block+0xfe/0x146 [btrfs] [ 9792.654986] [] btrfs_search_slot+0x14d/0x4b6 [btrfs] [ 9792.654997] [] ? map_extent_buffer+0x6e/0xa8 [btrfs] [ 9792.655022] [] btrfs_lookup_inode+0x2f/0x8f [btrfs] [ 9792.655025] [] ? _cond_resched+0xe/0x22 [ 9792.655027] [] ? mutex_lock+0x29/0x50 [ 9792.655039] [] btrfs_update_delayed_inode+0x72/0x137 [btrfs] [ 9792.655051] [] btrfs_run_delayed_items+0x90/0xdb [btrfs] [ 9792.655062] [] btrfs_commit_transaction+0x228/0x654 [btrfs] [ 9792.655064] [] ? remove_wait_queue+0x3a/0x3a [ 9792.655075] [] btrfs_evict_inode+0x14d/0x202 [btrfs] [ 9792.655077] [] evict+0x71/0x111 [ 9792.655079] [] iput+0x12a/0x132 [ 9792.655081] [] do_unlinkat+0x106/0x155 [ 9792.655083] [] ? path_put+0x1f/0x23 [ 9792.655085] [] ? audit_syscall_entry+0x145/0x171 [ 9792.655087] [] ? putname+0x34/0x36 [ 9792.655090] [] sys_unlinkat+0x29/0x2b [ 9792.655092] [] system_call_fastpath+0x16/0x1b [ 9792.655093] ---[ end trace 02b696eb02b3f768 ]--- This patch fix it by setting the reservation of the transaction handle to the correct one. Reported-by: Josef Bacik Signed-off-by: Miao Xie Signed-off-by: Chris Mason --- fs/btrfs/delayed-inode.c | 25 ++++++++++++++++++++----- fs/btrfs/delayed-inode.h | 1 - 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 6462c29d2d37..fc515b787e8c 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -297,7 +297,6 @@ struct btrfs_delayed_item *btrfs_alloc_delayed_item(u32 data_len) item->data_len = data_len; item->ins_or_del = 0; item->bytes_reserved = 0; - item->block_rsv = NULL; item->delayed_node = NULL; atomic_set(&item->refs, 1); } @@ -593,10 +592,8 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, num_bytes = btrfs_calc_trans_metadata_size(root, 1); ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); - if (!ret) { + if (!ret) item->bytes_reserved = num_bytes; - item->block_rsv = dst_rsv; - } return ret; } @@ -604,10 +601,13 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, static void btrfs_delayed_item_release_metadata(struct btrfs_root *root, struct btrfs_delayed_item *item) { + struct btrfs_block_rsv *rsv; + if (!item->bytes_reserved) return; - btrfs_block_rsv_release(root, item->block_rsv, + rsv = &root->fs_info->global_block_rsv; + btrfs_block_rsv_release(root, rsv, item->bytes_reserved); } @@ -1014,6 +1014,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans, struct btrfs_delayed_root *delayed_root; struct btrfs_delayed_node *curr_node, *prev_node; struct btrfs_path *path; + struct btrfs_block_rsv *block_rsv; int ret = 0; path = btrfs_alloc_path(); @@ -1021,6 +1022,9 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans, return -ENOMEM; path->leave_spinning = 1; + block_rsv = trans->block_rsv; + trans->block_rsv = &root->fs_info->global_block_rsv; + delayed_root = btrfs_get_delayed_root(root); curr_node = btrfs_first_delayed_node(delayed_root); @@ -1045,6 +1049,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans, } btrfs_free_path(path); + trans->block_rsv = block_rsv; return ret; } @@ -1052,6 +1057,7 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, struct btrfs_delayed_node *node) { struct btrfs_path *path; + struct btrfs_block_rsv *block_rsv; int ret; path = btrfs_alloc_path(); @@ -1059,6 +1065,9 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, return -ENOMEM; path->leave_spinning = 1; + block_rsv = trans->block_rsv; + trans->block_rsv = &node->root->fs_info->global_block_rsv; + ret = btrfs_insert_delayed_items(trans, path, node->root, node); if (!ret) ret = btrfs_delete_delayed_items(trans, path, node->root, node); @@ -1066,6 +1075,7 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, ret = btrfs_update_delayed_inode(trans, node->root, path, node); btrfs_free_path(path); + trans->block_rsv = block_rsv; return ret; } @@ -1116,6 +1126,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) struct btrfs_path *path; struct btrfs_delayed_node *delayed_node = NULL; struct btrfs_root *root; + struct btrfs_block_rsv *block_rsv; unsigned long nr = 0; int need_requeue = 0; int ret; @@ -1134,6 +1145,9 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) if (IS_ERR(trans)) goto free_path; + block_rsv = trans->block_rsv; + trans->block_rsv = &root->fs_info->global_block_rsv; + ret = btrfs_insert_delayed_items(trans, path, root, delayed_node); if (!ret) ret = btrfs_delete_delayed_items(trans, path, root, @@ -1176,6 +1190,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) nr = trans->blocks_used; + trans->block_rsv = block_rsv; btrfs_end_transaction_dmeta(trans, root); __btrfs_btree_balance_dirty(root, nr); free_path: diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index eb7d240aa648..cb79b6771e82 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -75,7 +75,6 @@ struct btrfs_delayed_item { struct list_head tree_list; /* used for batch insert/delete items */ struct list_head readdir_list; /* used for readdir items */ u64 bytes_reserved; - struct btrfs_block_rsv *block_rsv; struct btrfs_delayed_node *delayed_node; atomic_t refs; int ins_or_del; From 35a30d7ce54e087d8025a725d4e5a2fdee723a9f Mon Sep 17 00:00:00 2001 From: David Sterba Date: Mon, 13 Jun 2011 15:18:23 +0000 Subject: [PATCH 533/595] btrfs: fix uninitialized return value When allocation fails in btrfs_read_fs_root_no_name, ret is not set although it is returned, holding a garbage value. Signed-off-by: David Sterba Reviewed-by: Li Zefan Signed-off-by: Chris Mason --- fs/btrfs/disk-io.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c25ef5a0ccd6..1ac8db5dc0a3 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1299,12 +1299,12 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, return root; root->free_ino_ctl = kzalloc(sizeof(*root->free_ino_ctl), GFP_NOFS); - if (!root->free_ino_ctl) - goto fail; root->free_ino_pinned = kzalloc(sizeof(*root->free_ino_pinned), GFP_NOFS); - if (!root->free_ino_pinned) + if (!root->free_ino_pinned || !root->free_ino_ctl) { + ret = -ENOMEM; goto fail; + } btrfs_init_free_ino_ctl(root); mutex_init(&root->fs_commit_mutex); From cab758ef30e0e40f783627abc4b66d1b48fecd49 Mon Sep 17 00:00:00 2001 From: Clive Stubbings Date: Thu, 16 Jun 2011 22:30:39 +0000 Subject: [PATCH 534/595] fs_enet: fix freescale FCC ethernet dp buffer alignment The RIPTR and TIPTR (receive/transmit internal temporary data pointer), used by microcode as a temporary buffer for data, must be 32-byte aligned according to the RM for MPC8247. Tested on mgcoge. Signed-off-by: Clive Stubbings Signed-off-by: Holger Brunck cc: Pantelis Antoniou cc: Vitaly Bordug cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- drivers/net/fs_enet/mac-fcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index 7a84e45487e8..7583a9572bcc 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c @@ -105,7 +105,7 @@ static int do_pd_setup(struct fs_enet_private *fep) goto out_ep; fep->fcc.mem = (void __iomem *)cpm2_immr; - fpi->dpram_offset = cpm_dpalloc(128, 8); + fpi->dpram_offset = cpm_dpalloc(128, 32); if (IS_ERR_VALUE(fpi->dpram_offset)) { ret = fpi->dpram_offset; goto out_fcccp; From 1eddceadb0d6441cd39b2c38705a8f5fec86e770 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 17 Jun 2011 03:45:15 +0000 Subject: [PATCH 535/595] net: rfs: enable RFS before first data packet is received MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le jeudi 16 juin 2011 à 23:38 -0400, David Miller a écrit : > From: Ben Hutchings > Date: Fri, 17 Jun 2011 00:50:46 +0100 > > > On Wed, 2011-06-15 at 04:15 +0200, Eric Dumazet wrote: > >> @@ -1594,6 +1594,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) > >> goto discard; > >> > >> if (nsk != sk) { > >> + sock_rps_save_rxhash(nsk, skb->rxhash); > >> if (tcp_child_process(sk, nsk, skb)) { > >> rsk = nsk; > >> goto reset; > >> > > > > I haven't tried this, but it looks reasonable to me. > > > > What about IPv6? The logic in tcp_v6_do_rcv() looks very similar. > > Indeed ipv6 side needs the same fix. > > Eric please add that part and resubmit. And in fact I might stick > this into net-2.6 instead of net-next-2.6 > OK, here is the net-2.6 based one then, thanks ! [PATCH v2] net: rfs: enable RFS before first data packet is received First packet received on a passive tcp flow is not correctly RFS steered. One sock_rps_record_flow() call is missing in inet_accept() But before that, we also must record rxhash when child socket is setup. Signed-off-by: Eric Dumazet CC: Tom Herbert CC: Ben Hutchings CC: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 1 + net/ipv4/tcp_ipv4.c | 1 + net/ipv6/tcp_ipv6.c | 1 + 3 files changed, 3 insertions(+) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 9c1926027a26..eae1f676f870 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -676,6 +676,7 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags) lock_sock(sk2); + sock_rps_record_flow(sk2); WARN_ON(!((1 << sk2->sk_state) & (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE))); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index a7d6671e33b8..708dc203b034 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1589,6 +1589,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) goto discard; if (nsk != sk) { + sock_rps_save_rxhash(nsk, skb->rxhash); if (tcp_child_process(sk, nsk, skb)) { rsk = nsk; goto reset; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d1fd28711ba5..87551ca568cd 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1644,6 +1644,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) * the new socket.. */ if(nsk != sk) { + sock_rps_save_rxhash(nsk, skb->rxhash); if (tcp_child_process(sk, nsk, skb)) goto reset; if (opt_skb) From d0fd64c1de437bdf91c32d4f84a53fa4b2150348 Mon Sep 17 00:00:00 2001 From: Pavel Shved Date: Fri, 17 Jun 2011 06:25:10 +0000 Subject: [PATCH 536/595] farsync: add module_put to error path in fst_open() The fst_open() function, after a successful try_module_get() may return an error code if hdlc_open() returns it. However, it does not put the module on this error path. This patch adds the necessary module_put() call. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Pavel Shved Signed-off-by: David S. Miller --- drivers/net/wan/farsync.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index e050bd65e037..777d1a4e81b2 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -2203,8 +2203,10 @@ fst_open(struct net_device *dev) if (port->mode != FST_RAW) { err = hdlc_open(dev); - if (err) + if (err) { + module_put(THIS_MODULE); return err; + } } fst_openport(port); From 2f9381e98471837b631743270de988e78aad1f96 Mon Sep 17 00:00:00 2001 From: Pavel Shved Date: Fri, 17 Jun 2011 06:25:11 +0000 Subject: [PATCH 537/595] gigaset: call module_put before restart of if_open() if_open() calls try_module_get(), and after an attempt to lock a mutex the if_open() function may return -ERESTARTSYS without putting the module. Then, when if_open() is executed again, try_module_get() is called making the reference counter of THIS_MODULE greater than one at successful exit from if_open(). The if_close() function puts the module only once, and as a result it can't be unloaded. This patch adds module_put call before the return from if_open(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Pavel Shved Signed-off-by: David S. Miller --- drivers/isdn/gigaset/interface.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 59de638225fe..e35058bcd7b9 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -156,8 +156,10 @@ static int if_open(struct tty_struct *tty, struct file *filp) if (!cs || !try_module_get(cs->driver->owner)) return -ENODEV; - if (mutex_lock_interruptible(&cs->mutex)) + if (mutex_lock_interruptible(&cs->mutex)) { + module_put(cs->driver->owner); return -ERESTARTSYS; + } tty->driver_data = cs; ++cs->open_count; From eeb1497277d6b1a0a34ed36b97e18f2bd7d6de0d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 17 Jun 2011 16:25:39 -0400 Subject: [PATCH 538/595] inet_diag: fix inet_diag_bc_audit() A malicious user or buggy application can inject code and trigger an infinite loop in inet_diag_bc_audit() Also make sure each instruction is aligned on 4 bytes boundary, to avoid unaligned accesses. Reported-by: Dan Rosenberg Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/inet_diag.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 6ffe94ca5bc9..3267d3898437 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -437,7 +437,7 @@ static int valid_cc(const void *bc, int len, int cc) return 0; if (cc == len) return 1; - if (op->yes < 4) + if (op->yes < 4 || op->yes & 3) return 0; len -= op->yes; bc += op->yes; @@ -447,11 +447,11 @@ static int valid_cc(const void *bc, int len, int cc) static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) { - const unsigned char *bc = bytecode; + const void *bc = bytecode; int len = bytecode_len; while (len > 0) { - struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)bc; + const struct inet_diag_bc_op *op = bc; //printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len); switch (op->code) { @@ -462,22 +462,20 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) case INET_DIAG_BC_S_LE: case INET_DIAG_BC_D_GE: case INET_DIAG_BC_D_LE: - if (op->yes < 4 || op->yes > len + 4) - return -EINVAL; case INET_DIAG_BC_JMP: - if (op->no < 4 || op->no > len + 4) + if (op->no < 4 || op->no > len + 4 || op->no & 3) return -EINVAL; if (op->no < len && !valid_cc(bytecode, bytecode_len, len - op->no)) return -EINVAL; break; case INET_DIAG_BC_NOP: - if (op->yes < 4 || op->yes > len + 4) - return -EINVAL; break; default: return -EINVAL; } + if (op->yes < 4 || op->yes > len + 4 || op->yes & 3) + return -EINVAL; bc += op->yes; len -= op->yes; } From e999376f094162aa425ae749aa1df95ab928d010 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 17 Jun 2011 16:14:09 -0400 Subject: [PATCH 539/595] Btrfs: avoid delayed metadata items during commits Snapshot creation has two phases. One is the initial snapshot setup, and the second is done during commit, while nobody is allowed to modify the root we are snapshotting. The delayed metadata insertion code can break that rule, it does a delayed inode update on the inode of the parent of the snapshot, and delayed directory item insertion. This makes sure to run the pending delayed operations before we record the snapshot root, which avoids corruptions. Signed-off-by: Chris Mason --- fs/btrfs/delayed-inode.c | 7 +++++++ fs/btrfs/delayed-inode.h | 4 ++++ fs/btrfs/transaction.c | 27 +++++++++++++++++---------- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index fc515b787e8c..f1cbd028f7b3 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -1237,6 +1237,13 @@ static int btrfs_wq_run_delayed_node(struct btrfs_delayed_root *delayed_root, return 0; } +void btrfs_assert_delayed_root_empty(struct btrfs_root *root) +{ + struct btrfs_delayed_root *delayed_root; + delayed_root = btrfs_get_delayed_root(root); + WARN_ON(btrfs_first_delayed_node(delayed_root)); +} + void btrfs_balance_delayed_items(struct btrfs_root *root) { struct btrfs_delayed_root *delayed_root; diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index cb79b6771e82..d1a6a2915c66 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -137,4 +137,8 @@ int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent, /* for init */ int __init btrfs_delayed_inode_init(void); void btrfs_delayed_inode_exit(void); + +/* for debugging */ +void btrfs_assert_delayed_root_empty(struct btrfs_root *root); + #endif diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index c073d85e14f3..51dcec86757f 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -957,6 +957,15 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, ret = btrfs_update_inode(trans, parent_root, parent_inode); BUG_ON(ret); + /* + * pull in the delayed directory update + * and the delayed inode item + * otherwise we corrupt the FS during + * snapshot + */ + ret = btrfs_run_delayed_items(trans, root); + BUG_ON(ret); + record_root_in_trans(trans, root); btrfs_set_root_last_snapshot(&root->root_item, trans->transid); memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); @@ -1018,14 +1027,6 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, int ret; list_for_each_entry(pending, head, list) { - /* - * We must deal with the delayed items before creating - * snapshots, or we will create a snapthot with inconsistent - * information. - */ - ret = btrfs_run_delayed_items(trans, fs_info->fs_root); - BUG_ON(ret); - ret = create_pending_snapshot(trans, fs_info, pending); BUG_ON(ret); } @@ -1319,15 +1320,21 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, */ mutex_lock(&root->fs_info->reloc_mutex); - ret = create_pending_snapshots(trans, root->fs_info); + ret = btrfs_run_delayed_items(trans, root); BUG_ON(ret); - ret = btrfs_run_delayed_items(trans, root); + ret = create_pending_snapshots(trans, root->fs_info); BUG_ON(ret); ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); BUG_ON(ret); + /* + * make sure none of the code above managed to slip in a + * delayed item + */ + btrfs_assert_delayed_root_empty(root); + WARN_ON(cur_trans != trans->transaction); btrfs_scrub_pause(root); From 3744100e05c4e403ed21c99cd389c7e784664e4b Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 17 Jun 2011 22:58:54 +0200 Subject: [PATCH 540/595] r8169: fix static initializers. Signed-off-by: Francois Romieu --- drivers/net/r8169.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index ef1ce2ebeb4a..05d81780d1fd 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1621,7 +1621,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, * * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec */ - static const struct { + static const struct rtl_mac_info { u32 mask; u32 val; int mac_version; @@ -1689,7 +1689,8 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, /* Catch-all */ { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }, *p = mac_info; + }; + const struct rtl_mac_info *p = mac_info; u32 reg; reg = RTL_R32(TxConfig); @@ -3681,7 +3682,7 @@ static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) { - static const struct { + static const struct rtl_cfg2_info { u32 mac_version; u32 clk; u32 val; @@ -3690,7 +3691,8 @@ static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; + }; + const struct rtl_cfg2_info *p = cfg2_info; unsigned int i; u32 clk; From 650f156775c2638cc02ed7df31186a09ba79666a Mon Sep 17 00:00:00 2001 From: Jeff Ohlstein Date: Fri, 17 Jun 2011 13:55:38 -0700 Subject: [PATCH 541/595] msm: timer: compensate for timer shift in msm_read_timer_count Some msm targets have timers whose lower bits are unreliable. So, we present our timers as lower frequency than they actually are, and ignore the bottom 5 bits on such targets. This compensation was erroneously removed from the msm_read_timer_count function, so restore it. This was broken by 94790ec25 "msm: timer: SMP timer support for msm". Signed-off-by: Jeff Ohlstein --- arch/arm/mach-msm/timer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 9bfdd5ad2441..2232032181be 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -102,7 +102,11 @@ static cycle_t msm_read_timer_count(struct clocksource *cs) { struct msm_clock *clk = container_of(cs, struct msm_clock, clocksource); - return readl(clk->global_counter); + /* + * Shift timer count down by a constant due to unreliable lower bits + * on some targets. + */ + return readl(clk->global_counter) >> clk->shift; } static struct msm_clock *clockevent_to_clock(struct clock_event_device *evt) From 498e720b96379d8ee9c294950a01534a73defcf3 Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Fri, 17 Jun 2011 11:32:19 -0700 Subject: [PATCH 542/595] drm/i915: Fix gen6 (SNB) missed BLT ring interrupts. The failure appeared in dmesg as: [drm:i915_hangcheck_ring_idle] *ERROR* Hangcheck timer elapsed... blt ring idle [waiting on 35064155, at 35064155], missed IRQ? This works around that problem on by making the blitter command streamer write interrupt state to the Hardware Status Page when a MI_USER_INTERRUPT command is decoded, which appears to force the seqno out to memory before the interrupt happens. v1->v2: Moved to prior interrupt handler installation and RMW flags as per feedback. v2->v3: Removed RMW of flags (by anholt) Cc: stable@kernel.org Signed-off-by: Daniel J Blueman Signed-off-by: Eric Anholt Tested-by: Chris Wilson [v1] Tested-by: Eric Anholt [v1,v3] (incidence of the bug with a testcase went from avg 2/1000 to 0/12651 in the latest test run (plus more for v1)) Tested-by: Kenneth Graunke [v1] Tested-by: Robert Hooker [v1] Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=33394 Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_irq.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b9fafe3b045b..9e34a1abeb61 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1740,6 +1740,16 @@ void ironlake_irq_preinstall(struct drm_device *dev) INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); I915_WRITE(HWSTAM, 0xeffe); + if (IS_GEN6(dev)) { + /* Workaround stalls observed on Sandy Bridge GPUs by + * making the blitter command streamer generate a + * write to the Hardware Status Page for + * MI_USER_INTERRUPT. This appears to serialize the + * previous seqno write out before the interrupt + * happens. + */ + I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT); + } /* XXX hotplug from PCH */ From bb4aa39676f73b4657b3edd893ae83881c430c0c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 16 Jun 2011 20:44:51 -0700 Subject: [PATCH 543/595] mm: avoid repeated anon_vma lock/unlock sequences in anon_vma_clone() In anon_vma_clone() we traverse the vma->anon_vma_chain of the source vma, locking the anon_vma for each entry. But they are all going to have the same root entry, which means that we're locking and unlocking the same lock over and over again. Which is expensive in locked operations, but can get _really_ expensive when that root entry sees any kind of lock contention. In fact, Tim Chen reports a big performance regression due to this: when we switched to use a mutex instead of a spinlock, the contention case gets much worse. So to alleviate this all, this commit creates a small helper function (lock_anon_vma_root()) that can be used to take the lock just once rather than taking and releasing it over and over again. We still have the same "take the lock and release" it behavior in the exit path (in unlink_anon_vmas()), but that one is a bit harder to fix since we're actually freeing the anon_vma entries as we go, and that will touch the lock too. Reported-and-tested-by: Tim Chen Tested-by: Hugh Dickins Cc: Peter Zijlstra Cc: Andi Kleen Signed-off-by: Linus Torvalds --- mm/rmap.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/mm/rmap.c b/mm/rmap.c index 0eb463ea88dd..f286697c61dc 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -200,6 +200,32 @@ int anon_vma_prepare(struct vm_area_struct *vma) return -ENOMEM; } +/* + * This is a useful helper function for locking the anon_vma root as + * we traverse the vma->anon_vma_chain, looping over anon_vma's that + * have the same vma. + * + * Such anon_vma's should have the same root, so you'd expect to see + * just a single mutex_lock for the whole traversal. + */ +static inline struct anon_vma *lock_anon_vma_root(struct anon_vma *root, struct anon_vma *anon_vma) +{ + struct anon_vma *new_root = anon_vma->root; + if (new_root != root) { + if (WARN_ON_ONCE(root)) + mutex_unlock(&root->mutex); + root = new_root; + mutex_lock(&root->mutex); + } + return root; +} + +static inline void unlock_anon_vma_root(struct anon_vma *root) +{ + if (root) + mutex_unlock(&root->mutex); +} + static void anon_vma_chain_link(struct vm_area_struct *vma, struct anon_vma_chain *avc, struct anon_vma *anon_vma) @@ -208,13 +234,11 @@ static void anon_vma_chain_link(struct vm_area_struct *vma, avc->anon_vma = anon_vma; list_add(&avc->same_vma, &vma->anon_vma_chain); - anon_vma_lock(anon_vma); /* * It's critical to add new vmas to the tail of the anon_vma, * see comment in huge_memory.c:__split_huge_page(). */ list_add_tail(&avc->same_anon_vma, &anon_vma->head); - anon_vma_unlock(anon_vma); } /* @@ -224,16 +248,23 @@ static void anon_vma_chain_link(struct vm_area_struct *vma, int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src) { struct anon_vma_chain *avc, *pavc; + struct anon_vma *root = NULL; list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) { + struct anon_vma *anon_vma; + avc = anon_vma_chain_alloc(); if (!avc) goto enomem_failure; - anon_vma_chain_link(dst, avc, pavc->anon_vma); + anon_vma = pavc->anon_vma; + root = lock_anon_vma_root(root, anon_vma); + anon_vma_chain_link(dst, avc, anon_vma); } + unlock_anon_vma_root(root); return 0; enomem_failure: + unlock_anon_vma_root(root); unlink_anon_vmas(dst); return -ENOMEM; } @@ -280,7 +311,9 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) get_anon_vma(anon_vma->root); /* Mark this anon_vma as the one where our new (COWed) pages go. */ vma->anon_vma = anon_vma; + anon_vma_lock(anon_vma); anon_vma_chain_link(vma, avc, anon_vma); + anon_vma_unlock(anon_vma); return 0; From eee2acbae95555006307395d8a6c91452d62851d Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 17 Jun 2011 13:54:23 +0200 Subject: [PATCH 544/595] mm: avoid repeated anon_vma lock/unlock sequences in unlink_anon_vmas() This matches the anon_vma_clone() case, and uses the same lock helper functions. Because of the need to potentially release the anon_vma's, it's a bit more complex, though. We traverse the 'vma->anon_vma_chain' in two phases: the first loop gets the anon_vma lock (with the helper function that only takes the lock once for the whole loop), and removes any entries that don't need any more processing. The second phase just traverses the remaining list entries (without holding the anon_vma lock), and does any actual freeing of the anon_vma's that is required. Signed-off-by: Peter Zijlstra Tested-by: Hugh Dickins Tested-by: Tim Chen Cc: Andi Kleen Signed-off-by: Linus Torvalds --- mm/rmap.c | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/mm/rmap.c b/mm/rmap.c index f286697c61dc..68756a77ef87 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -324,36 +324,43 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) return -ENOMEM; } -static void anon_vma_unlink(struct anon_vma_chain *anon_vma_chain) -{ - struct anon_vma *anon_vma = anon_vma_chain->anon_vma; - int empty; - - /* If anon_vma_fork fails, we can get an empty anon_vma_chain. */ - if (!anon_vma) - return; - - anon_vma_lock(anon_vma); - list_del(&anon_vma_chain->same_anon_vma); - - /* We must garbage collect the anon_vma if it's empty */ - empty = list_empty(&anon_vma->head); - anon_vma_unlock(anon_vma); - - if (empty) - put_anon_vma(anon_vma); -} - void unlink_anon_vmas(struct vm_area_struct *vma) { struct anon_vma_chain *avc, *next; + struct anon_vma *root = NULL; /* * Unlink each anon_vma chained to the VMA. This list is ordered * from newest to oldest, ensuring the root anon_vma gets freed last. */ list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) { - anon_vma_unlink(avc); + struct anon_vma *anon_vma = avc->anon_vma; + + root = lock_anon_vma_root(root, anon_vma); + list_del(&avc->same_anon_vma); + + /* + * Leave empty anon_vmas on the list - we'll need + * to free them outside the lock. + */ + if (list_empty(&anon_vma->head)) + continue; + + list_del(&avc->same_vma); + anon_vma_chain_free(avc); + } + unlock_anon_vma_root(root); + + /* + * Iterate the list once more, it now only contains empty and unlinked + * anon_vmas, destroy them. Could not do before due to __put_anon_vma() + * needing to acquire the anon_vma->root->mutex. + */ + list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) { + struct anon_vma *anon_vma = avc->anon_vma; + + put_anon_vma(anon_vma); + list_del(&avc->same_vma); anon_vma_chain_free(avc); } From dd34739c03f2f9a79403d33419c2e61e11b4c403 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 17 Jun 2011 19:05:36 -0700 Subject: [PATCH 545/595] mm: avoid anon_vma_chain allocation under anon_vma lock Hugh Dickins points out that lockdep (correctly) spots a potential deadlock on the anon_vma lock, because we now do a GFP_KERNEL allocation of anon_vma_chain while doing anon_vma_clone(). The problem is that page reclaim will want to take the anon_vma lock of any anonymous pages that it will try to reclaim. So re-organize the code in anon_vma_clone() slightly: first do just a GFP_NOWAIT allocation, which will usually work fine. But if that fails, let's just drop the lock and re-do the allocation, now with GFP_KERNEL. End result: not only do we avoid the locking problem, this also ends up getting better concurrency in case the allocation does need to block. Tim Chen reports that with all these anon_vma locking tweaks, we're now almost back up to the spinlock performance. Reported-and-tested-by: Hugh Dickins Tested-by: Tim Chen Cc: Peter Zijlstra Cc: Andi Kleen Signed-off-by: Linus Torvalds --- mm/rmap.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/mm/rmap.c b/mm/rmap.c index 68756a77ef87..27dfd3b82b0f 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -112,9 +112,9 @@ static inline void anon_vma_free(struct anon_vma *anon_vma) kmem_cache_free(anon_vma_cachep, anon_vma); } -static inline struct anon_vma_chain *anon_vma_chain_alloc(void) +static inline struct anon_vma_chain *anon_vma_chain_alloc(gfp_t gfp) { - return kmem_cache_alloc(anon_vma_chain_cachep, GFP_KERNEL); + return kmem_cache_alloc(anon_vma_chain_cachep, gfp); } static void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain) @@ -159,7 +159,7 @@ int anon_vma_prepare(struct vm_area_struct *vma) struct mm_struct *mm = vma->vm_mm; struct anon_vma *allocated; - avc = anon_vma_chain_alloc(); + avc = anon_vma_chain_alloc(GFP_KERNEL); if (!avc) goto out_enomem; @@ -253,9 +253,14 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src) list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) { struct anon_vma *anon_vma; - avc = anon_vma_chain_alloc(); - if (!avc) - goto enomem_failure; + avc = anon_vma_chain_alloc(GFP_NOWAIT | __GFP_NOWARN); + if (unlikely(!avc)) { + unlock_anon_vma_root(root); + root = NULL; + avc = anon_vma_chain_alloc(GFP_KERNEL); + if (!avc) + goto enomem_failure; + } anon_vma = pavc->anon_vma; root = lock_anon_vma_root(root, anon_vma); anon_vma_chain_link(dst, avc, anon_vma); @@ -264,7 +269,6 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src) return 0; enomem_failure: - unlock_anon_vma_root(root); unlink_anon_vmas(dst); return -ENOMEM; } @@ -294,7 +298,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) anon_vma = anon_vma_alloc(); if (!anon_vma) goto out_error; - avc = anon_vma_chain_alloc(); + avc = anon_vma_chain_alloc(GFP_KERNEL); if (!avc) goto out_error_free_anon_vma; From 0897554cdd9de8a9f6f93d9ba27c7ebfae286158 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 14 Jun 2011 10:16:17 +1000 Subject: [PATCH 546/595] drm/nouveau: fix big-endian switch Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_state.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 80218887e0a0..144f79a350ae 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -881,8 +881,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) #ifdef __BIG_ENDIAN /* Put the card in BE mode if it's not */ - if (nv_rd32(dev, NV03_PMC_BOOT_1)) - nv_wr32(dev, NV03_PMC_BOOT_1, 0x00000001); + if (nv_rd32(dev, NV03_PMC_BOOT_1) != 0x01000001) + nv_wr32(dev, NV03_PMC_BOOT_1, 0x01000001); DRM_MEMORYBARRIER(); #endif From 2905544073f6ec235b44f624c66f52b61221a16c Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Sat, 11 Jun 2011 13:30:32 +0100 Subject: [PATCH 547/595] drm/nouveau/pm: Prevent overflow in nouveau_perf_init() While parsing the perf table, there is no check if the num of entries read from the vbios is less than the currently allocated number. In case of a buggy vbios this will cause overwriting of kernel memory, causing aditional problems. Add a simple check in order to prevent the case Signed-off-by: Emil Velikov Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_perf.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c index 922fb6b664ed..ef9dec0e6f8b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_perf.c +++ b/drivers/gpu/drm/nouveau/nouveau_perf.c @@ -182,6 +182,11 @@ nouveau_perf_init(struct drm_device *dev) entries = perf[2]; } + if (entries > NOUVEAU_PM_MAX_LEVEL) { + NV_DEBUG(dev, "perf table has too many entries - buggy vbios?\n"); + entries = NOUVEAU_PM_MAX_LEVEL; + } + entry = perf + headerlen; for (i = 0; i < entries; i++) { struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; From f66b3d5540994cb92182312be24944864cec5a16 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 16 Jun 2011 14:40:27 +1000 Subject: [PATCH 548/595] drm/nv50/disp: fix gamma with page flipping overlay turned on Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_display.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 74a3f6872701..08da478ba544 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -409,7 +409,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct nouveau_channel *evo = dispc->sync; int ret; - ret = RING_SPACE(evo, 24); + ret = RING_SPACE(evo, chan ? 25 : 27); if (unlikely(ret)) return ret; @@ -458,8 +458,19 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, /* queue the flip on the crtc's "display sync" channel */ BEGIN_RING(evo, 0, 0x0100, 1); OUT_RING (evo, 0xfffe0000); - BEGIN_RING(evo, 0, 0x0084, 5); - OUT_RING (evo, chan ? 0x00000100 : 0x00000010); + if (chan) { + BEGIN_RING(evo, 0, 0x0084, 1); + OUT_RING (evo, 0x00000100); + } else { + BEGIN_RING(evo, 0, 0x0084, 1); + OUT_RING (evo, 0x00000010); + /* allows gamma somehow, PDISP will bitch at you if + * you don't wait for vblank before changing this.. + */ + BEGIN_RING(evo, 0, 0x00e0, 1); + OUT_RING (evo, 0x40000000); + } + BEGIN_RING(evo, 0, 0x0088, 4); OUT_RING (evo, dispc->sem.offset); OUT_RING (evo, 0xf00d0000 | dispc->sem.value); OUT_RING (evo, 0x74b1e000); From b16a5a18ff994532120c1d18e678bbc5fb477b62 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 17 Jun 2011 23:41:54 +1000 Subject: [PATCH 549/595] drm/nouveau: fix assumption that semaphore dmaobj is valid in x-chan sync The DDX modifies DMA_SEMAPHORE on nv50 in order to implement sync-to-vblank, things will go very wrong for cross-channel sync after this. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_fence.c | 59 +++++++++++-------------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 4b9f4493c9f9..7347075ca5b8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -339,11 +339,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) int ret; if (dev_priv->chipset < 0x84) { - ret = RING_SPACE(chan, 3); + ret = RING_SPACE(chan, 4); if (ret) return ret; - BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 2); + BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 3); + OUT_RING (chan, NvSema); OUT_RING (chan, sema->mem->start); OUT_RING (chan, 1); } else @@ -351,10 +352,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) struct nouveau_vma *vma = &dev_priv->fence.bo->vma; u64 offset = vma->offset + sema->mem->start; - ret = RING_SPACE(chan, 5); + ret = RING_SPACE(chan, 7); if (ret) return ret; + BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); + OUT_RING (chan, chan->vram_handle); BEGIN_RING(chan, NvSubSw, 0x0010, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset)); @@ -394,11 +397,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) int ret; if (dev_priv->chipset < 0x84) { - ret = RING_SPACE(chan, 4); + ret = RING_SPACE(chan, 5); if (ret) return ret; - BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1); + BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 2); + OUT_RING (chan, NvSema); OUT_RING (chan, sema->mem->start); BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1); OUT_RING (chan, 1); @@ -407,10 +411,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) struct nouveau_vma *vma = &dev_priv->fence.bo->vma; u64 offset = vma->offset + sema->mem->start; - ret = RING_SPACE(chan, 5); + ret = RING_SPACE(chan, 7); if (ret) return ret; + BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); + OUT_RING (chan, chan->vram_handle); BEGIN_RING(chan, NvSubSw, 0x0010, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset)); @@ -504,22 +510,22 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) struct nouveau_gpuobj *obj = NULL; int ret; - if (dev_priv->card_type >= NV_C0) - goto out_initialised; + if (dev_priv->card_type < NV_C0) { + /* Create an NV_SW object for various sync purposes */ + ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); + if (ret) + return ret; - /* Create an NV_SW object for various sync purposes */ - ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); - if (ret) - return ret; + ret = RING_SPACE(chan, 2); + if (ret) + return ret; - /* we leave subchannel empty for nvc0 */ - ret = RING_SPACE(chan, 2); - if (ret) - return ret; - BEGIN_RING(chan, NvSubSw, 0, 1); - OUT_RING(chan, NvSw); + BEGIN_RING(chan, NvSubSw, 0, 1); + OUT_RING (chan, NvSw); + FIRE_RING (chan); + } - /* Create a DMA object for the shared cross-channel sync area. */ + /* Setup area of memory shared between all channels for x-chan sync */ if (USE_SEMA(dev) && dev_priv->chipset < 0x84) { struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; @@ -534,23 +540,8 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) nouveau_gpuobj_ref(NULL, &obj); if (ret) return ret; - - ret = RING_SPACE(chan, 2); - if (ret) - return ret; - BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); - OUT_RING(chan, NvSema); - } else { - ret = RING_SPACE(chan, 2); - if (ret) - return ret; - BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); - OUT_RING (chan, chan->vram_handle); /* whole VM */ } - FIRE_RING(chan); - -out_initialised: INIT_LIST_HEAD(&chan->fence.pending); spin_lock_init(&chan->fence.lock); atomic_set(&chan->fence.last_sequence_irq, 0); From 808b4e639eb00394de9989fabca23196c337ee75 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 7 Jun 2011 15:14:26 -0400 Subject: [PATCH 550/595] hwmon: (coretemp) Drop unused struct members pdev_entry.cpu and pdev_entry.cpu_core_id aren't used anywhere in the driver code so we can drop these struct members. Signed-off-by: Jean Delvare Cc: Fenghua Yu Cc: Guenter Roeck Cc: Durgadoss R Signed-off-by: Guenter Roeck --- drivers/hwmon/coretemp.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 85e937984ff7..0070d5476dd0 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -97,9 +97,7 @@ struct platform_data { struct pdev_entry { struct list_head list; struct platform_device *pdev; - unsigned int cpu; u16 phys_proc_id; - u16 cpu_core_id; }; static LIST_HEAD(pdev_list); @@ -653,9 +651,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu) } pdev_entry->pdev = pdev; - pdev_entry->cpu = cpu; pdev_entry->phys_proc_id = TO_PHYS_ID(cpu); - pdev_entry->cpu_core_id = TO_CORE_ID(cpu); list_add_tail(&pdev_entry->list, &pdev_list); mutex_unlock(&pdev_list_mutex); From 9a2d55be1168b56a5c65321dcce64c97798eaec7 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 24 May 2011 12:19:05 -0700 Subject: [PATCH 551/595] hwmon: (asus_atk0110) Consolidate sysfs attribute initialization Call sysfs_attr_init() from atk_init_attribute() to handle sysfs attribute initialization in a single function. Signed-off-by: Guenter Roeck Cc: Luca Tettamanti Acked-by: Jean Delvare --- drivers/hwmon/asus_atk0110.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index b5e892017e0c..dcb78a7a8047 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -268,6 +268,7 @@ static struct device_attribute atk_name_attr = static void atk_init_attribute(struct device_attribute *attr, char *name, sysfs_show_func show) { + sysfs_attr_init(&attr->attr); attr->attr.name = name; attr->attr.mode = 0444; attr->show = show; @@ -1188,19 +1189,15 @@ static int atk_create_files(struct atk_data *data) int err; list_for_each_entry(s, &data->sensor_list, list) { - sysfs_attr_init(&s->input_attr.attr); err = device_create_file(data->hwmon_dev, &s->input_attr); if (err) return err; - sysfs_attr_init(&s->label_attr.attr); err = device_create_file(data->hwmon_dev, &s->label_attr); if (err) return err; - sysfs_attr_init(&s->limit1_attr.attr); err = device_create_file(data->hwmon_dev, &s->limit1_attr); if (err) return err; - sysfs_attr_init(&s->limit2_attr.attr); err = device_create_file(data->hwmon_dev, &s->limit2_attr); if (err) return err; From 3cdb2052a6e365ad56202874e6a8a05a2bb336fc Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 24 May 2011 12:33:26 -0700 Subject: [PATCH 552/595] hwmon: (ibmaem) Initialize sysfs attributes Initialize dynamically allocated sysfs attributes before device_create_file() call to suppress lockdep_init_map() warning if lockdep debugging is enabled. Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Cc: stable@kernel.org # 2.6.34+ --- drivers/hwmon/ibmaem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c index 537409d07ee7..1a409c5bc9bc 100644 --- a/drivers/hwmon/ibmaem.c +++ b/drivers/hwmon/ibmaem.c @@ -947,6 +947,7 @@ static int aem_register_sensors(struct aem_data *data, /* Set up read-only sensors */ while (ro->label) { + sysfs_attr_init(&sensors->dev_attr.attr); sensors->dev_attr.attr.name = ro->label; sensors->dev_attr.attr.mode = S_IRUGO; sensors->dev_attr.show = ro->show; @@ -963,6 +964,7 @@ static int aem_register_sensors(struct aem_data *data, /* Set up read-write sensors */ while (rw->label) { + sysfs_attr_init(&sensors->dev_attr.attr); sensors->dev_attr.attr.name = rw->label; sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR; sensors->dev_attr.show = rw->show; From fb794e0f7153918c33f2300986d995524ab711cf Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 24 May 2011 12:34:12 -0700 Subject: [PATCH 553/595] hwmon: (ibmpex) Initialize sysfs attributes Initialize dynamically allocated sysfs attributes before device_create_file() call to suppress lockdep_init_map() warning if lockdep debugging is enabled. Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Cc: stable@kernel.org # 2.6.34+ --- drivers/hwmon/ibmpex.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c index 06d4eafcf76b..41dbf8161ed7 100644 --- a/drivers/hwmon/ibmpex.c +++ b/drivers/hwmon/ibmpex.c @@ -358,6 +358,7 @@ static int create_sensor(struct ibmpex_bmc_data *data, int type, else if (type == POWER_SENSOR) sprintf(n, power_sensor_name_templates[func], "power", counter); + sysfs_attr_init(&data->sensors[sensor].attr[func].dev_attr.attr); data->sensors[sensor].attr[func].dev_attr.attr.name = n; data->sensors[sensor].attr[func].dev_attr.attr.mode = S_IRUGO; data->sensors[sensor].attr[func].dev_attr.show = ibmpex_show_sensor; From b1e698db0939b04602ded2a2196ff69c92b49378 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 24 May 2011 12:34:55 -0700 Subject: [PATCH 554/595] hwmon: (s3c) Initialize sysfs attributes Initialize dynamically allocated sysfs attributes before device_create_file() call to suppress lockdep_init_map() warning if lockdep debugging is enabled. Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Cc: stable@kernel.org # 2.6.34+ --- drivers/hwmon/s3c-hwmon.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c index 92b42db43bcf..b39f52e2752a 100644 --- a/drivers/hwmon/s3c-hwmon.c +++ b/drivers/hwmon/s3c-hwmon.c @@ -232,6 +232,7 @@ static int s3c_hwmon_create_attr(struct device *dev, attr = &attrs->in; attr->index = channel; + sysfs_attr_init(&attr->dev_attr.attr); attr->dev_attr.attr.name = attrs->in_name; attr->dev_attr.attr.mode = S_IRUGO; attr->dev_attr.show = s3c_hwmon_ch_show; @@ -249,6 +250,7 @@ static int s3c_hwmon_create_attr(struct device *dev, attr = &attrs->label; attr->index = channel; + sysfs_attr_init(&attr->dev_attr.attr); attr->dev_attr.attr.name = attrs->label_name; attr->dev_attr.attr.mode = S_IRUGO; attr->dev_attr.show = s3c_hwmon_label_show; From da40b0b6b4d3a81c5051fe6ae0544c48c13261c4 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 18 Jun 2011 02:50:11 -0700 Subject: [PATCH 555/595] Input: evdev - try to wake up readers only if we have full packet We should only wake waiters on the event device when we actually post an EV_SYN/SYN_REPORT to the queue. Otherwise we end up making waiting threads runnable only to go right back to sleep because the device still isn't readable. Reported-by: Jeffrey Brown Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index be0921ef6b52..4cf25347b015 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -111,7 +111,8 @@ static void evdev_event(struct input_handle *handle, rcu_read_unlock(); - wake_up_interruptible(&evdev->wait); + if (type == EV_SYN && code == SYN_REPORT) + wake_up_interruptible(&evdev->wait); } static int evdev_fasync(int fd, struct file *file, int on) From b27af563befa95686c8d1abc491408aa6b9a31dc Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 15 Jun 2011 21:13:55 -0700 Subject: [PATCH 556/595] Input: omap-keypad - add missing input_sync() Otherwise the updated evdev driver (commit cdda911c34006f1089f3c87b1a1f, "Input: evdev - only signal polls on full packets") no longer works on top of omap-keypad. Tested on Amstrad Delta. Signed-off-by: Janusz Krzysztofik Reviewed-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/omap-keypad.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index f23a743817db..33d0bdc837c0 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -209,6 +209,7 @@ static void omap_kp_tasklet(unsigned long data) #endif } } + input_sync(omap_kp_data->input); memcpy(keypad_state, new_state, sizeof(keypad_state)); if (key_down) { From cca23d0b5350c9ca0473625c3f5879422ba534a6 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Sat, 18 Jun 2011 02:51:52 -0700 Subject: [PATCH 557/595] Input: sh_keysc - 8x8 MODE_6 fix According to the data sheet for G4, AP4 and AG5 KEYSC MODE_6 is 8x8 keys. Bump up MAXKEYS to 64 too. Signed-off-by: Magnus Damm Reviewed-by: Simon Horman Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/sh_keysc.c | 2 +- include/linux/input/sh_keysc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 834cf98e7efb..6876700a4469 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -32,7 +32,7 @@ static const struct { [SH_KEYSC_MODE_3] = { 2, 4, 7 }, [SH_KEYSC_MODE_4] = { 3, 6, 6 }, [SH_KEYSC_MODE_5] = { 4, 6, 7 }, - [SH_KEYSC_MODE_6] = { 5, 7, 7 }, + [SH_KEYSC_MODE_6] = { 5, 8, 8 }, }; struct sh_keysc_priv { diff --git a/include/linux/input/sh_keysc.h b/include/linux/input/sh_keysc.h index 649dc7f12925..5d253cd93691 100644 --- a/include/linux/input/sh_keysc.h +++ b/include/linux/input/sh_keysc.h @@ -1,7 +1,7 @@ #ifndef __SH_KEYSC_H__ #define __SH_KEYSC_H__ -#define SH_KEYSC_MAXKEYS 49 +#define SH_KEYSC_MAXKEYS 64 struct sh_keysc_info { enum { SH_KEYSC_MODE_1, SH_KEYSC_MODE_2, SH_KEYSC_MODE_3, From c11760c6d80ab6aa20e383cf378a7287305f591c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 8 Jun 2011 10:30:03 -0700 Subject: [PATCH 558/595] isofs: fix bh leak in isofs_fill_super() error case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In isofs_fill_super(), when an iso_primary_descriptor is found, it is kept in pri_bh. The error cases don't properly release it. Fix it. Reported-and-tested-by: 김원석 Cc: Andrew Morton Signed-off-by: Linus Torvalds --- fs/isofs/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 3db5ba4568fc..b3cc8586984e 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -974,7 +974,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) out_no_read: printk(KERN_WARNING "%s: bread failed, dev=%s, iso_blknum=%d, block=%d\n", __func__, s->s_id, iso_blknum, block); - goto out_freesbi; + goto out_freebh; out_bad_zone_size: printk(KERN_WARNING "ISOFS: Bad logical zone size %ld\n", sbi->s_log_zone_size); @@ -989,6 +989,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) out_freebh: brelse(bh); + brelse(pri_bh); out_freesbi: kfree(opt.iocharset); kfree(sbi); From 9aa3c94ce59066f545521033007abb6441706068 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 18 Jun 2011 11:59:18 -0700 Subject: [PATCH 559/595] ipv4: fix multicast losses Knut Tidemann found that first packet of a multicast flow was not correctly received, and bisected the regression to commit b23dd4fe42b4 (Make output route lookup return rtable directly.) Special thanks to Knut, who provided a very nice bug report, including sample programs to demonstrate the bug. Reported-and-bisectedby: Knut Tidemann Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/route.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 045f0ec6a4a0..aa13ef105110 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1902,9 +1902,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); rth = rt_intern_hash(hash, rth, skb, dev->ifindex); - err = 0; - if (IS_ERR(rth)) - err = PTR_ERR(rth); + return IS_ERR(rth) ? PTR_ERR(rth) : 0; e_nobufs: return -ENOBUFS; From 7d68dc3f1003a38948c55c803c32d1989dd49198 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 14 Jun 2011 19:53:09 +0200 Subject: [PATCH 560/595] x86, efi: Do not reserve boot services regions within reserved areas Commit 916f676f8dc started reserving boot service code since some systems require you to keep that code around until SetVirtualAddressMap is called. However, in some cases those areas will overlap with reserved regions. The proper medium-term fix is to fix the bootloader to prevent the conflicts from occurring by moving the kernel to a better position, but the kernel should check for this possibility, and only reserve regions which can be reserved. Signed-off-by: Maarten Lankhorst Link: http://lkml.kernel.org/r/4DF7A005.1050407@gmail.com Acked-by: Matthew Garrett Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar --- arch/x86/include/asm/memblock.h | 2 +- arch/x86/mm/memblock.c | 4 ++-- arch/x86/platform/efi/efi.c | 29 +++++++++++++++++++++++++---- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/memblock.h b/arch/x86/include/asm/memblock.h index 19ae14ba6978..0cd3800f33b9 100644 --- a/arch/x86/include/asm/memblock.h +++ b/arch/x86/include/asm/memblock.h @@ -4,7 +4,6 @@ #define ARCH_DISCARD_MEMBLOCK u64 memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align); -void memblock_x86_to_bootmem(u64 start, u64 end); void memblock_x86_reserve_range(u64 start, u64 end, char *name); void memblock_x86_free_range(u64 start, u64 end); @@ -19,5 +18,6 @@ u64 memblock_x86_hole_size(u64 start, u64 end); u64 memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align); u64 memblock_x86_free_memory_in_range(u64 addr, u64 limit); u64 memblock_x86_memory_in_range(u64 addr, u64 limit); +bool memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align); #endif diff --git a/arch/x86/mm/memblock.c b/arch/x86/mm/memblock.c index aa1169392b83..992da5ec5a64 100644 --- a/arch/x86/mm/memblock.c +++ b/arch/x86/mm/memblock.c @@ -8,7 +8,7 @@ #include /* Check for already reserved areas */ -static bool __init check_with_memblock_reserved_size(u64 *addrp, u64 *sizep, u64 align) +bool __init memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align) { struct memblock_region *r; u64 addr = *addrp, last; @@ -59,7 +59,7 @@ u64 __init memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align) if (addr >= ei_last) continue; *sizep = ei_last - addr; - while (check_with_memblock_reserved_size(&addr, sizep, align)) + while (memblock_x86_check_reserved_size(&addr, sizep, align)) ; if (*sizep) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 0d3a4fa34560..474356b98ede 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -310,14 +310,31 @@ void __init efi_reserve_boot_services(void) 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; - unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; + u64 start = md->phys_addr; + u64 size = md->num_pages << EFI_PAGE_SHIFT; if (md->type != EFI_BOOT_SERVICES_CODE && md->type != EFI_BOOT_SERVICES_DATA) continue; - - memblock_x86_reserve_range(start, start + size, "EFI Boot"); + /* Only reserve where possible: + * - Not within any already allocated areas + * - Not over any memory area (really needed, if above?) + * - Not within any part of the kernel + * - Not the bios reserved area + */ + if ((start+size >= virt_to_phys(_text) + && start <= virt_to_phys(_end)) || + !e820_all_mapped(start, start+size, E820_RAM) || + memblock_x86_check_reserved_size(&start, &size, + 1<num_pages = 0; + memblock_dbg(PFX "Could not reserve boot range " + "[0x%010llx-0x%010llx]\n", + start, start+size-1); + } else + memblock_x86_reserve_range(start, start+size, + "EFI Boot"); } } @@ -334,6 +351,10 @@ static void __init efi_free_boot_services(void) md->type != EFI_BOOT_SERVICES_DATA) continue; + /* Could not reserve boot area */ + if (!size) + continue; + free_bootmem_late(start, size); } } From c1f5c54b57341e872a9d375dccef7257f86033ef Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 18 Jun 2011 22:51:13 +0200 Subject: [PATCH 561/595] x86, MAINTAINERS: Add x86 MCE people Announce the new x86 MCE infrastructure maintainers. Acked-by: Borislav Petkov Acked-by: Tony Luck Acked-by: H. Peter Anvin Acked-by: Thomas Gleixner Link: http://lkml.kernel.org/n/tip-8hs7yob6wib4vblmrmbpbav4@git.kernel.org Signed-off-by: Ingo Molnar --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 502f2dd761eb..b12b8c13f53a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7007,6 +7007,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86. S: Maintained F: drivers/platform/x86 +X86 MCE INFRASTRUCTURE +M: Tony Luck +M: Borislav Petkov +L: linux-edac@vger.kernel.org +S: Maintained +F: arch/x86/kernel/cpu/mcheck/* + XEN HYPERVISOR INTERFACE M: Jeremy Fitzhardinge M: Konrad Rzeszutek Wilk From b72336355bb4c92d4a2be3f975dbea47089c83c1 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 30 May 2011 22:11:17 +0200 Subject: [PATCH 562/595] KVM: MMU: Fix build warnings in walk_addr_generic() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On 3.0-rc1 I get In file included from arch/x86/kvm/mmu.c:2856: arch/x86/kvm/paging_tmpl.h: In function ‘paging32_walk_addr_generic’: arch/x86/kvm/paging_tmpl.h:124: warning: ‘ptep_user’ may be used uninitialized in this function In file included from arch/x86/kvm/mmu.c:2852: arch/x86/kvm/paging_tmpl.h: In function ‘paging64_walk_addr_generic’: arch/x86/kvm/paging_tmpl.h:124: warning: ‘ptep_user’ may be used uninitialized in this function caused by 6e2ca7d1802bf8ed9908435e34daa116662e7790. According to Takuya Yoshikawa, ptep_user won't be used uninitialized so shut up gcc. Cc: Takuya Yoshikawa Link: http://lkml.kernel.org/r/20110530094604.GC21833@liondog.tnic Signed-off-by: Borislav Petkov Signed-off-by: Avi Kivity --- arch/x86/kvm/paging_tmpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 6c4dc010c4cb..9d03ad4dd5ec 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -121,7 +121,7 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker, gva_t addr, u32 access) { pt_element_t pte; - pt_element_t __user *ptep_user; + pt_element_t __user *uninitialized_var(ptep_user); gfn_t table_gfn; unsigned index, pt_access, uninitialized_var(pte_access); gpa_t pte_gpa; From 5233dd51ece1615d54ab96c4cbe9ac3cc595e955 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Mon, 6 Jun 2011 14:27:47 -0300 Subject: [PATCH 563/595] KVM: VMX: do not overwrite uptodate vcpu->arch.cr3 on KVM_SET_SREGS Only decache guest CR3 value if vcpu->arch.cr3 is stale. Fixes loadvm with live guest. Signed-off-by: Marcelo Tosatti Tested-by: Markus Schade Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 4c3fa0f67469..d48ec60ea421 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2047,7 +2047,8 @@ static void ept_update_paging_mode_cr0(unsigned long *hw_cr0, unsigned long cr0, struct kvm_vcpu *vcpu) { - vmx_decache_cr3(vcpu); + if (!test_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail)) + vmx_decache_cr3(vcpu); if (!(cr0 & X86_CR0_PG)) { /* From paging/starting to nonpaging */ vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, From a0a8eaba1661232f094654422bdabe2df4e26863 Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 17 Jun 2011 10:25:39 +0800 Subject: [PATCH 564/595] KVM: MMU: fix opposite condition in mapping_level_dirty_bitmap The condition is opposite, it always maps huge page for the dirty tracked page Reported-by: Steve Signed-off-by: Steve Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index bd14bb4c8594..aee38623b768 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -565,7 +565,7 @@ gfn_to_memslot_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t gfn, static bool mapping_level_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t large_gfn) { - return gfn_to_memslot_dirty_bitmap(vcpu, large_gfn, true); + return !gfn_to_memslot_dirty_bitmap(vcpu, large_gfn, true); } static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) From de2d1a524e94a79078d9fe22c57c0c6009237547 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Wed, 15 Jun 2011 20:50:04 -0700 Subject: [PATCH 565/595] KVM: Fix register corruption in pvclock_scale_delta The 128-bit multiply in pvclock.h was missing an output constraint for EDX which caused a register corruption to appear. Thanks to Ulrich for diagnosing the EDX corruption and Avi for providing this fix. Signed-off-by: Zachary Amsden Signed-off-by: Avi Kivity --- arch/x86/include/asm/pvclock.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h index 31d84acc1512..a518c0a45044 100644 --- a/arch/x86/include/asm/pvclock.h +++ b/arch/x86/include/asm/pvclock.h @@ -22,6 +22,8 @@ static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift) u64 product; #ifdef __i386__ u32 tmp1, tmp2; +#else + ulong tmp; #endif if (shift < 0) @@ -42,8 +44,11 @@ static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift) : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) ); #elif defined(__x86_64__) __asm__ ( - "mul %%rdx ; shrd $32,%%rdx,%%rax" - : "=a" (product) : "0" (delta), "d" ((u64)mul_frac) ); + "mul %[mul_frac] ; shrd $32, %[hi], %[lo]" + : [lo]"=a"(product), + [hi]"=d"(tmp) + : "0"(delta), + [mul_frac]"rm"((u64)mul_frac)); #else #error implement me! #endif From cefa9993f161c1c2b6b91b7ea2e84a9bfbd43d2e Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Sun, 19 Jun 2011 16:13:01 -0700 Subject: [PATCH 566/595] netpoll: copy dev name of slaves to struct netpoll Otherwise we will not see the name of the slave dev in error message: [ 388.469446] (null): doesn't support polling, aborting. Signed-off-by: WANG Cong Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 1 + net/bridge/br_device.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 652b30e525d0..eafe44a528ac 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1297,6 +1297,7 @@ static inline int slave_enable_netpoll(struct slave *slave) goto out; np->dev = slave->dev; + strlcpy(np->dev_name, slave->dev->name, IFNAMSIZ); err = __netpoll_setup(np); if (err) { kfree(np); diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index a6b2f86378c7..c188c803c09c 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -243,6 +243,7 @@ int br_netpoll_enable(struct net_bridge_port *p) goto out; np->dev = p->dev; + strlcpy(np->dev_name, p->dev->name, IFNAMSIZ); err = __netpoll_setup(np); if (err) { From 658924dc9ae2ca8e3c46f36306f5dbd501cf4688 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 19 Jun 2011 12:43:33 +0000 Subject: [PATCH 567/595] hp100: fix an skb->len race As soon as skb is given to hardware and spinlock released, TX completion can free skb under us. Therefore, we should update netdev stats before spinlock release. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/hp100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 8e10d2f6a5ad..c3ecb118c1df 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -1580,12 +1580,12 @@ static netdev_tx_t hp100_start_xmit_bm(struct sk_buff *skb, hp100_outl(ringptr->pdl_paddr, TX_PDA_L); /* Low Prio. Queue */ lp->txrcommit++; - spin_unlock_irqrestore(&lp->lock, flags); - /* Update statistics */ dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; + spin_unlock_irqrestore(&lp->lock, flags); + return NETDEV_TX_OK; drop: From 44da29d26bb8df3b0411ba902f2bc9b973ea38e4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 19 Jun 2011 12:52:36 +0000 Subject: [PATCH 568/595] sgi-xp: fix a use after free Its illegal to dereference skb after dev_kfree_skb(skb) Signed-off-by: Eric Dumazet CC: Robin Holt Signed-off-by: David S. Miller --- drivers/misc/sgi-xp/xpnet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index ee5109a3cd98..42f067347bc7 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c @@ -495,14 +495,14 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } } + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + if (atomic_dec_return(&queued_msg->use_count) == 0) { dev_kfree_skb(skb); kfree(queued_msg); } - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - return NETDEV_TX_OK; } From 8323fa6ba313ae2664420ec34d56a7fb0bbbe525 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 17 Jun 2011 13:13:52 -0400 Subject: [PATCH 569/595] drm/radeon/kms/atom: fix duallink on some early DCE3.2 cards Certain revisions of the vbios on DCE3.2 cards have a bug in the transmitter control table which prevents duallink from being enabled properly on some cards. The action switch statement jumps to the wrong offset for the OUTPUT_ENABLE action. The fix is to use the ENABLE action rather than the OUTPUT_ENABLE action on the affected cards. In fixed version of the vbios, both actions jump to the same offset, so the change should be safe. Reported-and-tested-by: Dave Airlie Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index f55b64cb59d1..012f80251e50 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1431,7 +1431,11 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) if (is_dig) { switch (mode) { case DRM_MODE_DPMS_ON: - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 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, 0, 0); + else + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); From 74d074eecbb4778e5f5ee7d59399da971682c532 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 17 Jun 2011 06:11:30 +0000 Subject: [PATCH 570/595] drm/radeon/kms: add missing param for dce3.2 DP transmitter setup This is used during phy init to set up the phy for DP. This may fix DP problems on DCE3.2 cards. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 012f80251e50..b293487e5aa3 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1090,9 +1090,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t break; } - if (is_dp) + if (is_dp) { args.v2.acConfig.fCoherentMode = 1; - else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + args.v2.acConfig.fDPConnector = 1; + } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { if (dig->coherent_mode) args.v2.acConfig.fCoherentMode = 1; if (radeon_encoder->pixel_clock > 165000) From 682f1a54a03513fd6bcede56845f1ba21f48c182 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 18 Jun 2011 03:59:51 +0000 Subject: [PATCH 571/595] drm/radeon: avoid warnings from r600/eg irq handlers on powered off card. Since we were calling the wptr function before checking if the IH was even enabled, or the GPU wasn't shutdown, we'd get spam in the logs when the GPU readback 0xffffffff. This reorders things so we return early in the no IH and GPU shutdown cases. Reported-and-tested-by: ManDay on #radeon Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 17 +++++++---------- drivers/gpu/drm/radeon/r600.c | 15 +++++++-------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 7e3d96e7ac04..7162b7bacac0 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2695,28 +2695,25 @@ static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev) int evergreen_irq_process(struct radeon_device *rdev) { - u32 wptr = evergreen_get_ih_wptr(rdev); - u32 rptr = rdev->ih.rptr; + u32 wptr; + u32 rptr; u32 src_id, src_data; u32 ring_index; unsigned long flags; bool queue_hotplug = false; - DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); - if (!rdev->ih.enabled) + if (!rdev->ih.enabled || rdev->shutdown) return IRQ_NONE; - spin_lock_irqsave(&rdev->ih.lock, flags); + wptr = evergreen_get_ih_wptr(rdev); + rptr = rdev->ih.rptr; + DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + spin_lock_irqsave(&rdev->ih.lock, flags); if (rptr == wptr) { spin_unlock_irqrestore(&rdev->ih.lock, flags); return IRQ_NONE; } - if (rdev->shutdown) { - spin_unlock_irqrestore(&rdev->ih.lock, flags); - return IRQ_NONE; - } - restart_ih: /* display interrupts */ evergreen_irq_ack(rdev); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 7dd45ca64e29..dc9fde38ef49 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3294,27 +3294,26 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) int r600_irq_process(struct radeon_device *rdev) { - u32 wptr = r600_get_ih_wptr(rdev); - u32 rptr = rdev->ih.rptr; + u32 wptr; + u32 rptr; u32 src_id, src_data; u32 ring_index; unsigned long flags; bool queue_hotplug = false; - DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); - if (!rdev->ih.enabled) + if (!rdev->ih.enabled || rdev->shutdown) return IRQ_NONE; + wptr = r600_get_ih_wptr(rdev); + rptr = rdev->ih.rptr; + DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + spin_lock_irqsave(&rdev->ih.lock, flags); if (rptr == wptr) { spin_unlock_irqrestore(&rdev->ih.lock, flags); return IRQ_NONE; } - if (rdev->shutdown) { - spin_unlock_irqrestore(&rdev->ih.lock, flags); - return IRQ_NONE; - } restart_ih: /* display interrupts */ From 4ee1c57fcadfb79a6515698d8001081b5b980e32 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 20 Jun 2011 15:25:35 +1000 Subject: [PATCH 572/595] drm/nouveau: drop leftover debugging this printk isn't really useful, just drop it for now. Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index f0d459bb46e4..525744d593c1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -262,7 +262,6 @@ static bool nouveau_dsm_detect(void) vga_count++; retval = nouveau_dsm_pci_probe(pdev); - printk("ret val is %d\n", retval); if (retval & NOUVEAU_DSM_HAS_MUX) has_dsm |= 1; if (retval & NOUVEAU_DSM_HAS_OPT) From 105f4622104848ff1ee1f644d661bef9dec3eb27 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 7 Jun 2011 11:50:23 -0400 Subject: [PATCH 573/595] nfsd4: fix break_lease flags on nfsd open Thanks to Casey Bodley for pointing out that on a read open we pass 0, instead of O_RDONLY, to break_lease, with the result that a read open is treated like a write open for the purposes of lease breaking! Reported-by: Casey Bodley Cc: stable@kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/vfs.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index f3fb61b69a1e..fd0acca5370a 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -696,7 +696,15 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor } #endif /* CONFIG_NFSD_V3 */ +static int nfsd_open_break_lease(struct inode *inode, int access) +{ + unsigned int mode; + if (access & NFSD_MAY_NOT_BREAK_LEASE) + return 0; + mode = (access & NFSD_MAY_WRITE) ? O_WRONLY : O_RDONLY; + return break_lease(inode, mode | O_NONBLOCK); +} /* * Open an existing file or directory. @@ -744,12 +752,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, if (!inode->i_fop) goto out; - /* - * Check to see if there are any leases on this file. - * This may block while leases are broken. - */ - if (!(access & NFSD_MAY_NOT_BREAK_LEASE)) - host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0)); + host_err = nfsd_open_break_lease(inode, access); if (host_err) /* NOMEM or WOULDBLOCK */ goto out_nfserr; From 185bf87393afe6b966881e36c459949d90930a7a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 20 Jun 2011 10:10:24 +0300 Subject: [PATCH 574/595] ubifs: dereferencing an ERR_PTR in ubifs_mount() d251ed271d5 "ubifs: fix sget races" left out the goto from this error path so the static checkers complain that we're dereferencing "sb" when it's an ERR_PTR. Signed-off-by: Dan Carpenter Signed-off-by: Al Viro --- fs/ubifs/super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 8c892c2d5300..529be0582029 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -2146,6 +2146,7 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, if (IS_ERR(sb)) { err = PTR_ERR(sb); kfree(c); + goto out_close; } if (sb->s_root) { From 1712c20dae7b770b62b2e3272100b3b40af0157c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 19:59:04 -0400 Subject: [PATCH 575/595] bad_inode_permission() is safe from RCU mode return -EIO; is *not* a blocking operation, thank you very much. Nick, what the hell have you been smoking? Signed-off-by: Al Viro --- fs/bad_inode.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 9ad2369d9e35..bfcb18feb1df 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -231,9 +231,6 @@ static int bad_inode_readlink(struct dentry *dentry, char __user *buffer, static int bad_inode_permission(struct inode *inode, int mask, unsigned int flags) { - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - return -EIO; } From ec12781f192568f7ea860f440f890389ba393df7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:03:36 -0400 Subject: [PATCH 576/595] cifs_permission() doesn't need to bail out in RCU mode nothing potentially blocking except generic_permission(), which will DTRT Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index e9def996e383..2f0c58646c10 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -257,9 +257,6 @@ static int cifs_permission(struct inode *inode, int mask, unsigned int flags) { struct cifs_sb_info *cifs_sb; - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - cifs_sb = CIFS_SB(inode->i_sb); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { From 6b419951f1e44c8a46fccfc6551eca9a9980acd6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:11:43 -0400 Subject: [PATCH 577/595] coda_ioctl_permission() is safe in RCU mode return (mask & MAY_EXEC) ? -EACCES : 0; is non-blocking... Signed-off-by: Al Viro --- fs/coda/pioctl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 6cbb3afb36dc..cb140ef293e4 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c @@ -43,8 +43,6 @@ const struct file_operations coda_ioctl_operations = { /* the coda pioctl inode ops */ static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags) { - if (flags & IPERM_FLAG_RCU) - return -ECHILD; return (mask & MAY_EXEC) ? -EACCES : 0; } From a63ab94d67879bc0630ea9821c582ddf58ba5527 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:17:22 -0400 Subject: [PATCH 578/595] logfs doesn't need ->permission() at all ... and never did, what with its ->permission() being what we do by default when ->permission is NULL... Signed-off-by: Al Viro --- fs/logfs/dir.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c index 9ed89d1663f8..1afae26cf236 100644 --- a/fs/logfs/dir.c +++ b/fs/logfs/dir.c @@ -555,13 +555,6 @@ static int logfs_symlink(struct inode *dir, struct dentry *dentry, return __logfs_create(dir, dentry, inode, target, destlen); } -static int logfs_permission(struct inode *inode, int mask, unsigned int flags) -{ - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - return generic_permission(inode, mask, flags, NULL); -} - static int logfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { @@ -820,7 +813,6 @@ const struct inode_operations logfs_dir_iops = { .mknod = logfs_mknod, .rename = logfs_rename, .rmdir = logfs_rmdir, - .permission = logfs_permission, .symlink = logfs_symlink, .unlink = logfs_unlink, }; From 730e908f3539066d4aa01f4720ebfc750ce4d045 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:21:44 -0400 Subject: [PATCH 579/595] nilfs2_permission() doesn't need to bail out in RCU mode Nothing blocking except for generic_permission(). Which will DTRT. Signed-off-by: Al Viro --- fs/nilfs2/inode.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index b954878ad6ce..b9b45fc2903e 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -801,12 +801,7 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr) int nilfs_permission(struct inode *inode, int mask, unsigned int flags) { - struct nilfs_root *root; - - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - - root = NILFS_I(inode)->i_root; + struct nilfs_root *root = NILFS_I(inode)->i_root; if ((mask & MAY_WRITE) && root && root->cno != NILFS_CPTREE_CURRENT_CNO) return -EROFS; /* snapshot is not writable */ From cf1279111686d9742cbc4145bc9d526c83f59fea Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:35:23 -0400 Subject: [PATCH 580/595] proc_fd_permission() is doesn't need to bail out in RCU mode nothing blocking except generic_permission() Signed-off-by: Al Viro --- fs/proc/base.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 14def991d9dd..8a84210ca080 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2169,11 +2169,7 @@ static const struct file_operations proc_fd_operations = { */ static int proc_fd_permission(struct inode *inode, int mask, unsigned int flags) { - int rv; - - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - rv = generic_permission(inode, mask, flags, NULL); + int rv = generic_permission(inode, mask, flags, NULL); if (rv == 0) return 0; if (task_pid(current) == proc_pid(inode)) From 1d29b5a2ed7eb8862c9b66daf475f3e4c1a40299 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:37:33 -0400 Subject: [PATCH 581/595] reiserfs_permission() doesn't need to bail out in RCU mode nothing blocking other than generic_permission() (and check_acl callback does bail out in RCU mode). Signed-off-by: Al Viro --- fs/reiserfs/xattr.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index e8a62f41b458..d78089690965 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -954,8 +954,6 @@ static int xattr_mount_check(struct super_block *s) int reiserfs_permission(struct inode *inode, int mask, unsigned int flags) { - if (flags & IPERM_FLAG_RCU) - return -ECHILD; /* * We don't do permission checks on the internal objects. * Permissions are determined by the "owning" object. From 1aec7036d0c2996c86ce483ca0a28f3b20807b43 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:42:00 -0400 Subject: [PATCH 582/595] proc_sys_permission() is OK in RCU mode nothing blocking there, since all instances of sysctl ->permissions() method are non-blocking - both of them, that is. Signed-off-by: Al Viro --- fs/proc/proc_sysctl.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index f50133c11c24..d167de365a8d 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -304,9 +304,6 @@ static int proc_sys_permission(struct inode *inode, int mask,unsigned int flags) struct ctl_table *table; int error; - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - /* Executable files are not allowed under /proc/sys/ */ if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) return -EACCES; From 6291176bcd71a2766a19a10cbd9bab07d289e1d7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 19:20:48 -0400 Subject: [PATCH 583/595] kill obsolete comment for follow_down() Signed-off-by: Al Viro --- fs/namei.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 9e425e7e6c8f..975c40620fe9 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1011,9 +1011,6 @@ static int follow_dotdot_rcu(struct nameidata *nd) * Follow down to the covering mount currently visible to userspace. At each * point, the filesystem owning that dentry may be queried as to whether the * caller is permitted to proceed or not. - * - * Care must be taken as namespace_sem may be held (indicated by mounting_here - * being true). */ int follow_down(struct path *path) { From 8e833fd2e1f0107ee7a4b6bc4de3c9f0e9b0ed41 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 19 Jun 2011 01:56:53 -0400 Subject: [PATCH 584/595] fix comment in generic_permission() CAP_DAC_OVERRIDE is enough for MAY_EXEC on directory, even if no exec bits are set. Signed-off-by: Al Viro --- fs/namei.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index 975c40620fe9..0223c41fb114 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -238,7 +238,8 @@ int generic_permission(struct inode *inode, int mask, unsigned int flags, /* * Read/write DACs are always overridable. - * Executable DACs are overridable if at least one exec bit is set. + * Executable DACs are overridable for all directories and + * for non-directories that have least one exec bit set. */ if (!(mask & MAY_EXEC) || execute_ok(inode)) if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) From 482e0cd3dbaa70f2a2bead4b5f2c0d203ef654ba Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 19 Jun 2011 13:01:04 -0400 Subject: [PATCH 585/595] devcgroup_inode_permission: take "is it a device node" checks to inlined wrapper inode_permission() calls devcgroup_inode_permission() and almost all such calls are _not_ for device nodes; let's at least keep the common path straight... Signed-off-by: Al Viro --- include/linux/device_cgroup.h | 10 +++++++++- security/device_cgroup.c | 8 +------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/linux/device_cgroup.h b/include/linux/device_cgroup.h index 0b0d9c39ed67..7aad1f440867 100644 --- a/include/linux/device_cgroup.h +++ b/include/linux/device_cgroup.h @@ -2,8 +2,16 @@ #include #ifdef CONFIG_CGROUP_DEVICE -extern int devcgroup_inode_permission(struct inode *inode, int mask); +extern int __devcgroup_inode_permission(struct inode *inode, int mask); extern int devcgroup_inode_mknod(int mode, dev_t dev); +static inline int devcgroup_inode_permission(struct inode *inode, int mask) +{ + if (likely(!inode->i_rdev)) + return 0; + if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode)) + return 0; + return __devcgroup_inode_permission(inode, mask); +} #else static inline int devcgroup_inode_permission(struct inode *inode, int mask) { return 0; } diff --git a/security/device_cgroup.c b/security/device_cgroup.c index cd1f779fa51d..1be68269e1c2 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -474,17 +474,11 @@ struct cgroup_subsys devices_subsys = { .subsys_id = devices_subsys_id, }; -int devcgroup_inode_permission(struct inode *inode, int mask) +int __devcgroup_inode_permission(struct inode *inode, int mask) { struct dev_cgroup *dev_cgroup; struct dev_whitelist_item *wh; - dev_t device = inode->i_rdev; - if (!device) - return 0; - if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode)) - return 0; - rcu_read_lock(); dev_cgroup = task_devcgroup(current); From c82b9d7fe7464aec78210544948564ffe3bb2d2b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 19 Jun 2011 20:26:15 +0000 Subject: [PATCH 586/595] netxen: fix race in skb->len access As soon as skb is given to hardware, TX completion can free skb under us. Therefore, we should update dev stats before kicking the device. Signed-off-by: Eric Dumazet CC: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index b644383017f9..c0788a31ff0f 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1965,11 +1965,11 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) netxen_tso_check(netdev, tx_ring, first_desc, skb); - netxen_nic_update_cmd_producer(adapter, tx_ring); - adapter->stats.txbytes += skb->len; adapter->stats.xmitcalled++; + netxen_nic_update_cmd_producer(adapter, tx_ring); + return NETDEV_TX_OK; drop_packet: From 8ad2475e3555346fbd738e77da12578b97d10505 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 19 Jun 2011 22:31:20 +0000 Subject: [PATCH 587/595] ipv4, ping: Remove duplicate icmp.h include Remove the duplicate inclusion of net/icmp.h from net/ipv4/ping.c Signed-off-by: Jesper Juhl Signed-off-by: David S. Miller --- net/ipv4/ping.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 9aaa67165f42..39b403f854c6 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include From 384420409d9b5d4443940abace49363d26135412 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Sun, 19 Jun 2011 21:48:06 +0000 Subject: [PATCH 588/595] pxa168_eth: fix race in transmit path. Because the socket buffer is freed in the completion interrupt, it is not safe to access it after submitting it to the hardware. Cc: stable@kernel.org Cc: Sachin Sanap Cc: Zhangfei Gao Cc: Philip Rakity Signed-off-by: Richard Cochran Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/pxa168_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c index 89f7540d90f9..5f597ca592bb 100644 --- a/drivers/net/pxa168_eth.c +++ b/drivers/net/pxa168_eth.c @@ -1273,7 +1273,7 @@ static int pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) wmb(); wrl(pep, SDMA_CMD, SDMA_CMD_TXDH | SDMA_CMD_ERD); - stats->tx_bytes += skb->len; + stats->tx_bytes += length; stats->tx_packets++; dev->trans_start = jiffies; if (pep->tx_ring_size - pep->tx_desc_count <= 1) { From fdb9c3cd5124c9a6e4c824ed2bca5b4602e84a1a Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 21 Apr 2011 23:09:11 +0000 Subject: [PATCH 589/595] msm: timer: Fix DGT rate on 8960 and 8660 The DGT runs at 27 MHz divided by 4 on 8660 and 8960. Signed-off-by: Stephen Boyd Signed-off-by: David Brown --- arch/arm/mach-msm/timer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 2232032181be..63621f152c98 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -57,10 +57,12 @@ enum timer_location { #if defined(CONFIG_ARCH_QSD8X50) #define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */ #define MSM_DGT_SHIFT (0) -#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60) || \ - defined(CONFIG_ARCH_MSM8960) +#elif defined(CONFIG_ARCH_MSM7X30) #define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */ #define MSM_DGT_SHIFT (0) +#elif defined(CONFIG_ARCH_MSM8X60) || defined(CONFIG_ARCH_MSM8960) +#define DGT_HZ (27000000 / 4) /* 27 MHz (PXO) / 4 by default */ +#define MSM_DGT_SHIFT (0) #else #define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */ #define MSM_DGT_SHIFT (5) From a377e187df725fe7e62d2cec59ec290c5a605d93 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 20 Jun 2011 13:00:31 -0400 Subject: [PATCH 590/595] drm/radeon/kms/r6xx+: voltage fixes 0xff01 is not an actual voltage value, but a flag for the driver. If the power state as that value, skip setting the voltage. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 6 ++++++ drivers/gpu/drm/radeon/r600.c | 3 +++ drivers/gpu/drm/radeon/radeon_atombios.c | 4 ++++ drivers/gpu/drm/radeon/rv770.c | 3 +++ 4 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 7162b7bacac0..445af7981637 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -140,11 +140,17 @@ void evergreen_pm_misc(struct radeon_device *rdev) struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; if (voltage->type == VOLTAGE_SW) { + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage->voltage == 0xff01) + return; if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) { radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); rdev->pm.current_vddc = voltage->voltage; DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage); } + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage->vddci == 0xff01) + return; if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) { radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI); rdev->pm.current_vddci = voltage->vddci; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index dc9fde38ef49..f79d2ccb6755 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -590,6 +590,9 @@ void r600_pm_misc(struct radeon_device *rdev) struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage->voltage == 0xff01) + return; if (voltage->voltage != rdev->pm.current_vddc) { radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); rdev->pm.current_vddc = voltage->voltage; diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index fa62a503ae70..1e725d9f767f 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2607,6 +2607,10 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) return; + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage_level == 0xff01) + return; + switch (crev) { case 1: args.v1.ucVoltageType = voltage_type; diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index ef8a5babe9f7..6f508ffd1035 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -105,6 +105,9 @@ void rv770_pm_misc(struct radeon_device *rdev) struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { + /* 0xff01 is a flag rather then an actual voltage */ + if (voltage->voltage == 0xff01) + return; if (voltage->voltage != rdev->pm.current_vddc) { radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); rdev->pm.current_vddc = voltage->voltage; From 79568f5be06c91071697c065f01f3ebfbeb25a61 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 20 Jun 2011 20:13:49 -0700 Subject: [PATCH 591/595] vfs: i_state needs to be 'unsigned long' for now Commit 13e12d14e2dc ("vfs: reorganize 'struct inode' layout a bit") moved things around a bit changed i_state to be unsigned int instead of unsigned long. That was to help structure layout for the 64-bit case, and shrink 'struct inode' a bit (admittedly that only happened when spinlock debugging was on and i_flags didn't pack with i_lock). However, Meelis Roos reports that this results in unaligned exceptions on sprc, and it turns out that the bit-locking primitives that we use for the I_NEW bit want to use the bitops. Which want 'unsigned long', not 'unsigned int'. We really should fix the bit locking code to not have that kind of requirement, but that's a much bigger change. So for now, revert that field back to 'unsigned long' (but keep the other re-ordering changes from the commit that caused this). Andi points out that we have played games with this in 'struct page', so it's solvable with other hacks too, but since right now the struct inode size advantage only happens with some rare config options, it's not worth fighting. It _would_ be worth fixing the bitlocking code, though. Especially since there is no type safety in the bitlocking code (this never caused any warnings, and worked fine on x86-64, because the bitlocks take a 'void *' and x86-64 doesn't care that deeply about alignment). So it's currently a very easy problem to trigger by mistake and never notice. Reported-by: Meelis Roos Cc: Andi Kleen Cc: David Miller Signed-off-by: Linus Torvalds --- include/linux/fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 1c777878f1ea..6e73e2e9ae33 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -744,7 +744,7 @@ struct inode { spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ unsigned int i_flags; - unsigned int i_state; + unsigned long i_state; #ifdef CONFIG_SECURITY void *i_security; #endif From 56299378726d5f2ba8d3c8cbbd13cb280ba45e4f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 20 Jun 2011 20:25:46 -0700 Subject: [PATCH 592/595] Linux 3.0-rc4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0499c2ee8541..41330a06e4ec 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 0 SUBLEVEL = 0 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = Sneaky Weasel # *DOCUMENTATION* From efc2924e733631a64c0afed8dbba2741d186998c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 6 Jun 2011 17:12:49 -0700 Subject: [PATCH 593/595] drm/i915: Call intel_enable_plane from i9xx_crtc_mode_set (again) This change got placed in the ironlake path instead of the 9xx path during a recent code shuffle. Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 81a9059b6a94..aa43e7be6053 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4687,6 +4687,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(DSPCNTR(plane), dspcntr); POSTING_READ(DSPCNTR(plane)); + intel_enable_plane(dev_priv, plane, pipe); ret = intel_pipe_set_base(crtc, x, y, old_fb); @@ -5217,8 +5218,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(DSPCNTR(plane), dspcntr); POSTING_READ(DSPCNTR(plane)); - if (!HAS_PCH_SPLIT(dev)) - intel_enable_plane(dev_priv, plane, pipe); ret = intel_pipe_set_base(crtc, x, y, old_fb); From ec6a890dfed7dd245beba5e5bcdfcffbd934c284 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 21 Jun 2011 18:37:59 +0100 Subject: [PATCH 594/595] drm/i915: Apply HWSTAM workaround for BSD ring on SandyBridge ...we need to apply exactly the same workaround for missing interrupts from BSD as for the BLT ring, apparently. See also commit 498e720b96379d8ee9c294950a01534a73defcf3 (drm/i915: Fix gen6 (SNB) missed BLT ring interrupts). Reported-and-tested-by: nkalkhof@web.de Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38529 Signed-off-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_irq.c | 1 + drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 9e34a1abeb61..ae2b49969b99 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1749,6 +1749,7 @@ void ironlake_irq_preinstall(struct drm_device *dev) * happens. */ I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT); + I915_WRITE(GEN6_BSD_HWSTAM, ~GEN6_BSD_USER_INTERRUPT); } /* XXX hotplug from PCH */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2f967af8e62e..5d5def756c9e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -531,6 +531,7 @@ #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0 #define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3) +#define GEN6_BSD_HWSTAM 0x12098 #define GEN6_BSD_IMR 0x120a8 #define GEN6_BSD_USER_INTERRUPT (1 << 12) From e92d03bff9a0d0bcbb812c9b1290ca96c9338d45 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 14 Jun 2011 16:43:09 -0700 Subject: [PATCH 595/595] Revert "drm/i915: Kill GTT mappings when moving from GTT domain" This reverts commit 4a684a4117abd756291969336af454e8a958802f. Userland has always been required to set the object's domain to GTT before using it through a GTT mapping, it's not something that the kernel is supposed to enforce. (The pagefault support is so that we can handle multiple mappings without userland having to pin across them, not so that userland can use GTT after GPU domains without telling the kernel). Fixes 19.2% +/- 0.8% (n=6) performance regression in cairo-gl firefox-talos-gfx on my T420 latop. Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_gem.c | 10 ++++------ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 4 ---- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 94c84d744100..c6389de53161 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1219,11 +1219,11 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ret = i915_gem_object_bind_to_gtt(obj, 0, true); if (ret) goto unlock; - } - ret = i915_gem_object_set_to_gtt_domain(obj, write); - if (ret) - goto unlock; + ret = i915_gem_object_set_to_gtt_domain(obj, write); + if (ret) + goto unlock; + } if (obj->tiling_mode == I915_TILING_NONE) ret = i915_gem_object_put_fence(obj); @@ -2926,8 +2926,6 @@ i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj) */ wmb(); - i915_gem_release_mmap(obj); - old_write_domain = obj->base.write_domain; obj->base.write_domain = 0; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 20a4cc5b818f..4934cf84c320 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -187,10 +187,6 @@ i915_gem_object_set_to_gpu_domain(struct drm_i915_gem_object *obj, if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) i915_gem_clflush_object(obj); - /* blow away mappings if mapped through GTT */ - if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_GTT) - i915_gem_release_mmap(obj); - if (obj->base.pending_write_domain) cd->flips |= atomic_read(&obj->pending_flip);