4685 lines
149 KiB
Diff
4685 lines
149 KiB
Diff
|
diff --git a/Makefile b/Makefile
|
||
|
index 40d1e3b..80bb4fd 100644
|
||
|
--- a/Makefile
|
||
|
+++ b/Makefile
|
||
|
@@ -1,6 +1,6 @@
|
||
|
VERSION = 3
|
||
|
PATCHLEVEL = 2
|
||
|
-SUBLEVEL = 23
|
||
|
+SUBLEVEL = 24
|
||
|
EXTRAVERSION =
|
||
|
NAME = Saber-toothed Squirrel
|
||
|
|
||
|
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
|
||
|
index 33ecd0c..b1e05cc 100644
|
||
|
--- a/arch/arm/plat-samsung/adc.c
|
||
|
+++ b/arch/arm/plat-samsung/adc.c
|
||
|
@@ -157,11 +157,13 @@ int s3c_adc_start(struct s3c_adc_client *client,
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
- if (client->is_ts && adc->ts_pend)
|
||
|
- return -EAGAIN;
|
||
|
-
|
||
|
spin_lock_irqsave(&adc->lock, flags);
|
||
|
|
||
|
+ if (client->is_ts && adc->ts_pend) {
|
||
|
+ spin_unlock_irqrestore(&adc->lock, flags);
|
||
|
+ return -EAGAIN;
|
||
|
+ }
|
||
|
+
|
||
|
client->channel = channel;
|
||
|
client->nr_samples = nr_samples;
|
||
|
|
||
|
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
|
||
|
index 97f8bf6..adda036 100644
|
||
|
--- a/arch/mips/include/asm/thread_info.h
|
||
|
+++ b/arch/mips/include/asm/thread_info.h
|
||
|
@@ -60,6 +60,8 @@ struct thread_info {
|
||
|
register struct thread_info *__current_thread_info __asm__("$28");
|
||
|
#define current_thread_info() __current_thread_info
|
||
|
|
||
|
+#endif /* !__ASSEMBLY__ */
|
||
|
+
|
||
|
/* thread information allocation */
|
||
|
#if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_32BIT)
|
||
|
#define THREAD_SIZE_ORDER (1)
|
||
|
@@ -97,8 +99,6 @@ register struct thread_info *__current_thread_info __asm__("$28");
|
||
|
|
||
|
#define free_thread_info(info) kfree(info)
|
||
|
|
||
|
-#endif /* !__ASSEMBLY__ */
|
||
|
-
|
||
|
#define PREEMPT_ACTIVE 0x10000000
|
||
|
|
||
|
/*
|
||
|
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
|
||
|
index a81176f..be281c6 100644
|
||
|
--- a/arch/mips/kernel/vmlinux.lds.S
|
||
|
+++ b/arch/mips/kernel/vmlinux.lds.S
|
||
|
@@ -1,5 +1,6 @@
|
||
|
#include <asm/asm-offsets.h>
|
||
|
#include <asm/page.h>
|
||
|
+#include <asm/thread_info.h>
|
||
|
#include <asm-generic/vmlinux.lds.h>
|
||
|
|
||
|
#undef mips
|
||
|
@@ -73,7 +74,7 @@ SECTIONS
|
||
|
.data : { /* Data */
|
||
|
. = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */
|
||
|
|
||
|
- INIT_TASK_DATA(PAGE_SIZE)
|
||
|
+ INIT_TASK_DATA(THREAD_SIZE)
|
||
|
NOSAVE_DATA
|
||
|
CACHELINE_ALIGNED_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
|
||
|
READ_MOSTLY_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
|
||
|
diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h
|
||
|
index 98b7c4b..fa3f921 100644
|
||
|
--- a/arch/powerpc/include/asm/cputime.h
|
||
|
+++ b/arch/powerpc/include/asm/cputime.h
|
||
|
@@ -126,11 +126,11 @@ static inline u64 cputime64_to_jiffies64(const cputime_t ct)
|
||
|
/*
|
||
|
* Convert cputime <-> microseconds
|
||
|
*/
|
||
|
-extern u64 __cputime_msec_factor;
|
||
|
+extern u64 __cputime_usec_factor;
|
||
|
|
||
|
static inline unsigned long cputime_to_usecs(const cputime_t ct)
|
||
|
{
|
||
|
- return mulhdu(ct, __cputime_msec_factor) * USEC_PER_MSEC;
|
||
|
+ return mulhdu(ct, __cputime_usec_factor);
|
||
|
}
|
||
|
|
||
|
static inline cputime_t usecs_to_cputime(const unsigned long us)
|
||
|
@@ -143,7 +143,7 @@ static inline cputime_t usecs_to_cputime(const unsigned long us)
|
||
|
sec = us / 1000000;
|
||
|
if (ct) {
|
||
|
ct *= tb_ticks_per_sec;
|
||
|
- do_div(ct, 1000);
|
||
|
+ do_div(ct, 1000000);
|
||
|
}
|
||
|
if (sec)
|
||
|
ct += (cputime_t) sec * tb_ticks_per_sec;
|
||
|
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
|
||
|
index 5db163c..ec8affe 100644
|
||
|
--- a/arch/powerpc/kernel/time.c
|
||
|
+++ b/arch/powerpc/kernel/time.c
|
||
|
@@ -168,13 +168,13 @@ EXPORT_SYMBOL_GPL(ppc_tb_freq);
|
||
|
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
|
||
|
/*
|
||
|
* Factors for converting from cputime_t (timebase ticks) to
|
||
|
- * jiffies, milliseconds, seconds, and clock_t (1/USER_HZ seconds).
|
||
|
+ * jiffies, microseconds, seconds, and clock_t (1/USER_HZ seconds).
|
||
|
* These are all stored as 0.64 fixed-point binary fractions.
|
||
|
*/
|
||
|
u64 __cputime_jiffies_factor;
|
||
|
EXPORT_SYMBOL(__cputime_jiffies_factor);
|
||
|
-u64 __cputime_msec_factor;
|
||
|
-EXPORT_SYMBOL(__cputime_msec_factor);
|
||
|
+u64 __cputime_usec_factor;
|
||
|
+EXPORT_SYMBOL(__cputime_usec_factor);
|
||
|
u64 __cputime_sec_factor;
|
||
|
EXPORT_SYMBOL(__cputime_sec_factor);
|
||
|
u64 __cputime_clockt_factor;
|
||
|
@@ -192,8 +192,8 @@ static void calc_cputime_factors(void)
|
||
|
|
||
|
div128_by_32(HZ, 0, tb_ticks_per_sec, &res);
|
||
|
__cputime_jiffies_factor = res.result_low;
|
||
|
- div128_by_32(1000, 0, tb_ticks_per_sec, &res);
|
||
|
- __cputime_msec_factor = res.result_low;
|
||
|
+ div128_by_32(1000000, 0, tb_ticks_per_sec, &res);
|
||
|
+ __cputime_usec_factor = res.result_low;
|
||
|
div128_by_32(1, 0, tb_ticks_per_sec, &res);
|
||
|
__cputime_sec_factor = res.result_low;
|
||
|
div128_by_32(USER_HZ, 0, tb_ticks_per_sec, &res);
|
||
|
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
|
||
|
index 4558f0d..479d03c 100644
|
||
|
--- a/arch/x86/kernel/acpi/boot.c
|
||
|
+++ b/arch/x86/kernel/acpi/boot.c
|
||
|
@@ -416,12 +416,14 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
- if (intsrc->source_irq == 0 && intsrc->global_irq == 2) {
|
||
|
+ if (intsrc->source_irq == 0) {
|
||
|
if (acpi_skip_timer_override) {
|
||
|
- printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
|
||
|
+ printk(PREFIX "BIOS IRQ0 override ignored.\n");
|
||
|
return 0;
|
||
|
}
|
||
|
- if (acpi_fix_pin2_polarity && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) {
|
||
|
+
|
||
|
+ if ((intsrc->global_irq == 2) && acpi_fix_pin2_polarity
|
||
|
+ && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) {
|
||
|
intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK;
|
||
|
printk(PREFIX "BIOS IRQ0 pin2 override: forcing polarity to high active.\n");
|
||
|
}
|
||
|
@@ -1327,17 +1329,12 @@ static int __init dmi_disable_acpi(const struct dmi_system_id *d)
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- * Force ignoring BIOS IRQ0 pin2 override
|
||
|
+ * Force ignoring BIOS IRQ0 override
|
||
|
*/
|
||
|
static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d)
|
||
|
{
|
||
|
- /*
|
||
|
- * The ati_ixp4x0_rev() early PCI quirk should have set
|
||
|
- * the acpi_skip_timer_override flag already:
|
||
|
- */
|
||
|
if (!acpi_skip_timer_override) {
|
||
|
- WARN(1, KERN_ERR "ati_ixp4x0 quirk not complete.\n");
|
||
|
- pr_notice("%s detected: Ignoring BIOS IRQ0 pin2 override\n",
|
||
|
+ pr_notice("%s detected: Ignoring BIOS IRQ0 override\n",
|
||
|
d->ident);
|
||
|
acpi_skip_timer_override = 1;
|
||
|
}
|
||
|
@@ -1431,7 +1428,7 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = {
|
||
|
* is enabled. This input is incorrectly designated the
|
||
|
* ISA IRQ 0 via an interrupt source override even though
|
||
|
* it is wired to the output of the master 8259A and INTIN0
|
||
|
- * is not connected at all. Force ignoring BIOS IRQ0 pin2
|
||
|
+ * is not connected at all. Force ignoring BIOS IRQ0
|
||
|
* override in that cases.
|
||
|
*/
|
||
|
{
|
||
|
@@ -1466,6 +1463,14 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = {
|
||
|
DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6715b"),
|
||
|
},
|
||
|
},
|
||
|
+ {
|
||
|
+ .callback = dmi_ignore_irq0_timer_override,
|
||
|
+ .ident = "FUJITSU SIEMENS",
|
||
|
+ .matches = {
|
||
|
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
|
||
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"),
|
||
|
+ },
|
||
|
+ },
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
|
||
|
index 37a458b..e61f79c 100644
|
||
|
--- a/arch/x86/kernel/reboot.c
|
||
|
+++ b/arch/x86/kernel/reboot.c
|
||
|
@@ -460,6 +460,14 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
|
||
|
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"),
|
||
|
},
|
||
|
},
|
||
|
+ { /* Handle problems with rebooting on the Precision M6600. */
|
||
|
+ .callback = set_pci_reboot,
|
||
|
+ .ident = "Dell OptiPlex 990",
|
||
|
+ .matches = {
|
||
|
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"),
|
||
|
+ },
|
||
|
+ },
|
||
|
{ }
|
||
|
};
|
||
|
|
||
|
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
|
||
|
index 688be8a..9e76a32 100644
|
||
|
--- a/block/scsi_ioctl.c
|
||
|
+++ b/block/scsi_ioctl.c
|
||
|
@@ -721,11 +721,14 @@ int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
+ if (capable(CAP_SYS_RAWIO))
|
||
|
+ return 0;
|
||
|
+
|
||
|
/* In particular, rule out all resets and host-specific ioctls. */
|
||
|
printk_ratelimited(KERN_WARNING
|
||
|
"%s: sending ioctl %x to a partition!\n", current->comm, cmd);
|
||
|
|
||
|
- return capable(CAP_SYS_RAWIO) ? 0 : -ENOTTY;
|
||
|
+ return -ENOTTY;
|
||
|
}
|
||
|
EXPORT_SYMBOL(scsi_verify_blk_ioctl);
|
||
|
|
||
|
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
|
||
|
index c850de4..eff7222 100644
|
||
|
--- a/drivers/acpi/processor_core.c
|
||
|
+++ b/drivers/acpi/processor_core.c
|
||
|
@@ -189,10 +189,12 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
|
||
|
* Processor (CPU3, 0x03, 0x00000410, 0x06) {}
|
||
|
* }
|
||
|
*
|
||
|
- * Ignores apic_id and always return 0 for CPU0's handle.
|
||
|
+ * Ignores apic_id and always returns 0 for the processor
|
||
|
+ * handle with acpi id 0 if nr_cpu_ids is 1.
|
||
|
+ * This should be the case if SMP tables are not found.
|
||
|
* Return -1 for other CPU's handle.
|
||
|
*/
|
||
|
- if (acpi_id == 0)
|
||
|
+ if (nr_cpu_ids <= 1 && acpi_id == 0)
|
||
|
return acpi_id;
|
||
|
else
|
||
|
return apic_id;
|
||
|
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
|
||
|
index ca191ff..ed6bc52 100644
|
||
|
--- a/drivers/acpi/sleep.c
|
||
|
+++ b/drivers/acpi/sleep.c
|
||
|
@@ -702,8 +702,8 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
|
||
|
* can wake the system. _S0W may be valid, too.
|
||
|
*/
|
||
|
if (acpi_target_sleep_state == ACPI_STATE_S0 ||
|
||
|
- (device_may_wakeup(dev) &&
|
||
|
- adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
|
||
|
+ (device_may_wakeup(dev) && adev->wakeup.flags.valid &&
|
||
|
+ adev->wakeup.sleep_state >= acpi_target_sleep_state)) {
|
||
|
acpi_status status;
|
||
|
|
||
|
acpi_method[3] = 'W';
|
||
|
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
|
||
|
index 9f66181..240a244 100644
|
||
|
--- a/drivers/acpi/sysfs.c
|
||
|
+++ b/drivers/acpi/sysfs.c
|
||
|
@@ -173,7 +173,7 @@ static int param_set_trace_state(const char *val, struct kernel_param *kp)
|
||
|
{
|
||
|
int result = 0;
|
||
|
|
||
|
- if (!strncmp(val, "enable", strlen("enable") - 1)) {
|
||
|
+ if (!strncmp(val, "enable", strlen("enable"))) {
|
||
|
result = acpi_debug_trace(trace_method_name, trace_debug_level,
|
||
|
trace_debug_layer, 0);
|
||
|
if (result)
|
||
|
@@ -181,7 +181,7 @@ static int param_set_trace_state(const char *val, struct kernel_param *kp)
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
- if (!strncmp(val, "disable", strlen("disable") - 1)) {
|
||
|
+ if (!strncmp(val, "disable", strlen("disable"))) {
|
||
|
int name = 0;
|
||
|
result = acpi_debug_trace((char *)&name, trace_debug_level,
|
||
|
trace_debug_layer, 0);
|
||
|
diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c
|
||
|
index 96198f3..a2da8f2 100644
|
||
|
--- a/drivers/gpio/gpio-wm8994.c
|
||
|
+++ b/drivers/gpio/gpio-wm8994.c
|
||
|
@@ -89,8 +89,11 @@ static int wm8994_gpio_direction_out(struct gpio_chip *chip,
|
||
|
struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
|
||
|
struct wm8994 *wm8994 = wm8994_gpio->wm8994;
|
||
|
|
||
|
+ if (value)
|
||
|
+ value = WM8994_GPN_LVL;
|
||
|
+
|
||
|
return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
|
||
|
- WM8994_GPN_DIR, 0);
|
||
|
+ WM8994_GPN_DIR | WM8994_GPN_LVL, value);
|
||
|
}
|
||
|
|
||
|
static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||
|
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
|
||
|
index 6aa7716..cc75c4b 100644
|
||
|
--- a/drivers/gpu/drm/i915/intel_display.c
|
||
|
+++ b/drivers/gpu/drm/i915/intel_display.c
|
||
|
@@ -8043,8 +8043,8 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
|
||
|
I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
|
||
|
|
||
|
if (intel_enable_rc6(dev_priv->dev))
|
||
|
- rc6_mask = GEN6_RC_CTL_RC6p_ENABLE |
|
||
|
- GEN6_RC_CTL_RC6_ENABLE;
|
||
|
+ rc6_mask = GEN6_RC_CTL_RC6_ENABLE |
|
||
|
+ ((IS_GEN7(dev_priv->dev)) ? GEN6_RC_CTL_RC6p_ENABLE : 0);
|
||
|
|
||
|
I915_WRITE(GEN6_RC_CONTROL,
|
||
|
rc6_mask |
|
||
|
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
|
||
|
index 299d238..899c712 100644
|
||
|
--- a/drivers/hid/hid-apple.c
|
||
|
+++ b/drivers/hid/hid-apple.c
|
||
|
@@ -514,6 +514,12 @@ static const struct hid_device_id apple_devices[] = {
|
||
|
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS),
|
||
|
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
|
||
|
+ .driver_data = APPLE_HAS_FN },
|
||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
|
||
|
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
|
||
|
+ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
|
||
|
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
|
||
|
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
|
||
|
index c27b402..95430a0 100644
|
||
|
--- a/drivers/hid/hid-core.c
|
||
|
+++ b/drivers/hid/hid-core.c
|
||
|
@@ -1374,6 +1374,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) },
|
||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
|
||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
|
||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
|
||
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
|
||
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
|
||
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
|
||
|
@@ -1884,6 +1887,7 @@ static const struct hid_device_id hid_ignore_list[] = {
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MCT) },
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) },
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) },
|
||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) },
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) },
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
|
||
|
@@ -1968,6 +1972,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) },
|
||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
|
||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
|
||
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
|
||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
|
||
|
{ }
|
||
|
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
|
||
|
index fba3fc4..7db934d 100644
|
||
|
--- a/drivers/hid/hid-ids.h
|
||
|
+++ b/drivers/hid/hid-ids.h
|
||
|
@@ -125,6 +125,9 @@
|
||
|
#define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI 0x024c
|
||
|
#define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO 0x024d
|
||
|
#define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS 0x024e
|
||
|
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262
|
||
|
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263
|
||
|
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264
|
||
|
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239
|
||
|
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a
|
||
|
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b
|
||
|
@@ -491,6 +494,9 @@
|
||
|
#define USB_DEVICE_ID_CRYSTALTOUCH 0x0006
|
||
|
#define USB_DEVICE_ID_CRYSTALTOUCH_DUAL 0x0007
|
||
|
|
||
|
+#define USB_VENDOR_ID_MADCATZ 0x0738
|
||
|
+#define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540
|
||
|
+
|
||
|
#define USB_VENDOR_ID_MCC 0x09db
|
||
|
#define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
|
||
|
#define USB_DEVICE_ID_MCC_PMD1208LS 0x007a
|
||
|
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
|
||
|
index d912649..1ba7af2 100644
|
||
|
--- a/drivers/hwmon/it87.c
|
||
|
+++ b/drivers/hwmon/it87.c
|
||
|
@@ -2086,7 +2086,7 @@ static void __devinit it87_init_device(struct platform_device *pdev)
|
||
|
|
||
|
/* Start monitoring */
|
||
|
it87_write_value(data, IT87_REG_CONFIG,
|
||
|
- (it87_read_value(data, IT87_REG_CONFIG) & 0x36)
|
||
|
+ (it87_read_value(data, IT87_REG_CONFIG) & 0x3e)
|
||
|
| (update_vbat ? 0x41 : 0x01));
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c
|
||
|
index 61c9cf1..1201a15 100644
|
||
|
--- a/drivers/hwspinlock/hwspinlock_core.c
|
||
|
+++ b/drivers/hwspinlock/hwspinlock_core.c
|
||
|
@@ -345,7 +345,7 @@ int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
|
||
|
spin_lock_init(&hwlock->lock);
|
||
|
hwlock->bank = bank;
|
||
|
|
||
|
- ret = hwspin_lock_register_single(hwlock, i);
|
||
|
+ ret = hwspin_lock_register_single(hwlock, base_id + i);
|
||
|
if (ret)
|
||
|
goto reg_failed;
|
||
|
}
|
||
|
@@ -354,7 +354,7 @@ int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
|
||
|
|
||
|
reg_failed:
|
||
|
while (--i >= 0)
|
||
|
- hwspin_lock_unregister_single(i);
|
||
|
+ hwspin_lock_unregister_single(base_id + i);
|
||
|
return ret;
|
||
|
}
|
||
|
EXPORT_SYMBOL_GPL(hwspin_lock_register);
|
||
|
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
|
||
|
index d728875..2189cbf 100644
|
||
|
--- a/drivers/input/joystick/xpad.c
|
||
|
+++ b/drivers/input/joystick/xpad.c
|
||
|
@@ -142,6 +142,7 @@ static const struct xpad_device {
|
||
|
{ 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX },
|
||
|
{ 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },
|
||
|
{ 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX },
|
||
|
+ { 0x0d2f, 0x0002, "Andamiro Pump It Up pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
|
||
|
{ 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX },
|
||
|
{ 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX },
|
||
|
{ 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX },
|
||
|
@@ -164,6 +165,7 @@ static const struct xpad_device {
|
||
|
{ 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
|
||
|
{ 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
|
||
|
{ 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
|
||
|
+ { 0x1689, 0xfd00, "Razer Onza Tournament Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
|
||
|
{ 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX },
|
||
|
{ 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN }
|
||
|
};
|
||
|
@@ -238,12 +240,14 @@ static struct usb_device_id xpad_table [] = {
|
||
|
XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */
|
||
|
XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */
|
||
|
XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */
|
||
|
+ { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
|
||
|
XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */
|
||
|
XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */
|
||
|
XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
|
||
|
XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */
|
||
|
XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */
|
||
|
- XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */
|
||
|
+ XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */
|
||
|
+ XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */
|
||
|
{ }
|
||
|
};
|
||
|
|
||
|
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
|
||
|
index 5ec617e..ec58f48 100644
|
||
|
--- a/drivers/input/mouse/bcm5974.c
|
||
|
+++ b/drivers/input/mouse/bcm5974.c
|
||
|
@@ -79,6 +79,10 @@
|
||
|
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252
|
||
|
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253
|
||
|
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254
|
||
|
+/* MacbookPro10,1 (unibody, June 2012) */
|
||
|
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262
|
||
|
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263
|
||
|
+#define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264
|
||
|
|
||
|
#define BCM5974_DEVICE(prod) { \
|
||
|
.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
|
||
|
@@ -128,6 +132,10 @@ static const struct usb_device_id bcm5974_table[] = {
|
||
|
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI),
|
||
|
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO),
|
||
|
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS),
|
||
|
+ /* MacbookPro10,1 */
|
||
|
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
|
||
|
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
|
||
|
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
|
||
|
/* Terminating entry */
|
||
|
{}
|
||
|
};
|
||
|
@@ -354,6 +362,18 @@ static const struct bcm5974_config bcm5974_config_table[] = {
|
||
|
{ DIM_X, DIM_X / SN_COORD, -4620, 5140 },
|
||
|
{ DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
|
||
|
},
|
||
|
+ {
|
||
|
+ USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI,
|
||
|
+ USB_DEVICE_ID_APPLE_WELLSPRING7_ISO,
|
||
|
+ USB_DEVICE_ID_APPLE_WELLSPRING7_JIS,
|
||
|
+ HAS_INTEGRATED_BUTTON,
|
||
|
+ 0x84, sizeof(struct bt_data),
|
||
|
+ 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
|
||
|
+ { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
|
||
|
+ { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
|
||
|
+ { DIM_X, DIM_X / SN_COORD, -4750, 5280 },
|
||
|
+ { DIM_Y, DIM_Y / SN_COORD, -150, 6730 }
|
||
|
+ },
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
|
||
|
index f1d5408..a1b8caa 100644
|
||
|
--- a/drivers/iommu/amd_iommu.c
|
||
|
+++ b/drivers/iommu/amd_iommu.c
|
||
|
@@ -59,6 +59,8 @@ static struct protection_domain *pt_domain;
|
||
|
|
||
|
static struct iommu_ops amd_iommu_ops;
|
||
|
|
||
|
+static struct dma_map_ops amd_iommu_dma_ops;
|
||
|
+
|
||
|
/*
|
||
|
* general struct to manage commands send to an IOMMU
|
||
|
*/
|
||
|
@@ -1878,6 +1880,11 @@ static int device_change_notifier(struct notifier_block *nb,
|
||
|
list_add_tail(&dma_domain->list, &iommu_pd_list);
|
||
|
spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
|
||
|
|
||
|
+ if (!iommu_pass_through)
|
||
|
+ dev->archdata.dma_ops = &amd_iommu_dma_ops;
|
||
|
+ else
|
||
|
+ dev->archdata.dma_ops = &nommu_dma_ops;
|
||
|
+
|
||
|
break;
|
||
|
case BUS_NOTIFY_DEL_DEVICE:
|
||
|
|
||
|
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
|
||
|
index 6269eb0..ef2d493 100644
|
||
|
--- a/drivers/iommu/amd_iommu_init.c
|
||
|
+++ b/drivers/iommu/amd_iommu_init.c
|
||
|
@@ -1468,6 +1468,8 @@ static int __init amd_iommu_init(void)
|
||
|
|
||
|
register_syscore_ops(&amd_iommu_syscore_ops);
|
||
|
|
||
|
+ x86_platform.iommu_shutdown = disable_iommus;
|
||
|
+
|
||
|
if (iommu_pass_through)
|
||
|
goto out;
|
||
|
|
||
|
@@ -1476,7 +1478,6 @@ static int __init amd_iommu_init(void)
|
||
|
else
|
||
|
printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n");
|
||
|
|
||
|
- x86_platform.iommu_shutdown = disable_iommus;
|
||
|
out:
|
||
|
return ret;
|
||
|
|
||
|
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
|
||
|
index 9bfd057..dae2b7a 100644
|
||
|
--- a/drivers/md/dm-raid1.c
|
||
|
+++ b/drivers/md/dm-raid1.c
|
||
|
@@ -1080,6 +1080,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
||
|
ti->split_io = dm_rh_get_region_size(ms->rh);
|
||
|
ti->num_flush_requests = 1;
|
||
|
ti->num_discard_requests = 1;
|
||
|
+ ti->discard_zeroes_data_unsupported = 1;
|
||
|
|
||
|
ms->kmirrord_wq = alloc_workqueue("kmirrord",
|
||
|
WQ_NON_REENTRANT | WQ_MEM_RECLAIM, 0);
|
||
|
@@ -1210,7 +1211,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio,
|
||
|
* We need to dec pending if this was a write.
|
||
|
*/
|
||
|
if (rw == WRITE) {
|
||
|
- if (!(bio->bi_rw & REQ_FLUSH))
|
||
|
+ if (!(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD)))
|
||
|
dm_rh_dec(ms->rh, map_context->ll);
|
||
|
return error;
|
||
|
}
|
||
|
diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c
|
||
|
index 7771ed2..69732e0 100644
|
||
|
--- a/drivers/md/dm-region-hash.c
|
||
|
+++ b/drivers/md/dm-region-hash.c
|
||
|
@@ -404,6 +404,9 @@ void dm_rh_mark_nosync(struct dm_region_hash *rh, struct bio *bio)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
+ if (bio->bi_rw & REQ_DISCARD)
|
||
|
+ return;
|
||
|
+
|
||
|
/* We must inform the log that the sync count has changed. */
|
||
|
log->type->set_region_sync(log, region, 0);
|
||
|
|
||
|
@@ -524,7 +527,7 @@ void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios)
|
||
|
struct bio *bio;
|
||
|
|
||
|
for (bio = bios->head; bio; bio = bio->bi_next) {
|
||
|
- if (bio->bi_rw & REQ_FLUSH)
|
||
|
+ if (bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))
|
||
|
continue;
|
||
|
rh_inc(rh, dm_rh_bio_to_region(rh, bio));
|
||
|
}
|
||
|
diff --git a/drivers/md/md.c b/drivers/md/md.c
|
||
|
index 700ecae..d8646d7 100644
|
||
|
--- a/drivers/md/md.c
|
||
|
+++ b/drivers/md/md.c
|
||
|
@@ -3700,8 +3700,8 @@ array_state_show(struct mddev *mddev, char *page)
|
||
|
return sprintf(page, "%s\n", array_states[st]);
|
||
|
}
|
||
|
|
||
|
-static int do_md_stop(struct mddev * mddev, int ro, int is_open);
|
||
|
-static int md_set_readonly(struct mddev * mddev, int is_open);
|
||
|
+static int do_md_stop(struct mddev * mddev, int ro, struct block_device *bdev);
|
||
|
+static int md_set_readonly(struct mddev * mddev, struct block_device *bdev);
|
||
|
static int do_md_run(struct mddev * mddev);
|
||
|
static int restart_array(struct mddev *mddev);
|
||
|
|
||
|
@@ -3717,14 +3717,14 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
|
||
|
/* stopping an active array */
|
||
|
if (atomic_read(&mddev->openers) > 0)
|
||
|
return -EBUSY;
|
||
|
- err = do_md_stop(mddev, 0, 0);
|
||
|
+ err = do_md_stop(mddev, 0, NULL);
|
||
|
break;
|
||
|
case inactive:
|
||
|
/* stopping an active array */
|
||
|
if (mddev->pers) {
|
||
|
if (atomic_read(&mddev->openers) > 0)
|
||
|
return -EBUSY;
|
||
|
- err = do_md_stop(mddev, 2, 0);
|
||
|
+ err = do_md_stop(mddev, 2, NULL);
|
||
|
} else
|
||
|
err = 0; /* already inactive */
|
||
|
break;
|
||
|
@@ -3732,7 +3732,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
|
||
|
break; /* not supported yet */
|
||
|
case readonly:
|
||
|
if (mddev->pers)
|
||
|
- err = md_set_readonly(mddev, 0);
|
||
|
+ err = md_set_readonly(mddev, NULL);
|
||
|
else {
|
||
|
mddev->ro = 1;
|
||
|
set_disk_ro(mddev->gendisk, 1);
|
||
|
@@ -3742,7 +3742,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
|
||
|
case read_auto:
|
||
|
if (mddev->pers) {
|
||
|
if (mddev->ro == 0)
|
||
|
- err = md_set_readonly(mddev, 0);
|
||
|
+ err = md_set_readonly(mddev, NULL);
|
||
|
else if (mddev->ro == 1)
|
||
|
err = restart_array(mddev);
|
||
|
if (err == 0) {
|
||
|
@@ -5078,15 +5078,17 @@ void md_stop(struct mddev *mddev)
|
||
|
}
|
||
|
EXPORT_SYMBOL_GPL(md_stop);
|
||
|
|
||
|
-static int md_set_readonly(struct mddev *mddev, int is_open)
|
||
|
+static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
|
||
|
{
|
||
|
int err = 0;
|
||
|
mutex_lock(&mddev->open_mutex);
|
||
|
- if (atomic_read(&mddev->openers) > is_open) {
|
||
|
+ if (atomic_read(&mddev->openers) > !!bdev) {
|
||
|
printk("md: %s still in use.\n",mdname(mddev));
|
||
|
err = -EBUSY;
|
||
|
goto out;
|
||
|
}
|
||
|
+ if (bdev)
|
||
|
+ sync_blockdev(bdev);
|
||
|
if (mddev->pers) {
|
||
|
__md_stop_writes(mddev);
|
||
|
|
||
|
@@ -5108,18 +5110,26 @@ out:
|
||
|
* 0 - completely stop and dis-assemble array
|
||
|
* 2 - stop but do not disassemble array
|
||
|
*/
|
||
|
-static int do_md_stop(struct mddev * mddev, int mode, int is_open)
|
||
|
+static int do_md_stop(struct mddev * mddev, int mode,
|
||
|
+ struct block_device *bdev)
|
||
|
{
|
||
|
struct gendisk *disk = mddev->gendisk;
|
||
|
struct md_rdev *rdev;
|
||
|
|
||
|
mutex_lock(&mddev->open_mutex);
|
||
|
- if (atomic_read(&mddev->openers) > is_open ||
|
||
|
+ if (atomic_read(&mddev->openers) > !!bdev ||
|
||
|
mddev->sysfs_active) {
|
||
|
printk("md: %s still in use.\n",mdname(mddev));
|
||
|
mutex_unlock(&mddev->open_mutex);
|
||
|
return -EBUSY;
|
||
|
}
|
||
|
+ if (bdev)
|
||
|
+ /* It is possible IO was issued on some other
|
||
|
+ * open file which was closed before we took ->open_mutex.
|
||
|
+ * As that was not the last close __blkdev_put will not
|
||
|
+ * have called sync_blockdev, so we must.
|
||
|
+ */
|
||
|
+ sync_blockdev(bdev);
|
||
|
|
||
|
if (mddev->pers) {
|
||
|
if (mddev->ro)
|
||
|
@@ -5193,7 +5203,7 @@ static void autorun_array(struct mddev *mddev)
|
||
|
err = do_md_run(mddev);
|
||
|
if (err) {
|
||
|
printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
|
||
|
- do_md_stop(mddev, 0, 0);
|
||
|
+ do_md_stop(mddev, 0, NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -6184,11 +6194,11 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
|
||
|
goto done_unlock;
|
||
|
|
||
|
case STOP_ARRAY:
|
||
|
- err = do_md_stop(mddev, 0, 1);
|
||
|
+ err = do_md_stop(mddev, 0, bdev);
|
||
|
goto done_unlock;
|
||
|
|
||
|
case STOP_ARRAY_RO:
|
||
|
- err = md_set_readonly(mddev, 1);
|
||
|
+ err = md_set_readonly(mddev, bdev);
|
||
|
goto done_unlock;
|
||
|
|
||
|
case BLKROSET:
|
||
|
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
|
||
|
index 7af60ec..2d97bf0 100644
|
||
|
--- a/drivers/md/raid1.c
|
||
|
+++ b/drivers/md/raid1.c
|
||
|
@@ -1713,8 +1713,14 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio)
|
||
|
|
||
|
if (atomic_dec_and_test(&r1_bio->remaining)) {
|
||
|
/* if we're here, all write(s) have completed, so clean up */
|
||
|
- md_done_sync(mddev, r1_bio->sectors, 1);
|
||
|
- put_buf(r1_bio);
|
||
|
+ int s = r1_bio->sectors;
|
||
|
+ if (test_bit(R1BIO_MadeGood, &r1_bio->state) ||
|
||
|
+ test_bit(R1BIO_WriteError, &r1_bio->state))
|
||
|
+ reschedule_retry(r1_bio);
|
||
|
+ else {
|
||
|
+ put_buf(r1_bio);
|
||
|
+ md_done_sync(mddev, s, 1);
|
||
|
+ }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -2378,9 +2384,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
|
||
|
*/
|
||
|
if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
|
||
|
atomic_set(&r1_bio->remaining, read_targets);
|
||
|
- for (i=0; i<conf->raid_disks; i++) {
|
||
|
+ for (i = 0; i < conf->raid_disks && read_targets; i++) {
|
||
|
bio = r1_bio->bios[i];
|
||
|
if (bio->bi_end_io == end_sync_read) {
|
||
|
+ read_targets--;
|
||
|
md_sync_acct(bio->bi_bdev, nr_sectors);
|
||
|
generic_make_request(bio);
|
||
|
}
|
||
|
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
|
||
|
index 6ba4954..26ef63a 100644
|
||
|
--- a/drivers/md/raid5.c
|
||
|
+++ b/drivers/md/raid5.c
|
||
|
@@ -196,12 +196,14 @@ static void __release_stripe(struct r5conf *conf, struct stripe_head *sh)
|
||
|
BUG_ON(!list_empty(&sh->lru));
|
||
|
BUG_ON(atomic_read(&conf->active_stripes)==0);
|
||
|
if (test_bit(STRIPE_HANDLE, &sh->state)) {
|
||
|
- if (test_bit(STRIPE_DELAYED, &sh->state))
|
||
|
+ if (test_bit(STRIPE_DELAYED, &sh->state) &&
|
||
|
+ !test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
|
||
|
list_add_tail(&sh->lru, &conf->delayed_list);
|
||
|
else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
|
||
|
sh->bm_seq - conf->seq_write > 0)
|
||
|
list_add_tail(&sh->lru, &conf->bitmap_list);
|
||
|
else {
|
||
|
+ clear_bit(STRIPE_DELAYED, &sh->state);
|
||
|
clear_bit(STRIPE_BIT_DELAY, &sh->state);
|
||
|
list_add_tail(&sh->lru, &conf->handle_list);
|
||
|
}
|
||
|
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
|
||
|
index f732877..d5cda35 100644
|
||
|
--- a/drivers/media/dvb/dvb-core/dvbdev.c
|
||
|
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
|
||
|
@@ -243,6 +243,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||
|
if (minor == MAX_DVB_MINORS) {
|
||
|
kfree(dvbdevfops);
|
||
|
kfree(dvbdev);
|
||
|
+ up_write(&minor_rwsem);
|
||
|
mutex_unlock(&dvbdev_register_lock);
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
|
||
|
index 34c03be..83e8e1b 100644
|
||
|
--- a/drivers/mtd/nand/nandsim.c
|
||
|
+++ b/drivers/mtd/nand/nandsim.c
|
||
|
@@ -28,7 +28,7 @@
|
||
|
#include <linux/module.h>
|
||
|
#include <linux/moduleparam.h>
|
||
|
#include <linux/vmalloc.h>
|
||
|
-#include <asm/div64.h>
|
||
|
+#include <linux/math64.h>
|
||
|
#include <linux/slab.h>
|
||
|
#include <linux/errno.h>
|
||
|
#include <linux/string.h>
|
||
|
@@ -547,12 +547,6 @@ static char *get_partition_name(int i)
|
||
|
return kstrdup(buf, GFP_KERNEL);
|
||
|
}
|
||
|
|
||
|
-static uint64_t divide(uint64_t n, uint32_t d)
|
||
|
-{
|
||
|
- do_div(n, d);
|
||
|
- return n;
|
||
|
-}
|
||
|
-
|
||
|
/*
|
||
|
* Initialize the nandsim structure.
|
||
|
*
|
||
|
@@ -581,7 +575,7 @@ static int init_nandsim(struct mtd_info *mtd)
|
||
|
ns->geom.oobsz = mtd->oobsize;
|
||
|
ns->geom.secsz = mtd->erasesize;
|
||
|
ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz;
|
||
|
- ns->geom.pgnum = divide(ns->geom.totsz, ns->geom.pgsz);
|
||
|
+ ns->geom.pgnum = div_u64(ns->geom.totsz, ns->geom.pgsz);
|
||
|
ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz;
|
||
|
ns->geom.secshift = ffs(ns->geom.secsz) - 1;
|
||
|
ns->geom.pgshift = chip->page_shift;
|
||
|
@@ -924,7 +918,7 @@ static int setup_wear_reporting(struct mtd_info *mtd)
|
||
|
|
||
|
if (!rptwear)
|
||
|
return 0;
|
||
|
- wear_eb_count = divide(mtd->size, mtd->erasesize);
|
||
|
+ wear_eb_count = div_u64(mtd->size, mtd->erasesize);
|
||
|
mem = wear_eb_count * sizeof(unsigned long);
|
||
|
if (mem / sizeof(unsigned long) != wear_eb_count) {
|
||
|
NS_ERR("Too many erase blocks for wear reporting\n");
|
||
|
diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c
|
||
|
index 3680aa2..2cf084e 100644
|
||
|
--- a/drivers/net/bonding/bond_debugfs.c
|
||
|
+++ b/drivers/net/bonding/bond_debugfs.c
|
||
|
@@ -6,7 +6,7 @@
|
||
|
#include "bonding.h"
|
||
|
#include "bond_alb.h"
|
||
|
|
||
|
-#ifdef CONFIG_DEBUG_FS
|
||
|
+#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_NET_NS)
|
||
|
|
||
|
#include <linux/debugfs.h>
|
||
|
#include <linux/seq_file.h>
|
||
|
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
|
||
|
index 1a88e38..6c284d1 100644
|
||
|
--- a/drivers/net/bonding/bond_main.c
|
||
|
+++ b/drivers/net/bonding/bond_main.c
|
||
|
@@ -3184,6 +3184,12 @@ static int bond_master_netdev_event(unsigned long event,
|
||
|
switch (event) {
|
||
|
case NETDEV_CHANGENAME:
|
||
|
return bond_event_changename(event_bond);
|
||
|
+ case NETDEV_UNREGISTER:
|
||
|
+ bond_remove_proc_entry(event_bond);
|
||
|
+ break;
|
||
|
+ case NETDEV_REGISTER:
|
||
|
+ bond_create_proc_entry(event_bond);
|
||
|
+ break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
@@ -4391,8 +4397,6 @@ static void bond_uninit(struct net_device *bond_dev)
|
||
|
|
||
|
bond_work_cancel_all(bond);
|
||
|
|
||
|
- bond_remove_proc_entry(bond);
|
||
|
-
|
||
|
bond_debug_unregister(bond);
|
||
|
|
||
|
__hw_addr_flush(&bond->mc_list);
|
||
|
@@ -4794,7 +4798,6 @@ static int bond_init(struct net_device *bond_dev)
|
||
|
|
||
|
bond_set_lockdep_class(bond_dev);
|
||
|
|
||
|
- bond_create_proc_entry(bond);
|
||
|
list_add_tail(&bond->bond_list, &bn->dev_list);
|
||
|
|
||
|
bond_prepare_sysfs_group(bond);
|
||
|
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
|
||
|
index eccdcff..5ae7df7 100644
|
||
|
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
|
||
|
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
|
||
|
@@ -267,7 +267,6 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter)
|
||
|
dev_warn(&pdev->dev, "stop mac failed\n");
|
||
|
atl1c_set_aspm(hw, false);
|
||
|
netif_carrier_off(netdev);
|
||
|
- netif_stop_queue(netdev);
|
||
|
atl1c_phy_reset(hw);
|
||
|
atl1c_phy_init(&adapter->hw);
|
||
|
} else {
|
||
|
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
|
||
|
index aec7212..8dda46a 100644
|
||
|
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
|
||
|
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
|
||
|
@@ -723,21 +723,6 @@ struct bnx2x_fastpath {
|
||
|
|
||
|
#define ETH_RX_ERROR_FALGS ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG
|
||
|
|
||
|
-#define BNX2X_IP_CSUM_ERR(cqe) \
|
||
|
- (!((cqe)->fast_path_cqe.status_flags & \
|
||
|
- ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG) && \
|
||
|
- ((cqe)->fast_path_cqe.type_error_flags & \
|
||
|
- ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG))
|
||
|
-
|
||
|
-#define BNX2X_L4_CSUM_ERR(cqe) \
|
||
|
- (!((cqe)->fast_path_cqe.status_flags & \
|
||
|
- ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) && \
|
||
|
- ((cqe)->fast_path_cqe.type_error_flags & \
|
||
|
- ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG))
|
||
|
-
|
||
|
-#define BNX2X_RX_CSUM_OK(cqe) \
|
||
|
- (!(BNX2X_L4_CSUM_ERR(cqe) || BNX2X_IP_CSUM_ERR(cqe)))
|
||
|
-
|
||
|
#define BNX2X_PRS_FLAG_OVERETH_IPV4(flags) \
|
||
|
(((le16_to_cpu(flags) & \
|
||
|
PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) >> \
|
||
|
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
|
||
|
index 580b44e..2c1a5c0 100644
|
||
|
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
|
||
|
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
|
||
|
@@ -220,7 +220,7 @@ int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata)
|
||
|
|
||
|
if ((netif_tx_queue_stopped(txq)) &&
|
||
|
(bp->state == BNX2X_STATE_OPEN) &&
|
||
|
- (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3))
|
||
|
+ (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 4))
|
||
|
netif_tx_wake_queue(txq);
|
||
|
|
||
|
__netif_tx_unlock(txq);
|
||
|
@@ -551,6 +551,26 @@ static inline void bnx2x_set_skb_rxhash(struct bnx2x *bp, union eth_rx_cqe *cqe,
|
||
|
le32_to_cpu(cqe->fast_path_cqe.rss_hash_result);
|
||
|
}
|
||
|
|
||
|
+static void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe,
|
||
|
+ struct bnx2x_fastpath *fp)
|
||
|
+{
|
||
|
+ /* Do nothing if no IP/L4 csum validation was done */
|
||
|
+
|
||
|
+ if (cqe->fast_path_cqe.status_flags &
|
||
|
+ (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG |
|
||
|
+ ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG))
|
||
|
+ return;
|
||
|
+
|
||
|
+ /* If both IP/L4 validation were done, check if an error was found. */
|
||
|
+
|
||
|
+ if (cqe->fast_path_cqe.type_error_flags &
|
||
|
+ (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG |
|
||
|
+ ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG))
|
||
|
+ fp->eth_q_stats.hw_csum_err++;
|
||
|
+ else
|
||
|
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||
|
+}
|
||
|
+
|
||
|
int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
|
||
|
{
|
||
|
struct bnx2x *bp = fp->bp;
|
||
|
@@ -746,13 +766,9 @@ reuse_rx:
|
||
|
|
||
|
skb_checksum_none_assert(skb);
|
||
|
|
||
|
- if (bp->dev->features & NETIF_F_RXCSUM) {
|
||
|
+ if (bp->dev->features & NETIF_F_RXCSUM)
|
||
|
+ bnx2x_csum_validate(skb, cqe, fp);
|
||
|
|
||
|
- if (likely(BNX2X_RX_CSUM_OK(cqe)))
|
||
|
- skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||
|
- else
|
||
|
- fp->eth_q_stats.hw_csum_err++;
|
||
|
- }
|
||
|
}
|
||
|
|
||
|
skb_record_rx_queue(skb, fp->index);
|
||
|
@@ -2238,8 +2254,6 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
|
||
|
/* we split the first BD into headers and data BDs
|
||
|
* to ease the pain of our fellow microcode engineers
|
||
|
* we use one mapping for both BDs
|
||
|
- * So far this has only been observed to happen
|
||
|
- * in Other Operating Systems(TM)
|
||
|
*/
|
||
|
static noinline u16 bnx2x_tx_split(struct bnx2x *bp,
|
||
|
struct bnx2x_fp_txdata *txdata,
|
||
|
@@ -2890,7 +2904,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||
|
|
||
|
txdata->tx_bd_prod += nbd;
|
||
|
|
||
|
- if (unlikely(bnx2x_tx_avail(bp, txdata) < MAX_SKB_FRAGS + 3)) {
|
||
|
+ if (unlikely(bnx2x_tx_avail(bp, txdata) < MAX_SKB_FRAGS + 4)) {
|
||
|
netif_tx_stop_queue(txq);
|
||
|
|
||
|
/* paired memory barrier is in bnx2x_tx_int(), we have to keep
|
||
|
@@ -2899,7 +2913,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||
|
smp_mb();
|
||
|
|
||
|
fp->eth_q_stats.driver_xoff++;
|
||
|
- if (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3)
|
||
|
+ if (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 4)
|
||
|
netif_tx_wake_queue(txq);
|
||
|
}
|
||
|
txdata->tx_pkt++;
|
||
|
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
|
||
|
index 2dcac28..6b258d9 100644
|
||
|
--- a/drivers/net/ethernet/broadcom/tg3.c
|
||
|
+++ b/drivers/net/ethernet/broadcom/tg3.c
|
||
|
@@ -14046,7 +14046,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- if (tg3_flag(tp, 5755_PLUS))
|
||
|
+ if (tg3_flag(tp, 5755_PLUS) ||
|
||
|
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
|
||
|
tg3_flag_set(tp, SHORT_DMA_BUG);
|
||
|
|
||
|
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
|
||
|
diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c
|
||
|
index e556fc3..3072d35 100644
|
||
|
--- a/drivers/net/ethernet/intel/e1000e/82571.c
|
||
|
+++ b/drivers/net/ethernet/intel/e1000e/82571.c
|
||
|
@@ -1571,6 +1571,9 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
|
||
|
ctrl = er32(CTRL);
|
||
|
status = er32(STATUS);
|
||
|
rxcw = er32(RXCW);
|
||
|
+ /* SYNCH bit and IV bit are sticky */
|
||
|
+ udelay(10);
|
||
|
+ rxcw = er32(RXCW);
|
||
|
|
||
|
if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) {
|
||
|
|
||
|
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
|
||
|
index cc2565c..9e61d6b 100644
|
||
|
--- a/drivers/net/ethernet/realtek/r8169.c
|
||
|
+++ b/drivers/net/ethernet/realtek/r8169.c
|
||
|
@@ -4185,6 +4185,7 @@ out:
|
||
|
return rc;
|
||
|
|
||
|
err_out_msi_4:
|
||
|
+ netif_napi_del(&tp->napi);
|
||
|
rtl_disable_msi(pdev, tp);
|
||
|
iounmap(ioaddr);
|
||
|
err_out_free_res_3:
|
||
|
@@ -4210,6 +4211,8 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
|
||
|
|
||
|
cancel_delayed_work_sync(&tp->task);
|
||
|
|
||
|
+ netif_napi_del(&tp->napi);
|
||
|
+
|
||
|
unregister_netdev(dev);
|
||
|
|
||
|
rtl_release_firmware(tp);
|
||
|
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
||
|
index 72cd190..d4d2bc1 100644
|
||
|
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
||
|
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
||
|
@@ -1174,6 +1174,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
|
||
|
priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion);
|
||
|
wmb();
|
||
|
priv->hw->desc->set_tx_owner(desc);
|
||
|
+ wmb();
|
||
|
}
|
||
|
|
||
|
/* Interrupt on completition only for the latest segment */
|
||
|
@@ -1189,6 +1190,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
|
||
|
|
||
|
/* To avoid raise condition */
|
||
|
priv->hw->desc->set_tx_owner(first);
|
||
|
+ wmb();
|
||
|
|
||
|
priv->cur_tx++;
|
||
|
|
||
|
@@ -1252,6 +1254,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
|
||
|
}
|
||
|
wmb();
|
||
|
priv->hw->desc->set_rx_owner(p + entry);
|
||
|
+ wmb();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
|
||
|
index 1b7082d..26106c0 100644
|
||
|
--- a/drivers/net/macvtap.c
|
||
|
+++ b/drivers/net/macvtap.c
|
||
|
@@ -504,10 +504,11 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
|
||
|
if (copy > size) {
|
||
|
++from;
|
||
|
--count;
|
||
|
- }
|
||
|
+ offset = 0;
|
||
|
+ } else
|
||
|
+ offset += size;
|
||
|
copy -= size;
|
||
|
offset1 += size;
|
||
|
- offset = 0;
|
||
|
}
|
||
|
|
||
|
if (len == offset1)
|
||
|
@@ -517,24 +518,29 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
|
||
|
struct page *page[MAX_SKB_FRAGS];
|
||
|
int num_pages;
|
||
|
unsigned long base;
|
||
|
+ unsigned long truesize;
|
||
|
|
||
|
- len = from->iov_len - offset1;
|
||
|
+ len = from->iov_len - offset;
|
||
|
if (!len) {
|
||
|
- offset1 = 0;
|
||
|
+ offset = 0;
|
||
|
++from;
|
||
|
continue;
|
||
|
}
|
||
|
- base = (unsigned long)from->iov_base + offset1;
|
||
|
+ base = (unsigned long)from->iov_base + offset;
|
||
|
size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
|
||
|
+ if (i + size > MAX_SKB_FRAGS)
|
||
|
+ return -EMSGSIZE;
|
||
|
num_pages = get_user_pages_fast(base, size, 0, &page[i]);
|
||
|
- if ((num_pages != size) ||
|
||
|
- (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags))
|
||
|
- /* put_page is in skb free */
|
||
|
+ if (num_pages != size) {
|
||
|
+ for (i = 0; i < num_pages; i++)
|
||
|
+ put_page(page[i]);
|
||
|
return -EFAULT;
|
||
|
+ }
|
||
|
+ truesize = size * PAGE_SIZE;
|
||
|
skb->data_len += len;
|
||
|
skb->len += len;
|
||
|
- skb->truesize += len;
|
||
|
- atomic_add(len, &skb->sk->sk_wmem_alloc);
|
||
|
+ skb->truesize += truesize;
|
||
|
+ atomic_add(truesize, &skb->sk->sk_wmem_alloc);
|
||
|
while (len) {
|
||
|
int off = base & ~PAGE_MASK;
|
||
|
int size = min_t(int, len, PAGE_SIZE - off);
|
||
|
@@ -545,7 +551,7 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
|
||
|
len -= size;
|
||
|
i++;
|
||
|
}
|
||
|
- offset1 = 0;
|
||
|
+ offset = 0;
|
||
|
++from;
|
||
|
}
|
||
|
return 0;
|
||
|
@@ -645,7 +651,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
|
||
|
int err;
|
||
|
struct virtio_net_hdr vnet_hdr = { 0 };
|
||
|
int vnet_hdr_len = 0;
|
||
|
- int copylen;
|
||
|
+ int copylen = 0;
|
||
|
bool zerocopy = false;
|
||
|
|
||
|
if (q->flags & IFF_VNET_HDR) {
|
||
|
@@ -674,15 +680,31 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
|
||
|
if (unlikely(len < ETH_HLEN))
|
||
|
goto err;
|
||
|
|
||
|
+ err = -EMSGSIZE;
|
||
|
+ if (unlikely(count > UIO_MAXIOV))
|
||
|
+ goto err;
|
||
|
+
|
||
|
if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY))
|
||
|
zerocopy = true;
|
||
|
|
||
|
if (zerocopy) {
|
||
|
+ /* Userspace may produce vectors with count greater than
|
||
|
+ * MAX_SKB_FRAGS, so we need to linearize parts of the skb
|
||
|
+ * to let the rest of data to be fit in the frags.
|
||
|
+ */
|
||
|
+ if (count > MAX_SKB_FRAGS) {
|
||
|
+ copylen = iov_length(iv, count - MAX_SKB_FRAGS);
|
||
|
+ if (copylen < vnet_hdr_len)
|
||
|
+ copylen = 0;
|
||
|
+ else
|
||
|
+ copylen -= vnet_hdr_len;
|
||
|
+ }
|
||
|
/* There are 256 bytes to be copied in skb, so there is enough
|
||
|
* room for skb expand head in case it is used.
|
||
|
* The rest buffer is mapped from userspace.
|
||
|
*/
|
||
|
- copylen = vnet_hdr.hdr_len;
|
||
|
+ if (copylen < vnet_hdr.hdr_len)
|
||
|
+ copylen = vnet_hdr.hdr_len;
|
||
|
if (!copylen)
|
||
|
copylen = GOODCOPY_LEN;
|
||
|
} else
|
||
|
@@ -693,10 +715,9 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
|
||
|
if (!skb)
|
||
|
goto err;
|
||
|
|
||
|
- if (zerocopy) {
|
||
|
+ if (zerocopy)
|
||
|
err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count);
|
||
|
- skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
|
||
|
- } else
|
||
|
+ else
|
||
|
err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len,
|
||
|
len);
|
||
|
if (err)
|
||
|
@@ -715,8 +736,10 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
|
||
|
rcu_read_lock_bh();
|
||
|
vlan = rcu_dereference_bh(q->vlan);
|
||
|
/* copy skb_ubuf_info for callback when skb has no error */
|
||
|
- if (zerocopy)
|
||
|
+ if (zerocopy) {
|
||
|
skb_shinfo(skb)->destructor_arg = m->msg_control;
|
||
|
+ skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
|
||
|
+ }
|
||
|
if (vlan)
|
||
|
macvlan_start_xmit(skb, vlan->dev);
|
||
|
else
|
||
|
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
|
||
|
index ad96164..00ed9c1 100644
|
||
|
--- a/drivers/net/usb/ipheth.c
|
||
|
+++ b/drivers/net/usb/ipheth.c
|
||
|
@@ -59,6 +59,7 @@
|
||
|
#define USB_PRODUCT_IPHONE_3G 0x1292
|
||
|
#define USB_PRODUCT_IPHONE_3GS 0x1294
|
||
|
#define USB_PRODUCT_IPHONE_4 0x1297
|
||
|
+#define USB_PRODUCT_IPAD 0x129a
|
||
|
#define USB_PRODUCT_IPHONE_4_VZW 0x129c
|
||
|
#define USB_PRODUCT_IPHONE_4S 0x12a0
|
||
|
|
||
|
@@ -101,6 +102,10 @@ static struct usb_device_id ipheth_table[] = {
|
||
|
IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
|
||
|
IPHETH_USBINTF_PROTO) },
|
||
|
{ USB_DEVICE_AND_INTERFACE_INFO(
|
||
|
+ USB_VENDOR_APPLE, USB_PRODUCT_IPAD,
|
||
|
+ IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
|
||
|
+ IPHETH_USBINTF_PROTO) },
|
||
|
+ { USB_DEVICE_AND_INTERFACE_INFO(
|
||
|
USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW,
|
||
|
IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
|
||
|
IPHETH_USBINTF_PROTO) },
|
||
|
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||
|
index 833cbef..8a40ff9 100644
|
||
|
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||
|
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||
|
@@ -900,8 +900,7 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
|
||
|
*/
|
||
|
if (!(txs->status & TX_STATUS_AMPDU)
|
||
|
&& (txs->status & TX_STATUS_INTERMEDIATE)) {
|
||
|
- wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n",
|
||
|
- __func__);
|
||
|
+ BCMMSG(wlc->wiphy, "INTERMEDIATE but not AMPDU\n");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/net/wireless/ipw2x00/ipw.h b/drivers/net/wireless/ipw2x00/ipw.h
|
||
|
new file mode 100644
|
||
|
index 0000000..4007bf5
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/net/wireless/ipw2x00/ipw.h
|
||
|
@@ -0,0 +1,23 @@
|
||
|
+/*
|
||
|
+ * Intel Pro/Wireless 2100, 2200BG, 2915ABG network connection driver
|
||
|
+ *
|
||
|
+ * Copyright 2012 Stanislav Yakovlev <stas.yakovlev@gmail.com>
|
||
|
+ *
|
||
|
+ * This program is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License version 2 as
|
||
|
+ * published by the Free Software Foundation.
|
||
|
+ */
|
||
|
+
|
||
|
+#ifndef __IPW_H__
|
||
|
+#define __IPW_H__
|
||
|
+
|
||
|
+#include <linux/ieee80211.h>
|
||
|
+
|
||
|
+static const u32 ipw_cipher_suites[] = {
|
||
|
+ WLAN_CIPHER_SUITE_WEP40,
|
||
|
+ WLAN_CIPHER_SUITE_WEP104,
|
||
|
+ WLAN_CIPHER_SUITE_TKIP,
|
||
|
+ WLAN_CIPHER_SUITE_CCMP,
|
||
|
+};
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
|
||
|
index 127e9c6..10862d4 100644
|
||
|
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
|
||
|
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
|
||
|
@@ -166,6 +166,7 @@ that only one external action is invoked at a time.
|
||
|
#include <net/lib80211.h>
|
||
|
|
||
|
#include "ipw2100.h"
|
||
|
+#include "ipw.h"
|
||
|
|
||
|
#define IPW2100_VERSION "git-1.2.2"
|
||
|
|
||
|
@@ -1955,6 +1956,9 @@ static int ipw2100_wdev_init(struct net_device *dev)
|
||
|
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band;
|
||
|
}
|
||
|
|
||
|
+ wdev->wiphy->cipher_suites = ipw_cipher_suites;
|
||
|
+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites);
|
||
|
+
|
||
|
set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
|
||
|
if (wiphy_register(wdev->wiphy)) {
|
||
|
ipw2100_down(priv);
|
||
|
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
|
||
|
index 827889b..56bd370 100644
|
||
|
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
|
||
|
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
|
||
|
@@ -34,6 +34,7 @@
|
||
|
#include <linux/slab.h>
|
||
|
#include <net/cfg80211-wext.h>
|
||
|
#include "ipw2200.h"
|
||
|
+#include "ipw.h"
|
||
|
|
||
|
|
||
|
#ifndef KBUILD_EXTMOD
|
||
|
@@ -11535,6 +11536,9 @@ static int ipw_wdev_init(struct net_device *dev)
|
||
|
wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band;
|
||
|
}
|
||
|
|
||
|
+ wdev->wiphy->cipher_suites = ipw_cipher_suites;
|
||
|
+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites);
|
||
|
+
|
||
|
set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
|
||
|
|
||
|
/* With that information in place, we can now register the wiphy... */
|
||
|
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-sta.c b/drivers/net/wireless/iwlegacy/iwl-4965-sta.c
|
||
|
index a262c23..0116ca8 100644
|
||
|
--- a/drivers/net/wireless/iwlegacy/iwl-4965-sta.c
|
||
|
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-sta.c
|
||
|
@@ -466,7 +466,7 @@ int iwl4965_remove_dynamic_key(struct iwl_priv *priv,
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
- if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
|
||
|
+ if (priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_INVALID) {
|
||
|
IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
|
||
|
keyconf->keyidx, key_flags);
|
||
|
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||
|
@@ -483,7 +483,7 @@ int iwl4965_remove_dynamic_key(struct iwl_priv *priv,
|
||
|
sizeof(struct iwl4965_keyinfo));
|
||
|
priv->stations[sta_id].sta.key.key_flags =
|
||
|
STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
|
||
|
- priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
|
||
|
+ priv->stations[sta_id].sta.key.key_offset = keyconf->hw_key_idx;
|
||
|
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
||
|
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||
|
|
||
|
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c
|
||
|
index 2bd5659..1bb64c9 100644
|
||
|
--- a/drivers/net/wireless/iwlegacy/iwl-core.c
|
||
|
+++ b/drivers/net/wireless/iwlegacy/iwl-core.c
|
||
|
@@ -1884,14 +1884,12 @@ void iwl_legacy_bg_watchdog(unsigned long data)
|
||
|
return;
|
||
|
|
||
|
/* monitor and check for other stuck queues */
|
||
|
- if (iwl_legacy_is_any_associated(priv)) {
|
||
|
- for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
|
||
|
- /* skip as we already checked the command queue */
|
||
|
- if (cnt == priv->cmd_queue)
|
||
|
- continue;
|
||
|
- if (iwl_legacy_check_stuck_queue(priv, cnt))
|
||
|
- return;
|
||
|
- }
|
||
|
+ for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
|
||
|
+ /* skip as we already checked the command queue */
|
||
|
+ if (cnt == priv->cmd_queue)
|
||
|
+ continue;
|
||
|
+ if (iwl_legacy_check_stuck_queue(priv, cnt))
|
||
|
+ return;
|
||
|
}
|
||
|
|
||
|
mod_timer(&priv->watchdog, jiffies +
|
||
|
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
|
||
|
index 1e31050..ba28807 100644
|
||
|
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
|
||
|
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
|
||
|
@@ -426,8 +426,8 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
|
||
|
case QID_RX:
|
||
|
if (!rt2x00queue_full(queue))
|
||
|
rt2x00queue_for_each_entry(queue,
|
||
|
- Q_INDEX_DONE,
|
||
|
Q_INDEX,
|
||
|
+ Q_INDEX_DONE,
|
||
|
NULL,
|
||
|
rt2x00usb_kick_rx_entry);
|
||
|
break;
|
||
|
diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.c b/drivers/net/wireless/rtl818x/rtl8187/leds.c
|
||
|
index 2e0de2f..c2d5b49 100644
|
||
|
--- a/drivers/net/wireless/rtl818x/rtl8187/leds.c
|
||
|
+++ b/drivers/net/wireless/rtl818x/rtl8187/leds.c
|
||
|
@@ -117,7 +117,7 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
|
||
|
radio_on = true;
|
||
|
} else if (radio_on) {
|
||
|
radio_on = false;
|
||
|
- cancel_delayed_work_sync(&priv->led_on);
|
||
|
+ cancel_delayed_work(&priv->led_on);
|
||
|
ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
|
||
|
}
|
||
|
} else if (radio_on) {
|
||
|
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
|
||
|
index 12d1e81..d024f83 100644
|
||
|
--- a/drivers/pci/pci-driver.c
|
||
|
+++ b/drivers/pci/pci-driver.c
|
||
|
@@ -742,6 +742,18 @@ static int pci_pm_suspend_noirq(struct device *dev)
|
||
|
|
||
|
pci_pm_set_unknown_state(pci_dev);
|
||
|
|
||
|
+ /*
|
||
|
+ * Some BIOSes from ASUS have a bug: If a USB EHCI host controller's
|
||
|
+ * PCI COMMAND register isn't 0, the BIOS assumes that the controller
|
||
|
+ * hasn't been quiesced and tries to turn it off. If the controller
|
||
|
+ * is already in D3, this can hang or cause memory corruption.
|
||
|
+ *
|
||
|
+ * Since the value of the COMMAND register doesn't matter once the
|
||
|
+ * device has been suspended, we can safely set it to 0 here.
|
||
|
+ */
|
||
|
+ if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
|
||
|
+ pci_write_config_word(pci_dev, PCI_COMMAND, 0);
|
||
|
+
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
|
||
|
index e5b75eb..6d4a531 100644
|
||
|
--- a/drivers/pci/pci.c
|
||
|
+++ b/drivers/pci/pci.c
|
||
|
@@ -1689,11 +1689,6 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
|
||
|
if (target_state == PCI_POWER_ERROR)
|
||
|
return -EIO;
|
||
|
|
||
|
- /* Some devices mustn't be in D3 during system sleep */
|
||
|
- if (target_state == PCI_D3hot &&
|
||
|
- (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP))
|
||
|
- return 0;
|
||
|
-
|
||
|
pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev));
|
||
|
|
||
|
error = pci_set_power_state(dev, target_state);
|
||
|
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
|
||
|
index 3c56fec..78fda9c 100644
|
||
|
--- a/drivers/pci/quirks.c
|
||
|
+++ b/drivers/pci/quirks.c
|
||
|
@@ -2940,32 +2940,6 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev)
|
||
|
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq);
|
||
|
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
|
||
|
|
||
|
-/*
|
||
|
- * The Intel 6 Series/C200 Series chipset's EHCI controllers on many
|
||
|
- * ASUS motherboards will cause memory corruption or a system crash
|
||
|
- * if they are in D3 while the system is put into S3 sleep.
|
||
|
- */
|
||
|
-static void __devinit asus_ehci_no_d3(struct pci_dev *dev)
|
||
|
-{
|
||
|
- const char *sys_info;
|
||
|
- static const char good_Asus_board[] = "P8Z68-V";
|
||
|
-
|
||
|
- if (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP)
|
||
|
- return;
|
||
|
- if (dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK)
|
||
|
- return;
|
||
|
- sys_info = dmi_get_system_info(DMI_BOARD_NAME);
|
||
|
- if (sys_info && memcmp(sys_info, good_Asus_board,
|
||
|
- sizeof(good_Asus_board) - 1) == 0)
|
||
|
- return;
|
||
|
-
|
||
|
- dev_info(&dev->dev, "broken D3 during system sleep on ASUS\n");
|
||
|
- dev->dev_flags |= PCI_DEV_FLAGS_NO_D3_DURING_SLEEP;
|
||
|
- device_set_wakeup_capable(&dev->dev, false);
|
||
|
-}
|
||
|
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c26, asus_ehci_no_d3);
|
||
|
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c2d, asus_ehci_no_d3);
|
||
|
-
|
||
|
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
|
||
|
struct pci_fixup *end)
|
||
|
{
|
||
|
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
|
||
|
index 809a3ae..b46ec11 100644
|
||
|
--- a/drivers/platform/x86/intel_ips.c
|
||
|
+++ b/drivers/platform/x86/intel_ips.c
|
||
|
@@ -72,6 +72,7 @@
|
||
|
#include <linux/string.h>
|
||
|
#include <linux/tick.h>
|
||
|
#include <linux/timer.h>
|
||
|
+#include <linux/dmi.h>
|
||
|
#include <drm/i915_drm.h>
|
||
|
#include <asm/msr.h>
|
||
|
#include <asm/processor.h>
|
||
|
@@ -1505,6 +1506,24 @@ static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = {
|
||
|
|
||
|
MODULE_DEVICE_TABLE(pci, ips_id_table);
|
||
|
|
||
|
+static int ips_blacklist_callback(const struct dmi_system_id *id)
|
||
|
+{
|
||
|
+ pr_info("Blacklisted intel_ips for %s\n", id->ident);
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
+static const struct dmi_system_id ips_blacklist[] = {
|
||
|
+ {
|
||
|
+ .callback = ips_blacklist_callback,
|
||
|
+ .ident = "HP ProBook",
|
||
|
+ .matches = {
|
||
|
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
|
||
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook"),
|
||
|
+ },
|
||
|
+ },
|
||
|
+ { } /* terminating entry */
|
||
|
+};
|
||
|
+
|
||
|
static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||
|
{
|
||
|
u64 platform_info;
|
||
|
@@ -1514,6 +1533,9 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||
|
u16 htshi, trc, trc_required_mask;
|
||
|
u8 tse;
|
||
|
|
||
|
+ if (dmi_check_system(ips_blacklist))
|
||
|
+ return -ENODEV;
|
||
|
+
|
||
|
ips = kzalloc(sizeof(struct ips_driver), GFP_KERNEL);
|
||
|
if (!ips)
|
||
|
return -ENOMEM;
|
||
|
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
|
||
|
index 09e26bf..af1e296 100644
|
||
|
--- a/drivers/platform/x86/samsung-laptop.c
|
||
|
+++ b/drivers/platform/x86/samsung-laptop.c
|
||
|
@@ -540,245 +540,34 @@ static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
|
||
|
get_performance_level, set_performance_level);
|
||
|
|
||
|
|
||
|
-static int __init dmi_check_cb(const struct dmi_system_id *id)
|
||
|
-{
|
||
|
- pr_info("found laptop model '%s'\n",
|
||
|
- id->ident);
|
||
|
- return 1;
|
||
|
-}
|
||
|
-
|
||
|
static struct dmi_system_id __initdata samsung_dmi_table[] = {
|
||
|
{
|
||
|
- .ident = "N128",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
- "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "N128"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "N128"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "N130",
|
||
|
.matches = {
|
||
|
DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
"SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "N130"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "N130"),
|
||
|
+ DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
|
||
|
},
|
||
|
- .callback = dmi_check_cb,
|
||
|
},
|
||
|
{
|
||
|
- .ident = "N510",
|
||
|
.matches = {
|
||
|
DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
"SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "N510"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "N510"),
|
||
|
+ DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */
|
||
|
},
|
||
|
- .callback = dmi_check_cb,
|
||
|
},
|
||
|
{
|
||
|
- .ident = "X125",
|
||
|
.matches = {
|
||
|
DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
"SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "X125"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "X125"),
|
||
|
+ DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
|
||
|
},
|
||
|
- .callback = dmi_check_cb,
|
||
|
},
|
||
|
{
|
||
|
- .ident = "X120/X170",
|
||
|
.matches = {
|
||
|
DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
"SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "X120/X170"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "X120/X170"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "NC10",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
- "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "NC10"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "NP-Q45",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
- "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "SQ45S70S"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "X360",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
- "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "X360"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "R410 Plus",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
- "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "R410P"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "R460"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "R518",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
- "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "R518"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "R518"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "R519/R719",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
- "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "R519/R719"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "R519/R719"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "N150/N210/N220",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
- "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "N220",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
- "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "N220"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "N220"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "N150/N210/N220/N230",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
- "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220/N230"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220/N230"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "N150P/N210P/N220P",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
- "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "N150P/N210P/N220P"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "N150P/N210P/N220P"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "R700",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "SR700"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "SR700"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "R530/R730",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "R530/R730"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "R530/R730"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "NF110/NF210/NF310",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "N145P/N250P/N260P",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "R70/R71",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR,
|
||
|
- "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "R70/R71"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "R70/R71"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "P460",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "P460"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "P460"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "R528/R728",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "R528/R728"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "R528/R728"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "NC210/NC110",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"),
|
||
|
- },
|
||
|
- .callback = dmi_check_cb,
|
||
|
- },
|
||
|
- {
|
||
|
- .ident = "X520",
|
||
|
- .matches = {
|
||
|
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||
|
- DMI_MATCH(DMI_PRODUCT_NAME, "X520"),
|
||
|
- DMI_MATCH(DMI_BOARD_NAME, "X520"),
|
||
|
+ DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */
|
||
|
},
|
||
|
- .callback = dmi_check_cb,
|
||
|
},
|
||
|
{ },
|
||
|
};
|
||
|
@@ -819,7 +608,8 @@ static int __init samsung_init(void)
|
||
|
|
||
|
f0000_segment = ioremap_nocache(0xf0000, 0xffff);
|
||
|
if (!f0000_segment) {
|
||
|
- pr_err("Can't map the segment at 0xf0000\n");
|
||
|
+ if (debug || force)
|
||
|
+ pr_err("Can't map the segment at 0xf0000\n");
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
@@ -832,7 +622,8 @@ static int __init samsung_init(void)
|
||
|
}
|
||
|
|
||
|
if (loca == 0xffff) {
|
||
|
- pr_err("This computer does not support SABI\n");
|
||
|
+ if (debug || force)
|
||
|
+ pr_err("This computer does not support SABI\n");
|
||
|
goto error_no_signature;
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
|
||
|
index 39e41fb..5160354 100644
|
||
|
--- a/drivers/rtc/rtc-mxc.c
|
||
|
+++ b/drivers/rtc/rtc-mxc.c
|
||
|
@@ -191,10 +191,11 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
|
||
|
struct platform_device *pdev = dev_id;
|
||
|
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
||
|
void __iomem *ioaddr = pdata->ioaddr;
|
||
|
+ unsigned long flags;
|
||
|
u32 status;
|
||
|
u32 events = 0;
|
||
|
|
||
|
- spin_lock_irq(&pdata->rtc->irq_lock);
|
||
|
+ spin_lock_irqsave(&pdata->rtc->irq_lock, flags);
|
||
|
status = readw(ioaddr + RTC_RTCISR) & readw(ioaddr + RTC_RTCIENR);
|
||
|
/* clear interrupt sources */
|
||
|
writew(status, ioaddr + RTC_RTCISR);
|
||
|
@@ -217,7 +218,7 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
|
||
|
rtc_update_alarm(&pdev->dev, &pdata->g_rtc_alarm);
|
||
|
|
||
|
rtc_update_irq(pdata->rtc, 1, events);
|
||
|
- spin_unlock_irq(&pdata->rtc->irq_lock);
|
||
|
+ spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags);
|
||
|
|
||
|
return IRQ_HANDLED;
|
||
|
}
|
||
|
diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c
|
||
|
index 532d212..393e7ce 100644
|
||
|
--- a/drivers/scsi/aic94xx/aic94xx_task.c
|
||
|
+++ b/drivers/scsi/aic94xx/aic94xx_task.c
|
||
|
@@ -201,7 +201,7 @@ static void asd_get_response_tasklet(struct asd_ascb *ascb,
|
||
|
|
||
|
if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {
|
||
|
resp->frame_len = le16_to_cpu(*(__le16 *)(r+6));
|
||
|
- memcpy(&resp->ending_fis[0], r+16, 24);
|
||
|
+ memcpy(&resp->ending_fis[0], r+16, ATA_RESP_FIS_SIZE);
|
||
|
ts->buf_valid_size = sizeof(*resp);
|
||
|
}
|
||
|
}
|
||
|
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
|
||
|
index db9238f..4868fc9 100644
|
||
|
--- a/drivers/scsi/libsas/sas_ata.c
|
||
|
+++ b/drivers/scsi/libsas/sas_ata.c
|
||
|
@@ -112,12 +112,12 @@ static void sas_ata_task_done(struct sas_task *task)
|
||
|
if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD ||
|
||
|
((stat->stat == SAM_STAT_CHECK_CONDITION &&
|
||
|
dev->sata_dev.command_set == ATAPI_COMMAND_SET))) {
|
||
|
- ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf);
|
||
|
+ memcpy(dev->sata_dev.fis, resp->ending_fis, ATA_RESP_FIS_SIZE);
|
||
|
|
||
|
if (!link->sactive) {
|
||
|
- qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command);
|
||
|
+ qc->err_mask |= ac_err_mask(dev->sata_dev.fis[2]);
|
||
|
} else {
|
||
|
- link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.tf.command);
|
||
|
+ link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.fis[2]);
|
||
|
if (unlikely(link->eh_info.err_mask))
|
||
|
qc->flags |= ATA_QCFLAG_FAILED;
|
||
|
}
|
||
|
@@ -138,8 +138,8 @@ static void sas_ata_task_done(struct sas_task *task)
|
||
|
qc->flags |= ATA_QCFLAG_FAILED;
|
||
|
}
|
||
|
|
||
|
- dev->sata_dev.tf.feature = 0x04; /* status err */
|
||
|
- dev->sata_dev.tf.command = ATA_ERR;
|
||
|
+ dev->sata_dev.fis[3] = 0x04; /* status err */
|
||
|
+ dev->sata_dev.fis[2] = ATA_ERR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -252,7 +252,7 @@ static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc)
|
||
|
{
|
||
|
struct domain_device *dev = qc->ap->private_data;
|
||
|
|
||
|
- memcpy(&qc->result_tf, &dev->sata_dev.tf, sizeof(qc->result_tf));
|
||
|
+ ata_tf_from_fis(dev->sata_dev.fis, &qc->result_tf);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c
|
||
|
index 65ea65a..93b9406 100644
|
||
|
--- a/drivers/target/target_core_cdb.c
|
||
|
+++ b/drivers/target/target_core_cdb.c
|
||
|
@@ -1199,7 +1199,7 @@ int target_emulate_write_same(struct se_task *task)
|
||
|
if (num_blocks != 0)
|
||
|
range = num_blocks;
|
||
|
else
|
||
|
- range = (dev->transport->get_blocks(dev) - lba);
|
||
|
+ range = (dev->transport->get_blocks(dev) - lba) + 1;
|
||
|
|
||
|
pr_debug("WRITE_SAME UNMAP: LBA: %llu Range: %llu\n",
|
||
|
(unsigned long long)lba, (unsigned long long)range);
|
||
|
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
|
||
|
index b75bc92..9145141 100644
|
||
|
--- a/drivers/target/target_core_pr.c
|
||
|
+++ b/drivers/target/target_core_pr.c
|
||
|
@@ -2042,7 +2042,7 @@ static int __core_scsi3_write_aptpl_to_file(
|
||
|
if (IS_ERR(file) || !file || !file->f_dentry) {
|
||
|
pr_err("filp_open(%s) for APTPL metadata"
|
||
|
" failed\n", path);
|
||
|
- return (PTR_ERR(file) < 0 ? PTR_ERR(file) : -ENOENT);
|
||
|
+ return IS_ERR(file) ? PTR_ERR(file) : -ENOENT;
|
||
|
}
|
||
|
|
||
|
iov[0].iov_base = &buf[0];
|
||
|
@@ -3853,7 +3853,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task)
|
||
|
" SPC-2 reservation is held, returning"
|
||
|
" RESERVATION_CONFLICT\n");
|
||
|
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
||
|
- ret = EINVAL;
|
||
|
+ ret = -EINVAL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
@@ -3863,7 +3863,8 @@ int target_scsi3_emulate_pr_out(struct se_task *task)
|
||
|
*/
|
||
|
if (!cmd->se_sess) {
|
||
|
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||
|
- return -EINVAL;
|
||
|
+ ret = -EINVAL;
|
||
|
+ goto out;
|
||
|
}
|
||
|
|
||
|
if (cmd->data_length < 24) {
|
||
|
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
|
||
|
index d95cfe2..278819c 100644
|
||
|
--- a/drivers/target/tcm_fc/tfc_cmd.c
|
||
|
+++ b/drivers/target/tcm_fc/tfc_cmd.c
|
||
|
@@ -249,6 +249,8 @@ u32 ft_get_task_tag(struct se_cmd *se_cmd)
|
||
|
{
|
||
|
struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
|
||
|
|
||
|
+ if (cmd->aborted)
|
||
|
+ return ~0;
|
||
|
return fc_seq_exch(cmd->seq)->rxid;
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
|
||
|
index 19fb5fa..9aaed0d 100644
|
||
|
--- a/drivers/usb/class/cdc-wdm.c
|
||
|
+++ b/drivers/usb/class/cdc-wdm.c
|
||
|
@@ -473,6 +473,8 @@ retry:
|
||
|
goto retry;
|
||
|
}
|
||
|
if (!desc->reslength) { /* zero length read */
|
||
|
+ dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
|
||
|
+ clear_bit(WDM_READ, &desc->flags);
|
||
|
spin_unlock_irq(&desc->iuspin);
|
||
|
goto retry;
|
||
|
}
|
||
|
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
|
||
|
index 52d27ed..175b6bb 100644
|
||
|
--- a/drivers/usb/core/hub.c
|
||
|
+++ b/drivers/usb/core/hub.c
|
||
|
@@ -2039,12 +2039,16 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
|
||
|
static int hub_port_reset(struct usb_hub *hub, int port1,
|
||
|
struct usb_device *udev, unsigned int delay, bool warm);
|
||
|
|
||
|
-/* Is a USB 3.0 port in the Inactive state? */
|
||
|
-static bool hub_port_inactive(struct usb_hub *hub, u16 portstatus)
|
||
|
+/* Is a USB 3.0 port in the Inactive or Complinance Mode state?
|
||
|
+ * Port worm reset is required to recover
|
||
|
+ */
|
||
|
+static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus)
|
||
|
{
|
||
|
return hub_is_superspeed(hub->hdev) &&
|
||
|
- (portstatus & USB_PORT_STAT_LINK_STATE) ==
|
||
|
- USB_SS_PORT_LS_SS_INACTIVE;
|
||
|
+ (((portstatus & USB_PORT_STAT_LINK_STATE) ==
|
||
|
+ USB_SS_PORT_LS_SS_INACTIVE) ||
|
||
|
+ ((portstatus & USB_PORT_STAT_LINK_STATE) ==
|
||
|
+ USB_SS_PORT_LS_COMP_MOD)) ;
|
||
|
}
|
||
|
|
||
|
static int hub_port_wait_reset(struct usb_hub *hub, int port1,
|
||
|
@@ -2080,7 +2084,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
|
||
|
*
|
||
|
* See https://bugzilla.kernel.org/show_bug.cgi?id=41752
|
||
|
*/
|
||
|
- if (hub_port_inactive(hub, portstatus)) {
|
||
|
+ if (hub_port_warm_reset_required(hub, portstatus)) {
|
||
|
int ret;
|
||
|
|
||
|
if ((portchange & USB_PORT_STAT_C_CONNECTION))
|
||
|
@@ -3646,9 +3650,7 @@ static void hub_events(void)
|
||
|
/* Warm reset a USB3 protocol port if it's in
|
||
|
* SS.Inactive state.
|
||
|
*/
|
||
|
- if (hub_is_superspeed(hub->hdev) &&
|
||
|
- (portstatus & USB_PORT_STAT_LINK_STATE)
|
||
|
- == USB_SS_PORT_LS_SS_INACTIVE) {
|
||
|
+ if (hub_port_warm_reset_required(hub, portstatus)) {
|
||
|
dev_dbg(hub_dev, "warm reset port %d\n", i);
|
||
|
hub_port_reset(hub, i, NULL,
|
||
|
HUB_BH_RESET_TIME, true);
|
||
|
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
|
||
|
index a8b2980..fd8a2c2 100644
|
||
|
--- a/drivers/usb/host/xhci-hub.c
|
||
|
+++ b/drivers/usb/host/xhci-hub.c
|
||
|
@@ -438,6 +438,42 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+/* Updates Link Status for super Speed port */
|
||
|
+static void xhci_hub_report_link_state(u32 *status, u32 status_reg)
|
||
|
+{
|
||
|
+ u32 pls = status_reg & PORT_PLS_MASK;
|
||
|
+
|
||
|
+ /* resume state is a xHCI internal state.
|
||
|
+ * Do not report it to usb core.
|
||
|
+ */
|
||
|
+ if (pls == XDEV_RESUME)
|
||
|
+ return;
|
||
|
+
|
||
|
+ /* When the CAS bit is set then warm reset
|
||
|
+ * should be performed on port
|
||
|
+ */
|
||
|
+ if (status_reg & PORT_CAS) {
|
||
|
+ /* The CAS bit can be set while the port is
|
||
|
+ * in any link state.
|
||
|
+ * Only roothubs have CAS bit, so we
|
||
|
+ * pretend to be in compliance mode
|
||
|
+ * unless we're already in compliance
|
||
|
+ * or the inactive state.
|
||
|
+ */
|
||
|
+ if (pls != USB_SS_PORT_LS_COMP_MOD &&
|
||
|
+ pls != USB_SS_PORT_LS_SS_INACTIVE) {
|
||
|
+ pls = USB_SS_PORT_LS_COMP_MOD;
|
||
|
+ }
|
||
|
+ /* Return also connection bit -
|
||
|
+ * hub state machine resets port
|
||
|
+ * when this bit is set.
|
||
|
+ */
|
||
|
+ pls |= USB_PORT_STAT_CONNECTION;
|
||
|
+ }
|
||
|
+ /* update status field */
|
||
|
+ *status |= pls;
|
||
|
+}
|
||
|
+
|
||
|
int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
||
|
u16 wIndex, char *buf, u16 wLength)
|
||
|
{
|
||
|
@@ -579,13 +615,9 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
||
|
else
|
||
|
status |= USB_PORT_STAT_POWER;
|
||
|
}
|
||
|
- /* Port Link State */
|
||
|
+ /* Update Port Link State for super speed ports*/
|
||
|
if (hcd->speed == HCD_USB3) {
|
||
|
- /* resume state is a xHCI internal state.
|
||
|
- * Do not report it to usb core.
|
||
|
- */
|
||
|
- if ((temp & PORT_PLS_MASK) != XDEV_RESUME)
|
||
|
- status |= (temp & PORT_PLS_MASK);
|
||
|
+ xhci_hub_report_link_state(&status, temp);
|
||
|
}
|
||
|
if (bus_state->port_c_suspend & (1 << wIndex))
|
||
|
status |= 1 << USB_PORT_FEAT_C_SUSPEND;
|
||
|
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
|
||
|
index 363b141..7a56805 100644
|
||
|
--- a/drivers/usb/host/xhci.h
|
||
|
+++ b/drivers/usb/host/xhci.h
|
||
|
@@ -341,7 +341,11 @@ struct xhci_op_regs {
|
||
|
#define PORT_PLC (1 << 22)
|
||
|
/* port configure error change - port failed to configure its link partner */
|
||
|
#define PORT_CEC (1 << 23)
|
||
|
-/* bit 24 reserved */
|
||
|
+/* Cold Attach Status - xHC can set this bit to report device attached during
|
||
|
+ * Sx state. Warm port reset should be perfomed to clear this bit and move port
|
||
|
+ * to connected state.
|
||
|
+ */
|
||
|
+#define PORT_CAS (1 << 24)
|
||
|
/* wake on connect (enable) */
|
||
|
#define PORT_WKCONN_E (1 << 25)
|
||
|
/* wake on disconnect (enable) */
|
||
|
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
|
||
|
index 21a4734..5971c95 100644
|
||
|
--- a/drivers/usb/serial/option.c
|
||
|
+++ b/drivers/usb/serial/option.c
|
||
|
@@ -496,6 +496,15 @@ static void option_instat_callback(struct urb *urb);
|
||
|
|
||
|
/* MediaTek products */
|
||
|
#define MEDIATEK_VENDOR_ID 0x0e8d
|
||
|
+#define MEDIATEK_PRODUCT_DC_1COM 0x00a0
|
||
|
+#define MEDIATEK_PRODUCT_DC_4COM 0x00a5
|
||
|
+#define MEDIATEK_PRODUCT_DC_5COM 0x00a4
|
||
|
+#define MEDIATEK_PRODUCT_7208_1COM 0x7101
|
||
|
+#define MEDIATEK_PRODUCT_7208_2COM 0x7102
|
||
|
+#define MEDIATEK_PRODUCT_FP_1COM 0x0003
|
||
|
+#define MEDIATEK_PRODUCT_FP_2COM 0x0023
|
||
|
+#define MEDIATEK_PRODUCT_FPDC_1COM 0x0043
|
||
|
+#define MEDIATEK_PRODUCT_FPDC_2COM 0x0033
|
||
|
|
||
|
/* Cellient products */
|
||
|
#define CELLIENT_VENDOR_ID 0x2692
|
||
|
@@ -553,6 +562,10 @@ static const struct option_blacklist_info net_intf1_blacklist = {
|
||
|
.reserved = BIT(1),
|
||
|
};
|
||
|
|
||
|
+static const struct option_blacklist_info net_intf2_blacklist = {
|
||
|
+ .reserved = BIT(2),
|
||
|
+};
|
||
|
+
|
||
|
static const struct option_blacklist_info net_intf3_blacklist = {
|
||
|
.reserved = BIT(3),
|
||
|
};
|
||
|
@@ -1093,6 +1106,8 @@ static const struct usb_device_id option_ids[] = {
|
||
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
|
||
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
|
||
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
|
||
|
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff),
|
||
|
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
|
||
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
|
||
|
0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
|
||
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
|
||
|
@@ -1234,6 +1249,17 @@ static const struct usb_device_id option_ids[] = {
|
||
|
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) },
|
||
|
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) },
|
||
|
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) }, /* MediaTek MT6276M modem & app port */
|
||
|
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_1COM, 0x0a, 0x00, 0x00) },
|
||
|
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_5COM, 0xff, 0x02, 0x01) },
|
||
|
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_5COM, 0xff, 0x00, 0x00) },
|
||
|
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM, 0xff, 0x02, 0x01) },
|
||
|
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM, 0xff, 0x00, 0x00) },
|
||
|
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7208_1COM, 0x02, 0x00, 0x00) },
|
||
|
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7208_2COM, 0x02, 0x02, 0x01) },
|
||
|
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_1COM, 0x0a, 0x00, 0x00) },
|
||
|
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) },
|
||
|
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) },
|
||
|
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) },
|
||
|
{ USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
|
||
|
{ } /* Terminating entry */
|
||
|
};
|
||
|
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
|
||
|
index c14c42b..ae66278 100644
|
||
|
--- a/drivers/vhost/vhost.c
|
||
|
+++ b/drivers/vhost/vhost.c
|
||
|
@@ -222,6 +222,8 @@ static int vhost_worker(void *data)
|
||
|
if (work) {
|
||
|
__set_current_state(TASK_RUNNING);
|
||
|
work->fn(work);
|
||
|
+ if (need_resched())
|
||
|
+ schedule();
|
||
|
} else
|
||
|
schedule();
|
||
|
|
||
|
diff --git a/fs/buffer.c b/fs/buffer.c
|
||
|
index c807931..4115eca 100644
|
||
|
--- a/fs/buffer.c
|
||
|
+++ b/fs/buffer.c
|
||
|
@@ -1087,6 +1087,9 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
|
||
|
static struct buffer_head *
|
||
|
__getblk_slow(struct block_device *bdev, sector_t block, int size)
|
||
|
{
|
||
|
+ int ret;
|
||
|
+ struct buffer_head *bh;
|
||
|
+
|
||
|
/* Size must be multiple of hard sectorsize */
|
||
|
if (unlikely(size & (bdev_logical_block_size(bdev)-1) ||
|
||
|
(size < 512 || size > PAGE_SIZE))) {
|
||
|
@@ -1099,20 +1102,21 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size)
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
- for (;;) {
|
||
|
- struct buffer_head * bh;
|
||
|
- int ret;
|
||
|
+retry:
|
||
|
+ bh = __find_get_block(bdev, block, size);
|
||
|
+ if (bh)
|
||
|
+ return bh;
|
||
|
|
||
|
+ ret = grow_buffers(bdev, block, size);
|
||
|
+ if (ret == 0) {
|
||
|
+ free_more_memory();
|
||
|
+ goto retry;
|
||
|
+ } else if (ret > 0) {
|
||
|
bh = __find_get_block(bdev, block, size);
|
||
|
if (bh)
|
||
|
return bh;
|
||
|
-
|
||
|
- ret = grow_buffers(bdev, block, size);
|
||
|
- if (ret < 0)
|
||
|
- return NULL;
|
||
|
- if (ret == 0)
|
||
|
- free_more_memory();
|
||
|
}
|
||
|
+ return NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
|
||
|
index b21670c..56c152d 100644
|
||
|
--- a/fs/cifs/connect.c
|
||
|
+++ b/fs/cifs/connect.c
|
||
|
@@ -2925,6 +2925,18 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
|
||
|
#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
|
||
|
#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
|
||
|
|
||
|
+/*
|
||
|
+ * On hosts with high memory, we can't currently support wsize/rsize that are
|
||
|
+ * larger than we can kmap at once. Cap the rsize/wsize at
|
||
|
+ * LAST_PKMAP * PAGE_SIZE. We'll never be able to fill a read or write request
|
||
|
+ * larger than that anyway.
|
||
|
+ */
|
||
|
+#ifdef CONFIG_HIGHMEM
|
||
|
+#define CIFS_KMAP_SIZE_LIMIT (LAST_PKMAP * PAGE_CACHE_SIZE)
|
||
|
+#else /* CONFIG_HIGHMEM */
|
||
|
+#define CIFS_KMAP_SIZE_LIMIT (1<<24)
|
||
|
+#endif /* CONFIG_HIGHMEM */
|
||
|
+
|
||
|
static unsigned int
|
||
|
cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
|
||
|
{
|
||
|
@@ -2955,6 +2967,9 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
|
||
|
wsize = min_t(unsigned int, wsize,
|
||
|
server->maxBuf - sizeof(WRITE_REQ) + 4);
|
||
|
|
||
|
+ /* limit to the amount that we can kmap at once */
|
||
|
+ wsize = min_t(unsigned int, wsize, CIFS_KMAP_SIZE_LIMIT);
|
||
|
+
|
||
|
/* hard limit of CIFS_MAX_WSIZE */
|
||
|
wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
|
||
|
|
||
|
@@ -2996,6 +3011,9 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
|
||
|
if (!(server->capabilities & CAP_LARGE_READ_X))
|
||
|
rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
|
||
|
|
||
|
+ /* limit to the amount that we can kmap at once */
|
||
|
+ rsize = min_t(unsigned int, rsize, CIFS_KMAP_SIZE_LIMIT);
|
||
|
+
|
||
|
/* hard limit of CIFS_MAX_RSIZE */
|
||
|
rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
|
||
|
|
||
|
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
|
||
|
index db4a138..4c37ed4 100644
|
||
|
--- a/fs/cifs/readdir.c
|
||
|
+++ b/fs/cifs/readdir.c
|
||
|
@@ -86,9 +86,12 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
|
||
|
|
||
|
dentry = d_lookup(parent, name);
|
||
|
if (dentry) {
|
||
|
- /* FIXME: check for inode number changes? */
|
||
|
- if (dentry->d_inode != NULL)
|
||
|
+ inode = dentry->d_inode;
|
||
|
+ /* update inode in place if i_ino didn't change */
|
||
|
+ if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
|
||
|
+ cifs_fattr_to_inode(inode, fattr);
|
||
|
return dentry;
|
||
|
+ }
|
||
|
d_drop(dentry);
|
||
|
dput(dentry);
|
||
|
}
|
||
|
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c
|
||
|
index 69f994a..0dbe58a 100644
|
||
|
--- a/fs/ecryptfs/kthread.c
|
||
|
+++ b/fs/ecryptfs/kthread.c
|
||
|
@@ -149,7 +149,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
|
||
|
(*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred);
|
||
|
if (!IS_ERR(*lower_file))
|
||
|
goto out;
|
||
|
- if (flags & O_RDONLY) {
|
||
|
+ if ((flags & O_ACCMODE) == O_RDONLY) {
|
||
|
rc = PTR_ERR((*lower_file));
|
||
|
goto out;
|
||
|
}
|
||
|
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
|
||
|
index 0dc5a3d..de42310 100644
|
||
|
--- a/fs/ecryptfs/miscdev.c
|
||
|
+++ b/fs/ecryptfs/miscdev.c
|
||
|
@@ -49,7 +49,10 @@ ecryptfs_miscdev_poll(struct file *file, poll_table *pt)
|
||
|
mutex_lock(&ecryptfs_daemon_hash_mux);
|
||
|
/* TODO: Just use file->private_data? */
|
||
|
rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
|
||
|
- BUG_ON(rc || !daemon);
|
||
|
+ if (rc || !daemon) {
|
||
|
+ mutex_unlock(&ecryptfs_daemon_hash_mux);
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
mutex_lock(&daemon->mux);
|
||
|
mutex_unlock(&ecryptfs_daemon_hash_mux);
|
||
|
if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
|
||
|
@@ -122,6 +125,7 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
|
||
|
goto out_unlock_daemon;
|
||
|
}
|
||
|
daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN;
|
||
|
+ file->private_data = daemon;
|
||
|
atomic_inc(&ecryptfs_num_miscdev_opens);
|
||
|
out_unlock_daemon:
|
||
|
mutex_unlock(&daemon->mux);
|
||
|
@@ -152,9 +156,9 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file)
|
||
|
|
||
|
mutex_lock(&ecryptfs_daemon_hash_mux);
|
||
|
rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
|
||
|
- BUG_ON(rc || !daemon);
|
||
|
+ if (rc || !daemon)
|
||
|
+ daemon = file->private_data;
|
||
|
mutex_lock(&daemon->mux);
|
||
|
- BUG_ON(daemon->pid != task_pid(current));
|
||
|
BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN));
|
||
|
daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN;
|
||
|
atomic_dec(&ecryptfs_num_miscdev_opens);
|
||
|
@@ -191,31 +195,32 @@ int ecryptfs_send_miscdev(char *data, size_t data_size,
|
||
|
struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
|
||
|
u16 msg_flags, struct ecryptfs_daemon *daemon)
|
||
|
{
|
||
|
- int rc = 0;
|
||
|
+ struct ecryptfs_message *msg;
|
||
|
|
||
|
- mutex_lock(&msg_ctx->mux);
|
||
|
- msg_ctx->msg = kmalloc((sizeof(*msg_ctx->msg) + data_size),
|
||
|
- GFP_KERNEL);
|
||
|
- if (!msg_ctx->msg) {
|
||
|
- rc = -ENOMEM;
|
||
|
+ msg = kmalloc((sizeof(*msg) + data_size), GFP_KERNEL);
|
||
|
+ if (!msg) {
|
||
|
printk(KERN_ERR "%s: Out of memory whilst attempting "
|
||
|
"to kmalloc(%zd, GFP_KERNEL)\n", __func__,
|
||
|
- (sizeof(*msg_ctx->msg) + data_size));
|
||
|
- goto out_unlock;
|
||
|
+ (sizeof(*msg) + data_size));
|
||
|
+ return -ENOMEM;
|
||
|
}
|
||
|
+
|
||
|
+ mutex_lock(&msg_ctx->mux);
|
||
|
+ msg_ctx->msg = msg;
|
||
|
msg_ctx->msg->index = msg_ctx->index;
|
||
|
msg_ctx->msg->data_len = data_size;
|
||
|
msg_ctx->type = msg_type;
|
||
|
memcpy(msg_ctx->msg->data, data, data_size);
|
||
|
msg_ctx->msg_size = (sizeof(*msg_ctx->msg) + data_size);
|
||
|
- mutex_lock(&daemon->mux);
|
||
|
list_add_tail(&msg_ctx->daemon_out_list, &daemon->msg_ctx_out_queue);
|
||
|
+ mutex_unlock(&msg_ctx->mux);
|
||
|
+
|
||
|
+ mutex_lock(&daemon->mux);
|
||
|
daemon->num_queued_msg_ctx++;
|
||
|
wake_up_interruptible(&daemon->wait);
|
||
|
mutex_unlock(&daemon->mux);
|
||
|
-out_unlock:
|
||
|
- mutex_unlock(&msg_ctx->mux);
|
||
|
- return rc;
|
||
|
+
|
||
|
+ return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
@@ -246,8 +251,16 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
|
||
|
mutex_lock(&ecryptfs_daemon_hash_mux);
|
||
|
/* TODO: Just use file->private_data? */
|
||
|
rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
|
||
|
- BUG_ON(rc || !daemon);
|
||
|
+ if (rc || !daemon) {
|
||
|
+ mutex_unlock(&ecryptfs_daemon_hash_mux);
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
mutex_lock(&daemon->mux);
|
||
|
+ if (task_pid(current) != daemon->pid) {
|
||
|
+ mutex_unlock(&daemon->mux);
|
||
|
+ mutex_unlock(&ecryptfs_daemon_hash_mux);
|
||
|
+ return -EPERM;
|
||
|
+ }
|
||
|
if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
|
||
|
rc = 0;
|
||
|
mutex_unlock(&ecryptfs_daemon_hash_mux);
|
||
|
@@ -284,9 +297,6 @@ check_list:
|
||
|
* message from the queue; try again */
|
||
|
goto check_list;
|
||
|
}
|
||
|
- BUG_ON(euid != daemon->euid);
|
||
|
- BUG_ON(current_user_ns() != daemon->user_ns);
|
||
|
- BUG_ON(task_pid(current) != daemon->pid);
|
||
|
msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
|
||
|
struct ecryptfs_msg_ctx, daemon_out_list);
|
||
|
BUG_ON(!msg_ctx);
|
||
|
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
|
||
|
index 4d9d3a4..a6f3763 100644
|
||
|
--- a/fs/eventpoll.c
|
||
|
+++ b/fs/eventpoll.c
|
||
|
@@ -1629,8 +1629,10 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
|
||
|
if (op == EPOLL_CTL_ADD) {
|
||
|
if (is_file_epoll(tfile)) {
|
||
|
error = -ELOOP;
|
||
|
- if (ep_loop_check(ep, tfile) != 0)
|
||
|
+ if (ep_loop_check(ep, tfile) != 0) {
|
||
|
+ clear_tfile_check_list();
|
||
|
goto error_tgt_fput;
|
||
|
+ }
|
||
|
} else
|
||
|
list_add(&tfile->f_tfile_llink, &tfile_check_list);
|
||
|
}
|
||
|
diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c
|
||
|
index 49cf230..24a49d4 100644
|
||
|
--- a/fs/exofs/ore.c
|
||
|
+++ b/fs/exofs/ore.c
|
||
|
@@ -735,13 +735,7 @@ static int _prepare_for_striping(struct ore_io_state *ios)
|
||
|
out:
|
||
|
ios->numdevs = devs_in_group;
|
||
|
ios->pages_consumed = cur_pg;
|
||
|
- if (unlikely(ret)) {
|
||
|
- if (length == ios->length)
|
||
|
- return ret;
|
||
|
- else
|
||
|
- ios->length -= length;
|
||
|
- }
|
||
|
- return 0;
|
||
|
+ return ret;
|
||
|
}
|
||
|
|
||
|
int ore_create(struct ore_io_state *ios)
|
||
|
diff --git a/fs/exofs/ore_raid.c b/fs/exofs/ore_raid.c
|
||
|
index d222c77..fff2070 100644
|
||
|
--- a/fs/exofs/ore_raid.c
|
||
|
+++ b/fs/exofs/ore_raid.c
|
||
|
@@ -461,16 +461,12 @@ static void _mark_read4write_pages_uptodate(struct ore_io_state *ios, int ret)
|
||
|
* ios->sp2d[p][*], xor is calculated the same way. These pages are
|
||
|
* allocated/freed and don't go through cache
|
||
|
*/
|
||
|
-static int _read_4_write(struct ore_io_state *ios)
|
||
|
+static int _read_4_write_first_stripe(struct ore_io_state *ios)
|
||
|
{
|
||
|
- struct ore_io_state *ios_read;
|
||
|
struct ore_striping_info read_si;
|
||
|
struct __stripe_pages_2d *sp2d = ios->sp2d;
|
||
|
u64 offset = ios->si.first_stripe_start;
|
||
|
- u64 last_stripe_end;
|
||
|
- unsigned bytes_in_stripe = ios->si.bytes_in_stripe;
|
||
|
- unsigned i, c, p, min_p = sp2d->pages_in_unit, max_p = -1;
|
||
|
- int ret;
|
||
|
+ unsigned c, p, min_p = sp2d->pages_in_unit, max_p = -1;
|
||
|
|
||
|
if (offset == ios->offset) /* Go to start collect $200 */
|
||
|
goto read_last_stripe;
|
||
|
@@ -478,6 +474,9 @@ static int _read_4_write(struct ore_io_state *ios)
|
||
|
min_p = _sp2d_min_pg(sp2d);
|
||
|
max_p = _sp2d_max_pg(sp2d);
|
||
|
|
||
|
+ ORE_DBGMSG("stripe_start=0x%llx ios->offset=0x%llx min_p=%d max_p=%d\n",
|
||
|
+ offset, ios->offset, min_p, max_p);
|
||
|
+
|
||
|
for (c = 0; ; c++) {
|
||
|
ore_calc_stripe_info(ios->layout, offset, 0, &read_si);
|
||
|
read_si.obj_offset += min_p * PAGE_SIZE;
|
||
|
@@ -512,6 +511,18 @@ static int _read_4_write(struct ore_io_state *ios)
|
||
|
}
|
||
|
|
||
|
read_last_stripe:
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int _read_4_write_last_stripe(struct ore_io_state *ios)
|
||
|
+{
|
||
|
+ struct ore_striping_info read_si;
|
||
|
+ struct __stripe_pages_2d *sp2d = ios->sp2d;
|
||
|
+ u64 offset;
|
||
|
+ u64 last_stripe_end;
|
||
|
+ unsigned bytes_in_stripe = ios->si.bytes_in_stripe;
|
||
|
+ unsigned c, p, min_p = sp2d->pages_in_unit, max_p = -1;
|
||
|
+
|
||
|
offset = ios->offset + ios->length;
|
||
|
if (offset % PAGE_SIZE)
|
||
|
_add_to_r4w_last_page(ios, &offset);
|
||
|
@@ -527,15 +538,15 @@ read_last_stripe:
|
||
|
c = _dev_order(ios->layout->group_width * ios->layout->mirrors_p1,
|
||
|
ios->layout->mirrors_p1, read_si.par_dev, read_si.dev);
|
||
|
|
||
|
- BUG_ON(ios->si.first_stripe_start + bytes_in_stripe != last_stripe_end);
|
||
|
- /* unaligned IO must be within a single stripe */
|
||
|
-
|
||
|
if (min_p == sp2d->pages_in_unit) {
|
||
|
/* Didn't do it yet */
|
||
|
min_p = _sp2d_min_pg(sp2d);
|
||
|
max_p = _sp2d_max_pg(sp2d);
|
||
|
}
|
||
|
|
||
|
+ ORE_DBGMSG("offset=0x%llx stripe_end=0x%llx min_p=%d max_p=%d\n",
|
||
|
+ offset, last_stripe_end, min_p, max_p);
|
||
|
+
|
||
|
while (offset < last_stripe_end) {
|
||
|
struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p];
|
||
|
|
||
|
@@ -568,6 +579,15 @@ read_last_stripe:
|
||
|
}
|
||
|
|
||
|
read_it:
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int _read_4_write_execute(struct ore_io_state *ios)
|
||
|
+{
|
||
|
+ struct ore_io_state *ios_read;
|
||
|
+ unsigned i;
|
||
|
+ int ret;
|
||
|
+
|
||
|
ios_read = ios->ios_read_4_write;
|
||
|
if (!ios_read)
|
||
|
return 0;
|
||
|
@@ -591,6 +611,8 @@ read_it:
|
||
|
}
|
||
|
|
||
|
_mark_read4write_pages_uptodate(ios_read, ret);
|
||
|
+ ore_put_io_state(ios_read);
|
||
|
+ ios->ios_read_4_write = NULL; /* Might need a reuse at last stripe */
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@@ -626,8 +648,11 @@ int _ore_add_parity_unit(struct ore_io_state *ios,
|
||
|
/* If first stripe, Read in all read4write pages
|
||
|
* (if needed) before we calculate the first parity.
|
||
|
*/
|
||
|
- _read_4_write(ios);
|
||
|
+ _read_4_write_first_stripe(ios);
|
||
|
}
|
||
|
+ if (!cur_len) /* If last stripe r4w pages of last stripe */
|
||
|
+ _read_4_write_last_stripe(ios);
|
||
|
+ _read_4_write_execute(ios);
|
||
|
|
||
|
for (i = 0; i < num_pages; i++) {
|
||
|
pages[i] = _raid_page_alloc();
|
||
|
@@ -654,34 +679,14 @@ int _ore_add_parity_unit(struct ore_io_state *ios,
|
||
|
|
||
|
int _ore_post_alloc_raid_stuff(struct ore_io_state *ios)
|
||
|
{
|
||
|
- struct ore_layout *layout = ios->layout;
|
||
|
-
|
||
|
if (ios->parity_pages) {
|
||
|
+ struct ore_layout *layout = ios->layout;
|
||
|
unsigned pages_in_unit = layout->stripe_unit / PAGE_SIZE;
|
||
|
- unsigned stripe_size = ios->si.bytes_in_stripe;
|
||
|
- u64 last_stripe, first_stripe;
|
||
|
|
||
|
if (_sp2d_alloc(pages_in_unit, layout->group_width,
|
||
|
layout->parity, &ios->sp2d)) {
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
-
|
||
|
- /* Round io down to last full strip */
|
||
|
- first_stripe = div_u64(ios->offset, stripe_size);
|
||
|
- last_stripe = div_u64(ios->offset + ios->length, stripe_size);
|
||
|
-
|
||
|
- /* If an IO spans more then a single stripe it must end at
|
||
|
- * a stripe boundary. The reminder at the end is pushed into the
|
||
|
- * next IO.
|
||
|
- */
|
||
|
- if (last_stripe != first_stripe) {
|
||
|
- ios->length = last_stripe * stripe_size - ios->offset;
|
||
|
-
|
||
|
- BUG_ON(!ios->length);
|
||
|
- ios->nr_pages = (ios->length + PAGE_SIZE - 1) /
|
||
|
- PAGE_SIZE;
|
||
|
- ios->si.length = ios->length; /*make it consistent */
|
||
|
- }
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
|
||
|
index ab7aa3f..a93486e 100644
|
||
|
--- a/fs/ext4/super.c
|
||
|
+++ b/fs/ext4/super.c
|
||
|
@@ -1097,7 +1097,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
|
||
|
}
|
||
|
if (sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME) {
|
||
|
seq_printf(seq, ",max_batch_time=%u",
|
||
|
- (unsigned) sbi->s_min_batch_time);
|
||
|
+ (unsigned) sbi->s_max_batch_time);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
diff --git a/fs/fifo.c b/fs/fifo.c
|
||
|
index b1a524d..cf6f434 100644
|
||
|
--- a/fs/fifo.c
|
||
|
+++ b/fs/fifo.c
|
||
|
@@ -14,7 +14,7 @@
|
||
|
#include <linux/sched.h>
|
||
|
#include <linux/pipe_fs_i.h>
|
||
|
|
||
|
-static void wait_for_partner(struct inode* inode, unsigned int *cnt)
|
||
|
+static int wait_for_partner(struct inode* inode, unsigned int *cnt)
|
||
|
{
|
||
|
int cur = *cnt;
|
||
|
|
||
|
@@ -23,6 +23,7 @@ static void wait_for_partner(struct inode* inode, unsigned int *cnt)
|
||
|
if (signal_pending(current))
|
||
|
break;
|
||
|
}
|
||
|
+ return cur == *cnt ? -ERESTARTSYS : 0;
|
||
|
}
|
||
|
|
||
|
static void wake_up_partner(struct inode* inode)
|
||
|
@@ -67,8 +68,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
|
||
|
* seen a writer */
|
||
|
filp->f_version = pipe->w_counter;
|
||
|
} else {
|
||
|
- wait_for_partner(inode, &pipe->w_counter);
|
||
|
- if(signal_pending(current))
|
||
|
+ if (wait_for_partner(inode, &pipe->w_counter))
|
||
|
goto err_rd;
|
||
|
}
|
||
|
}
|
||
|
@@ -90,8 +90,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
|
||
|
wake_up_partner(inode);
|
||
|
|
||
|
if (!pipe->readers) {
|
||
|
- wait_for_partner(inode, &pipe->r_counter);
|
||
|
- if (signal_pending(current))
|
||
|
+ if (wait_for_partner(inode, &pipe->r_counter))
|
||
|
goto err_wr;
|
||
|
}
|
||
|
break;
|
||
|
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
|
||
|
index 2d0ca24..ebc2f4d 100644
|
||
|
--- a/fs/hugetlbfs/inode.c
|
||
|
+++ b/fs/hugetlbfs/inode.c
|
||
|
@@ -592,9 +592,15 @@ static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||
|
spin_lock(&sbinfo->stat_lock);
|
||
|
/* If no limits set, just report 0 for max/free/used
|
||
|
* blocks, like simple_statfs() */
|
||
|
- if (sbinfo->max_blocks >= 0) {
|
||
|
- buf->f_blocks = sbinfo->max_blocks;
|
||
|
- buf->f_bavail = buf->f_bfree = sbinfo->free_blocks;
|
||
|
+ if (sbinfo->spool) {
|
||
|
+ long free_pages;
|
||
|
+
|
||
|
+ spin_lock(&sbinfo->spool->lock);
|
||
|
+ buf->f_blocks = sbinfo->spool->max_hpages;
|
||
|
+ free_pages = sbinfo->spool->max_hpages
|
||
|
+ - sbinfo->spool->used_hpages;
|
||
|
+ buf->f_bavail = buf->f_bfree = free_pages;
|
||
|
+ spin_unlock(&sbinfo->spool->lock);
|
||
|
buf->f_files = sbinfo->max_inodes;
|
||
|
buf->f_ffree = sbinfo->free_inodes;
|
||
|
}
|
||
|
@@ -610,6 +616,10 @@ static void hugetlbfs_put_super(struct super_block *sb)
|
||
|
|
||
|
if (sbi) {
|
||
|
sb->s_fs_info = NULL;
|
||
|
+
|
||
|
+ if (sbi->spool)
|
||
|
+ hugepage_put_subpool(sbi->spool);
|
||
|
+
|
||
|
kfree(sbi);
|
||
|
}
|
||
|
}
|
||
|
@@ -841,10 +851,14 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
|
||
|
sb->s_fs_info = sbinfo;
|
||
|
sbinfo->hstate = config.hstate;
|
||
|
spin_lock_init(&sbinfo->stat_lock);
|
||
|
- sbinfo->max_blocks = config.nr_blocks;
|
||
|
- sbinfo->free_blocks = config.nr_blocks;
|
||
|
sbinfo->max_inodes = config.nr_inodes;
|
||
|
sbinfo->free_inodes = config.nr_inodes;
|
||
|
+ sbinfo->spool = NULL;
|
||
|
+ if (config.nr_blocks != -1) {
|
||
|
+ sbinfo->spool = hugepage_new_subpool(config.nr_blocks);
|
||
|
+ if (!sbinfo->spool)
|
||
|
+ goto out_free;
|
||
|
+ }
|
||
|
sb->s_maxbytes = MAX_LFS_FILESIZE;
|
||
|
sb->s_blocksize = huge_page_size(config.hstate);
|
||
|
sb->s_blocksize_bits = huge_page_shift(config.hstate);
|
||
|
@@ -864,38 +878,12 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
|
||
|
sb->s_root = root;
|
||
|
return 0;
|
||
|
out_free:
|
||
|
+ if (sbinfo->spool)
|
||
|
+ kfree(sbinfo->spool);
|
||
|
kfree(sbinfo);
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
|
||
|
-int hugetlb_get_quota(struct address_space *mapping, long delta)
|
||
|
-{
|
||
|
- int ret = 0;
|
||
|
- struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb);
|
||
|
-
|
||
|
- if (sbinfo->free_blocks > -1) {
|
||
|
- spin_lock(&sbinfo->stat_lock);
|
||
|
- if (sbinfo->free_blocks - delta >= 0)
|
||
|
- sbinfo->free_blocks -= delta;
|
||
|
- else
|
||
|
- ret = -ENOMEM;
|
||
|
- spin_unlock(&sbinfo->stat_lock);
|
||
|
- }
|
||
|
-
|
||
|
- return ret;
|
||
|
-}
|
||
|
-
|
||
|
-void hugetlb_put_quota(struct address_space *mapping, long delta)
|
||
|
-{
|
||
|
- struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb);
|
||
|
-
|
||
|
- if (sbinfo->free_blocks > -1) {
|
||
|
- spin_lock(&sbinfo->stat_lock);
|
||
|
- sbinfo->free_blocks += delta;
|
||
|
- spin_unlock(&sbinfo->stat_lock);
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
static struct dentry *hugetlbfs_mount(struct file_system_type *fs_type,
|
||
|
int flags, const char *dev_name, void *data)
|
||
|
{
|
||
|
diff --git a/fs/locks.c b/fs/locks.c
|
||
|
index 0d68f1f..6a64f15 100644
|
||
|
--- a/fs/locks.c
|
||
|
+++ b/fs/locks.c
|
||
|
@@ -1465,7 +1465,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
|
||
|
case F_WRLCK:
|
||
|
return generic_add_lease(filp, arg, flp);
|
||
|
default:
|
||
|
- BUG();
|
||
|
+ return -EINVAL;
|
||
|
}
|
||
|
}
|
||
|
EXPORT_SYMBOL(generic_setlease);
|
||
|
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
|
||
|
index 47d1c6f..b122af8 100644
|
||
|
--- a/fs/nfs/idmap.c
|
||
|
+++ b/fs/nfs/idmap.c
|
||
|
@@ -318,12 +318,12 @@ struct idmap_hashent {
|
||
|
unsigned long ih_expires;
|
||
|
__u32 ih_id;
|
||
|
size_t ih_namelen;
|
||
|
- char ih_name[IDMAP_NAMESZ];
|
||
|
+ const char *ih_name;
|
||
|
};
|
||
|
|
||
|
struct idmap_hashtable {
|
||
|
__u8 h_type;
|
||
|
- struct idmap_hashent h_entries[IDMAP_HASH_SZ];
|
||
|
+ struct idmap_hashent *h_entries;
|
||
|
};
|
||
|
|
||
|
struct idmap {
|
||
|
@@ -378,6 +378,28 @@ nfs_idmap_new(struct nfs_client *clp)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static void
|
||
|
+idmap_alloc_hashtable(struct idmap_hashtable *h)
|
||
|
+{
|
||
|
+ if (h->h_entries != NULL)
|
||
|
+ return;
|
||
|
+ h->h_entries = kcalloc(IDMAP_HASH_SZ,
|
||
|
+ sizeof(*h->h_entries),
|
||
|
+ GFP_KERNEL);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+idmap_free_hashtable(struct idmap_hashtable *h)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+
|
||
|
+ if (h->h_entries == NULL)
|
||
|
+ return;
|
||
|
+ for (i = 0; i < IDMAP_HASH_SZ; i++)
|
||
|
+ kfree(h->h_entries[i].ih_name);
|
||
|
+ kfree(h->h_entries);
|
||
|
+}
|
||
|
+
|
||
|
void
|
||
|
nfs_idmap_delete(struct nfs_client *clp)
|
||
|
{
|
||
|
@@ -387,6 +409,8 @@ nfs_idmap_delete(struct nfs_client *clp)
|
||
|
return;
|
||
|
rpc_unlink(idmap->idmap_dentry);
|
||
|
clp->cl_idmap = NULL;
|
||
|
+ idmap_free_hashtable(&idmap->idmap_user_hash);
|
||
|
+ idmap_free_hashtable(&idmap->idmap_group_hash);
|
||
|
kfree(idmap);
|
||
|
}
|
||
|
|
||
|
@@ -396,6 +420,8 @@ nfs_idmap_delete(struct nfs_client *clp)
|
||
|
static inline struct idmap_hashent *
|
||
|
idmap_name_hash(struct idmap_hashtable* h, const char *name, size_t len)
|
||
|
{
|
||
|
+ if (h->h_entries == NULL)
|
||
|
+ return NULL;
|
||
|
return &h->h_entries[fnvhash32(name, len) % IDMAP_HASH_SZ];
|
||
|
}
|
||
|
|
||
|
@@ -404,6 +430,8 @@ idmap_lookup_name(struct idmap_hashtable *h, const char *name, size_t len)
|
||
|
{
|
||
|
struct idmap_hashent *he = idmap_name_hash(h, name, len);
|
||
|
|
||
|
+ if (he == NULL)
|
||
|
+ return NULL;
|
||
|
if (he->ih_namelen != len || memcmp(he->ih_name, name, len) != 0)
|
||
|
return NULL;
|
||
|
if (time_after(jiffies, he->ih_expires))
|
||
|
@@ -414,6 +442,8 @@ idmap_lookup_name(struct idmap_hashtable *h, const char *name, size_t len)
|
||
|
static inline struct idmap_hashent *
|
||
|
idmap_id_hash(struct idmap_hashtable* h, __u32 id)
|
||
|
{
|
||
|
+ if (h->h_entries == NULL)
|
||
|
+ return NULL;
|
||
|
return &h->h_entries[fnvhash32(&id, sizeof(id)) % IDMAP_HASH_SZ];
|
||
|
}
|
||
|
|
||
|
@@ -421,6 +451,9 @@ static struct idmap_hashent *
|
||
|
idmap_lookup_id(struct idmap_hashtable *h, __u32 id)
|
||
|
{
|
||
|
struct idmap_hashent *he = idmap_id_hash(h, id);
|
||
|
+
|
||
|
+ if (he == NULL)
|
||
|
+ return NULL;
|
||
|
if (he->ih_id != id || he->ih_namelen == 0)
|
||
|
return NULL;
|
||
|
if (time_after(jiffies, he->ih_expires))
|
||
|
@@ -436,12 +469,14 @@ idmap_lookup_id(struct idmap_hashtable *h, __u32 id)
|
||
|
static inline struct idmap_hashent *
|
||
|
idmap_alloc_name(struct idmap_hashtable *h, char *name, size_t len)
|
||
|
{
|
||
|
+ idmap_alloc_hashtable(h);
|
||
|
return idmap_name_hash(h, name, len);
|
||
|
}
|
||
|
|
||
|
static inline struct idmap_hashent *
|
||
|
idmap_alloc_id(struct idmap_hashtable *h, __u32 id)
|
||
|
{
|
||
|
+ idmap_alloc_hashtable(h);
|
||
|
return idmap_id_hash(h, id);
|
||
|
}
|
||
|
|
||
|
@@ -449,9 +484,14 @@ static void
|
||
|
idmap_update_entry(struct idmap_hashent *he, const char *name,
|
||
|
size_t namelen, __u32 id)
|
||
|
{
|
||
|
+ char *str = kmalloc(namelen + 1, GFP_KERNEL);
|
||
|
+ if (str == NULL)
|
||
|
+ return;
|
||
|
+ kfree(he->ih_name);
|
||
|
he->ih_id = id;
|
||
|
- memcpy(he->ih_name, name, namelen);
|
||
|
- he->ih_name[namelen] = '\0';
|
||
|
+ memcpy(str, name, namelen);
|
||
|
+ str[namelen] = '\0';
|
||
|
+ he->ih_name = str;
|
||
|
he->ih_namelen = namelen;
|
||
|
he->ih_expires = jiffies + nfs_idmap_cache_timeout;
|
||
|
}
|
||
|
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
|
||
|
index 66020ac..07354b7 100644
|
||
|
--- a/fs/nfs/nfs4state.c
|
||
|
+++ b/fs/nfs/nfs4state.c
|
||
|
@@ -1186,8 +1186,9 @@ restart:
|
||
|
spin_lock(&state->state_lock);
|
||
|
list_for_each_entry(lock, &state->lock_states, ls_locks) {
|
||
|
if (!(lock->ls_flags & NFS_LOCK_INITIALIZED))
|
||
|
- printk("%s: Lock reclaim failed!\n",
|
||
|
- __func__);
|
||
|
+ pr_warn_ratelimited("NFS: "
|
||
|
+ "%s: Lock reclaim "
|
||
|
+ "failed!\n", __func__);
|
||
|
}
|
||
|
spin_unlock(&state->state_lock);
|
||
|
nfs4_put_open_state(state);
|
||
|
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c
|
||
|
index 55d0128..a03ee52 100644
|
||
|
--- a/fs/nfs/objlayout/objio_osd.c
|
||
|
+++ b/fs/nfs/objlayout/objio_osd.c
|
||
|
@@ -433,7 +433,10 @@ int objio_read_pagelist(struct nfs_read_data *rdata)
|
||
|
objios->ios->done = _read_done;
|
||
|
dprintk("%s: offset=0x%llx length=0x%x\n", __func__,
|
||
|
rdata->args.offset, rdata->args.count);
|
||
|
- return ore_read(objios->ios);
|
||
|
+ ret = ore_read(objios->ios);
|
||
|
+ if (unlikely(ret))
|
||
|
+ objio_free_result(&objios->oir);
|
||
|
+ return ret;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
@@ -464,8 +467,16 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
|
||
|
struct objio_state *objios = priv;
|
||
|
struct nfs_write_data *wdata = objios->oir.rpcdata;
|
||
|
pgoff_t index = offset / PAGE_SIZE;
|
||
|
- struct page *page = find_get_page(wdata->inode->i_mapping, index);
|
||
|
+ struct page *page;
|
||
|
+ loff_t i_size = i_size_read(wdata->inode);
|
||
|
+
|
||
|
+ if (offset >= i_size) {
|
||
|
+ *uptodate = true;
|
||
|
+ dprintk("%s: g_zero_page index=0x%lx\n", __func__, index);
|
||
|
+ return ZERO_PAGE(0);
|
||
|
+ }
|
||
|
|
||
|
+ page = find_get_page(wdata->inode->i_mapping, index);
|
||
|
if (!page) {
|
||
|
page = find_or_create_page(wdata->inode->i_mapping,
|
||
|
index, GFP_NOFS);
|
||
|
@@ -486,8 +497,10 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
|
||
|
|
||
|
static void __r4w_put_page(void *priv, struct page *page)
|
||
|
{
|
||
|
- dprintk("%s: index=0x%lx\n", __func__, page->index);
|
||
|
- page_cache_release(page);
|
||
|
+ dprintk("%s: index=0x%lx\n", __func__,
|
||
|
+ (page == ZERO_PAGE(0)) ? -1UL : page->index);
|
||
|
+ if (ZERO_PAGE(0) != page)
|
||
|
+ page_cache_release(page);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
@@ -517,8 +530,10 @@ int objio_write_pagelist(struct nfs_write_data *wdata, int how)
|
||
|
dprintk("%s: offset=0x%llx length=0x%x\n", __func__,
|
||
|
wdata->args.offset, wdata->args.count);
|
||
|
ret = ore_write(objios->ios);
|
||
|
- if (unlikely(ret))
|
||
|
+ if (unlikely(ret)) {
|
||
|
+ objio_free_result(&objios->oir);
|
||
|
return ret;
|
||
|
+ }
|
||
|
|
||
|
if (objios->sync)
|
||
|
_write_done(objios->ios, objios);
|
||
|
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
|
||
|
index 07ee5b4..1c7d45e 100644
|
||
|
--- a/fs/ocfs2/file.c
|
||
|
+++ b/fs/ocfs2/file.c
|
||
|
@@ -1950,7 +1950,7 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode,
|
||
|
if (ret < 0)
|
||
|
mlog_errno(ret);
|
||
|
|
||
|
- if (file->f_flags & O_SYNC)
|
||
|
+ if (file && (file->f_flags & O_SYNC))
|
||
|
handle->h_sync = 1;
|
||
|
|
||
|
ocfs2_commit_trans(osb, handle);
|
||
|
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
|
||
|
index fbb0b47..d5378d0 100644
|
||
|
--- a/fs/ramfs/file-nommu.c
|
||
|
+++ b/fs/ramfs/file-nommu.c
|
||
|
@@ -110,6 +110,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
|
||
|
|
||
|
/* prevent the page from being discarded on memory pressure */
|
||
|
SetPageDirty(page);
|
||
|
+ SetPageUptodate(page);
|
||
|
|
||
|
unlock_page(page);
|
||
|
put_page(page);
|
||
|
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
|
||
|
index 6094c5a..b73ecd8 100644
|
||
|
--- a/fs/ubifs/sb.c
|
||
|
+++ b/fs/ubifs/sb.c
|
||
|
@@ -715,8 +715,12 @@ static int fixup_free_space(struct ubifs_info *c)
|
||
|
lnum = ubifs_next_log_lnum(c, lnum);
|
||
|
}
|
||
|
|
||
|
- /* Fixup the current log head */
|
||
|
- err = fixup_leb(c, c->lhead_lnum, c->lhead_offs);
|
||
|
+ /*
|
||
|
+ * Fixup the log head which contains the only a CS node at the
|
||
|
+ * beginning.
|
||
|
+ */
|
||
|
+ err = fixup_leb(c, c->lhead_lnum,
|
||
|
+ ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size));
|
||
|
if (err)
|
||
|
goto out;
|
||
|
|
||
|
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
|
||
|
index bd21ecd..a3ce901 100644
|
||
|
--- a/include/linux/Kbuild
|
||
|
+++ b/include/linux/Kbuild
|
||
|
@@ -268,6 +268,7 @@ header-y += netfilter_ipv4.h
|
||
|
header-y += netfilter_ipv6.h
|
||
|
header-y += netlink.h
|
||
|
header-y += netrom.h
|
||
|
+header-y += nfc.h
|
||
|
header-y += nfs.h
|
||
|
header-y += nfs2.h
|
||
|
header-y += nfs3.h
|
||
|
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
|
||
|
index fd0dc30..cc07d27 100644
|
||
|
--- a/include/linux/hrtimer.h
|
||
|
+++ b/include/linux/hrtimer.h
|
||
|
@@ -165,6 +165,7 @@ enum hrtimer_base_type {
|
||
|
* @lock: lock protecting the base and associated clock bases
|
||
|
* and timers
|
||
|
* @active_bases: Bitfield to mark bases with active timers
|
||
|
+ * @clock_was_set: Indicates that clock was set from irq context.
|
||
|
* @expires_next: absolute time of the next event which was scheduled
|
||
|
* via clock_set_next_event()
|
||
|
* @hres_active: State of high resolution mode
|
||
|
@@ -177,7 +178,8 @@ enum hrtimer_base_type {
|
||
|
*/
|
||
|
struct hrtimer_cpu_base {
|
||
|
raw_spinlock_t lock;
|
||
|
- unsigned long active_bases;
|
||
|
+ unsigned int active_bases;
|
||
|
+ unsigned int clock_was_set;
|
||
|
#ifdef CONFIG_HIGH_RES_TIMERS
|
||
|
ktime_t expires_next;
|
||
|
int hres_active;
|
||
|
@@ -286,6 +288,8 @@ extern void hrtimer_peek_ahead_timers(void);
|
||
|
# define MONOTONIC_RES_NSEC HIGH_RES_NSEC
|
||
|
# define KTIME_MONOTONIC_RES KTIME_HIGH_RES
|
||
|
|
||
|
+extern void clock_was_set_delayed(void);
|
||
|
+
|
||
|
#else
|
||
|
|
||
|
# define MONOTONIC_RES_NSEC LOW_RES_NSEC
|
||
|
@@ -306,6 +310,9 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
+
|
||
|
+static inline void clock_was_set_delayed(void) { }
|
||
|
+
|
||
|
#endif
|
||
|
|
||
|
extern void clock_was_set(void);
|
||
|
@@ -320,6 +327,7 @@ extern ktime_t ktime_get(void);
|
||
|
extern ktime_t ktime_get_real(void);
|
||
|
extern ktime_t ktime_get_boottime(void);
|
||
|
extern ktime_t ktime_get_monotonic_offset(void);
|
||
|
+extern ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot);
|
||
|
|
||
|
DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
|
||
|
|
||
|
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
|
||
|
index d9d6c86..c5ed2f1 100644
|
||
|
--- a/include/linux/hugetlb.h
|
||
|
+++ b/include/linux/hugetlb.h
|
||
|
@@ -14,6 +14,15 @@ struct user_struct;
|
||
|
#include <linux/shm.h>
|
||
|
#include <asm/tlbflush.h>
|
||
|
|
||
|
+struct hugepage_subpool {
|
||
|
+ spinlock_t lock;
|
||
|
+ long count;
|
||
|
+ long max_hpages, used_hpages;
|
||
|
+};
|
||
|
+
|
||
|
+struct hugepage_subpool *hugepage_new_subpool(long nr_blocks);
|
||
|
+void hugepage_put_subpool(struct hugepage_subpool *spool);
|
||
|
+
|
||
|
int PageHuge(struct page *page);
|
||
|
|
||
|
void reset_vma_resv_huge_pages(struct vm_area_struct *vma);
|
||
|
@@ -138,12 +147,11 @@ struct hugetlbfs_config {
|
||
|
};
|
||
|
|
||
|
struct hugetlbfs_sb_info {
|
||
|
- long max_blocks; /* blocks allowed */
|
||
|
- long free_blocks; /* blocks free */
|
||
|
long max_inodes; /* inodes allowed */
|
||
|
long free_inodes; /* inodes free */
|
||
|
spinlock_t stat_lock;
|
||
|
struct hstate *hstate;
|
||
|
+ struct hugepage_subpool *spool;
|
||
|
};
|
||
|
|
||
|
|
||
|
@@ -166,8 +174,6 @@ extern const struct file_operations hugetlbfs_file_operations;
|
||
|
extern const struct vm_operations_struct hugetlb_vm_ops;
|
||
|
struct file *hugetlb_file_setup(const char *name, size_t size, vm_flags_t acct,
|
||
|
struct user_struct **user, int creat_flags);
|
||
|
-int hugetlb_get_quota(struct address_space *mapping, long delta);
|
||
|
-void hugetlb_put_quota(struct address_space *mapping, long delta);
|
||
|
|
||
|
static inline int is_file_hugepages(struct file *file)
|
||
|
{
|
||
|
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
|
||
|
index 188cb2f..905b1e1 100644
|
||
|
--- a/include/linux/mmzone.h
|
||
|
+++ b/include/linux/mmzone.h
|
||
|
@@ -652,7 +652,7 @@ typedef struct pglist_data {
|
||
|
range, including holes */
|
||
|
int node_id;
|
||
|
wait_queue_head_t kswapd_wait;
|
||
|
- struct task_struct *kswapd;
|
||
|
+ struct task_struct *kswapd; /* Protected by lock_memory_hotplug() */
|
||
|
int kswapd_max_order;
|
||
|
enum zone_type classzone_idx;
|
||
|
} pg_data_t;
|
||
|
diff --git a/include/linux/pci.h b/include/linux/pci.h
|
||
|
index c0cfa0d..7cda65b 100644
|
||
|
--- a/include/linux/pci.h
|
||
|
+++ b/include/linux/pci.h
|
||
|
@@ -176,8 +176,6 @@ enum pci_dev_flags {
|
||
|
PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2,
|
||
|
/* Provide indication device is assigned by a Virtual Machine Manager */
|
||
|
PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4,
|
||
|
- /* Device causes system crash if in D3 during S3 sleep */
|
||
|
- PCI_DEV_FLAGS_NO_D3_DURING_SLEEP = (__force pci_dev_flags_t) 8,
|
||
|
};
|
||
|
|
||
|
enum pci_irq_reroute_variant {
|
||
|
diff --git a/include/linux/sched.h b/include/linux/sched.h
|
||
|
index 1c4f3e9..5afa2a3 100644
|
||
|
--- a/include/linux/sched.h
|
||
|
+++ b/include/linux/sched.h
|
||
|
@@ -1892,6 +1892,14 @@ static inline int set_cpus_allowed_ptr(struct task_struct *p,
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
+#ifdef CONFIG_NO_HZ
|
||
|
+void calc_load_enter_idle(void);
|
||
|
+void calc_load_exit_idle(void);
|
||
|
+#else
|
||
|
+static inline void calc_load_enter_idle(void) { }
|
||
|
+static inline void calc_load_exit_idle(void) { }
|
||
|
+#endif /* CONFIG_NO_HZ */
|
||
|
+
|
||
|
#ifndef CONFIG_CPUMASK_OFFSTACK
|
||
|
static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
|
||
|
{
|
||
|
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
|
||
|
index bdb4590..53dc7e7 100644
|
||
|
--- a/include/linux/skbuff.h
|
||
|
+++ b/include/linux/skbuff.h
|
||
|
@@ -213,11 +213,8 @@ enum {
|
||
|
/* device driver is going to provide hardware time stamp */
|
||
|
SKBTX_IN_PROGRESS = 1 << 2,
|
||
|
|
||
|
- /* ensure the originating sk reference is available on driver level */
|
||
|
- SKBTX_DRV_NEEDS_SK_REF = 1 << 3,
|
||
|
-
|
||
|
/* device driver supports TX zero-copy buffers */
|
||
|
- SKBTX_DEV_ZEROCOPY = 1 << 4,
|
||
|
+ SKBTX_DEV_ZEROCOPY = 1 << 3,
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
diff --git a/include/linux/timex.h b/include/linux/timex.h
|
||
|
index aa60fe7..08e90fb 100644
|
||
|
--- a/include/linux/timex.h
|
||
|
+++ b/include/linux/timex.h
|
||
|
@@ -266,7 +266,7 @@ static inline int ntp_synced(void)
|
||
|
/* Returns how long ticks are at present, in ns / 2^NTP_SCALE_SHIFT. */
|
||
|
extern u64 tick_length;
|
||
|
|
||
|
-extern void second_overflow(void);
|
||
|
+extern int second_overflow(unsigned long secs);
|
||
|
extern void update_ntp_one_tick(void);
|
||
|
extern int do_adjtimex(struct timex *);
|
||
|
extern void hardpps(const struct timespec *, const struct timespec *);
|
||
|
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
|
||
|
index 6a308d4..1e100c6 100644
|
||
|
--- a/include/scsi/libsas.h
|
||
|
+++ b/include/scsi/libsas.h
|
||
|
@@ -159,6 +159,8 @@ enum ata_command_set {
|
||
|
ATAPI_COMMAND_SET = 1,
|
||
|
};
|
||
|
|
||
|
+#define ATA_RESP_FIS_SIZE 24
|
||
|
+
|
||
|
struct sata_device {
|
||
|
enum ata_command_set command_set;
|
||
|
struct smp_resp rps_resp; /* report_phy_sata_resp */
|
||
|
@@ -170,7 +172,7 @@ struct sata_device {
|
||
|
|
||
|
struct ata_port *ap;
|
||
|
struct ata_host ata_host;
|
||
|
- struct ata_taskfile tf;
|
||
|
+ u8 fis[ATA_RESP_FIS_SIZE];
|
||
|
u32 sstatus;
|
||
|
u32 serror;
|
||
|
u32 scontrol;
|
||
|
@@ -486,7 +488,7 @@ enum exec_status {
|
||
|
*/
|
||
|
struct ata_task_resp {
|
||
|
u16 frame_len;
|
||
|
- u8 ending_fis[24]; /* dev to host or data-in */
|
||
|
+ u8 ending_fis[ATA_RESP_FIS_SIZE]; /* dev to host or data-in */
|
||
|
u32 sstatus;
|
||
|
u32 serror;
|
||
|
u32 scontrol;
|
||
|
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
|
||
|
index ae34bf5..6db7a5e 100644
|
||
|
--- a/kernel/hrtimer.c
|
||
|
+++ b/kernel/hrtimer.c
|
||
|
@@ -657,6 +657,14 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base)
|
||
|
+{
|
||
|
+ ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset;
|
||
|
+ ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset;
|
||
|
+
|
||
|
+ return ktime_get_update_offsets(offs_real, offs_boot);
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* Retrigger next event is called after clock was set
|
||
|
*
|
||
|
@@ -665,22 +673,12 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
|
||
|
static void retrigger_next_event(void *arg)
|
||
|
{
|
||
|
struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases);
|
||
|
- struct timespec realtime_offset, xtim, wtm, sleep;
|
||
|
|
||
|
if (!hrtimer_hres_active())
|
||
|
return;
|
||
|
|
||
|
- /* Optimized out for !HIGH_RES */
|
||
|
- get_xtime_and_monotonic_and_sleep_offset(&xtim, &wtm, &sleep);
|
||
|
- set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec);
|
||
|
-
|
||
|
- /* Adjust CLOCK_REALTIME offset */
|
||
|
raw_spin_lock(&base->lock);
|
||
|
- base->clock_base[HRTIMER_BASE_REALTIME].offset =
|
||
|
- timespec_to_ktime(realtime_offset);
|
||
|
- base->clock_base[HRTIMER_BASE_BOOTTIME].offset =
|
||
|
- timespec_to_ktime(sleep);
|
||
|
-
|
||
|
+ hrtimer_update_base(base);
|
||
|
hrtimer_force_reprogram(base, 0);
|
||
|
raw_spin_unlock(&base->lock);
|
||
|
}
|
||
|
@@ -710,13 +708,25 @@ static int hrtimer_switch_to_hres(void)
|
||
|
base->clock_base[i].resolution = KTIME_HIGH_RES;
|
||
|
|
||
|
tick_setup_sched_timer();
|
||
|
-
|
||
|
/* "Retrigger" the interrupt to get things going */
|
||
|
retrigger_next_event(NULL);
|
||
|
local_irq_restore(flags);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * Called from timekeeping code to reprogramm the hrtimer interrupt
|
||
|
+ * device. If called from the timer interrupt context we defer it to
|
||
|
+ * softirq context.
|
||
|
+ */
|
||
|
+void clock_was_set_delayed(void)
|
||
|
+{
|
||
|
+ struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
|
||
|
+
|
||
|
+ cpu_base->clock_was_set = 1;
|
||
|
+ __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
|
||
|
+}
|
||
|
+
|
||
|
#else
|
||
|
|
||
|
static inline int hrtimer_hres_active(void) { return 0; }
|
||
|
@@ -1250,11 +1260,10 @@ void hrtimer_interrupt(struct clock_event_device *dev)
|
||
|
cpu_base->nr_events++;
|
||
|
dev->next_event.tv64 = KTIME_MAX;
|
||
|
|
||
|
- entry_time = now = ktime_get();
|
||
|
+ raw_spin_lock(&cpu_base->lock);
|
||
|
+ entry_time = now = hrtimer_update_base(cpu_base);
|
||
|
retry:
|
||
|
expires_next.tv64 = KTIME_MAX;
|
||
|
-
|
||
|
- raw_spin_lock(&cpu_base->lock);
|
||
|
/*
|
||
|
* We set expires_next to KTIME_MAX here with cpu_base->lock
|
||
|
* held to prevent that a timer is enqueued in our queue via
|
||
|
@@ -1330,8 +1339,12 @@ retry:
|
||
|
* We need to prevent that we loop forever in the hrtimer
|
||
|
* interrupt routine. We give it 3 attempts to avoid
|
||
|
* overreacting on some spurious event.
|
||
|
+ *
|
||
|
+ * Acquire base lock for updating the offsets and retrieving
|
||
|
+ * the current time.
|
||
|
*/
|
||
|
- now = ktime_get();
|
||
|
+ raw_spin_lock(&cpu_base->lock);
|
||
|
+ now = hrtimer_update_base(cpu_base);
|
||
|
cpu_base->nr_retries++;
|
||
|
if (++retries < 3)
|
||
|
goto retry;
|
||
|
@@ -1343,6 +1356,7 @@ retry:
|
||
|
*/
|
||
|
cpu_base->nr_hangs++;
|
||
|
cpu_base->hang_detected = 1;
|
||
|
+ raw_spin_unlock(&cpu_base->lock);
|
||
|
delta = ktime_sub(now, entry_time);
|
||
|
if (delta.tv64 > cpu_base->max_hang_time.tv64)
|
||
|
cpu_base->max_hang_time = delta;
|
||
|
@@ -1395,6 +1409,13 @@ void hrtimer_peek_ahead_timers(void)
|
||
|
|
||
|
static void run_hrtimer_softirq(struct softirq_action *h)
|
||
|
{
|
||
|
+ struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
|
||
|
+
|
||
|
+ if (cpu_base->clock_was_set) {
|
||
|
+ cpu_base->clock_was_set = 0;
|
||
|
+ clock_was_set();
|
||
|
+ }
|
||
|
+
|
||
|
hrtimer_peek_ahead_timers();
|
||
|
}
|
||
|
|
||
|
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
|
||
|
index b313086..64f8f97 100644
|
||
|
--- a/kernel/power/swap.c
|
||
|
+++ b/kernel/power/swap.c
|
||
|
@@ -6,7 +6,7 @@
|
||
|
*
|
||
|
* Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz>
|
||
|
* Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
|
||
|
- * Copyright (C) 2010 Bojan Smojver <bojan@rexursive.com>
|
||
|
+ * Copyright (C) 2010-2012 Bojan Smojver <bojan@rexursive.com>
|
||
|
*
|
||
|
* This file is released under the GPLv2.
|
||
|
*
|
||
|
@@ -283,14 +283,17 @@ static int write_page(void *buf, sector_t offset, struct bio **bio_chain)
|
||
|
return -ENOSPC;
|
||
|
|
||
|
if (bio_chain) {
|
||
|
- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
|
||
|
+ src = (void *)__get_free_page(__GFP_WAIT | __GFP_NOWARN |
|
||
|
+ __GFP_NORETRY);
|
||
|
if (src) {
|
||
|
copy_page(src, buf);
|
||
|
} else {
|
||
|
ret = hib_wait_on_bio_chain(bio_chain); /* Free pages */
|
||
|
if (ret)
|
||
|
return ret;
|
||
|
- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
|
||
|
+ src = (void *)__get_free_page(__GFP_WAIT |
|
||
|
+ __GFP_NOWARN |
|
||
|
+ __GFP_NORETRY);
|
||
|
if (src) {
|
||
|
copy_page(src, buf);
|
||
|
} else {
|
||
|
@@ -368,12 +371,17 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf,
|
||
|
clear_page(handle->cur);
|
||
|
handle->cur_swap = offset;
|
||
|
handle->k = 0;
|
||
|
- }
|
||
|
- if (bio_chain && low_free_pages() <= handle->reqd_free_pages) {
|
||
|
- error = hib_wait_on_bio_chain(bio_chain);
|
||
|
- if (error)
|
||
|
- goto out;
|
||
|
- handle->reqd_free_pages = reqd_free_pages();
|
||
|
+
|
||
|
+ if (bio_chain && low_free_pages() <= handle->reqd_free_pages) {
|
||
|
+ error = hib_wait_on_bio_chain(bio_chain);
|
||
|
+ if (error)
|
||
|
+ goto out;
|
||
|
+ /*
|
||
|
+ * Recalculate the number of required free pages, to
|
||
|
+ * make sure we never take more than half.
|
||
|
+ */
|
||
|
+ handle->reqd_free_pages = reqd_free_pages();
|
||
|
+ }
|
||
|
}
|
||
|
out:
|
||
|
return error;
|
||
|
@@ -420,8 +428,9 @@ static int swap_writer_finish(struct swap_map_handle *handle,
|
||
|
/* Maximum number of threads for compression/decompression. */
|
||
|
#define LZO_THREADS 3
|
||
|
|
||
|
-/* Maximum number of pages for read buffering. */
|
||
|
-#define LZO_READ_PAGES (MAP_PAGE_ENTRIES * 8)
|
||
|
+/* Minimum/maximum number of pages for read buffering. */
|
||
|
+#define LZO_MIN_RD_PAGES 1024
|
||
|
+#define LZO_MAX_RD_PAGES 8192
|
||
|
|
||
|
|
||
|
/**
|
||
|
@@ -632,12 +641,6 @@ static int save_image_lzo(struct swap_map_handle *handle,
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- * Adjust number of free pages after all allocations have been done.
|
||
|
- * We don't want to run out of pages when writing.
|
||
|
- */
|
||
|
- handle->reqd_free_pages = reqd_free_pages();
|
||
|
-
|
||
|
- /*
|
||
|
* Start the CRC32 thread.
|
||
|
*/
|
||
|
init_waitqueue_head(&crc->go);
|
||
|
@@ -658,6 +661,12 @@ static int save_image_lzo(struct swap_map_handle *handle,
|
||
|
goto out_clean;
|
||
|
}
|
||
|
|
||
|
+ /*
|
||
|
+ * Adjust the number of required free pages after all allocations have
|
||
|
+ * been done. We don't want to run out of pages when writing.
|
||
|
+ */
|
||
|
+ handle->reqd_free_pages = reqd_free_pages();
|
||
|
+
|
||
|
printk(KERN_INFO
|
||
|
"PM: Using %u thread(s) for compression.\n"
|
||
|
"PM: Compressing and saving image data (%u pages) ... ",
|
||
|
@@ -1067,7 +1076,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
|
||
|
unsigned i, thr, run_threads, nr_threads;
|
||
|
unsigned ring = 0, pg = 0, ring_size = 0,
|
||
|
have = 0, want, need, asked = 0;
|
||
|
- unsigned long read_pages;
|
||
|
+ unsigned long read_pages = 0;
|
||
|
unsigned char **page = NULL;
|
||
|
struct dec_data *data = NULL;
|
||
|
struct crc_data *crc = NULL;
|
||
|
@@ -1079,7 +1088,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
|
||
|
nr_threads = num_online_cpus() - 1;
|
||
|
nr_threads = clamp_val(nr_threads, 1, LZO_THREADS);
|
||
|
|
||
|
- page = vmalloc(sizeof(*page) * LZO_READ_PAGES);
|
||
|
+ page = vmalloc(sizeof(*page) * LZO_MAX_RD_PAGES);
|
||
|
if (!page) {
|
||
|
printk(KERN_ERR "PM: Failed to allocate LZO page\n");
|
||
|
ret = -ENOMEM;
|
||
|
@@ -1144,15 +1153,22 @@ static int load_image_lzo(struct swap_map_handle *handle,
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- * Adjust number of pages for read buffering, in case we are short.
|
||
|
+ * Set the number of pages for read buffering.
|
||
|
+ * This is complete guesswork, because we'll only know the real
|
||
|
+ * picture once prepare_image() is called, which is much later on
|
||
|
+ * during the image load phase. We'll assume the worst case and
|
||
|
+ * say that none of the image pages are from high memory.
|
||
|
*/
|
||
|
- read_pages = (nr_free_pages() - snapshot_get_image_size()) >> 1;
|
||
|
- read_pages = clamp_val(read_pages, LZO_CMP_PAGES, LZO_READ_PAGES);
|
||
|
+ if (low_free_pages() > snapshot_get_image_size())
|
||
|
+ read_pages = (low_free_pages() - snapshot_get_image_size()) / 2;
|
||
|
+ read_pages = clamp_val(read_pages, LZO_MIN_RD_PAGES, LZO_MAX_RD_PAGES);
|
||
|
|
||
|
for (i = 0; i < read_pages; i++) {
|
||
|
page[i] = (void *)__get_free_page(i < LZO_CMP_PAGES ?
|
||
|
__GFP_WAIT | __GFP_HIGH :
|
||
|
- __GFP_WAIT);
|
||
|
+ __GFP_WAIT | __GFP_NOWARN |
|
||
|
+ __GFP_NORETRY);
|
||
|
+
|
||
|
if (!page[i]) {
|
||
|
if (i < LZO_CMP_PAGES) {
|
||
|
ring_size = i;
|
||
|
diff --git a/kernel/sched.c b/kernel/sched.c
|
||
|
index 576a27f..52ac69b 100644
|
||
|
--- a/kernel/sched.c
|
||
|
+++ b/kernel/sched.c
|
||
|
@@ -1885,7 +1885,6 @@ static void double_rq_unlock(struct rq *rq1, struct rq *rq2)
|
||
|
|
||
|
#endif
|
||
|
|
||
|
-static void calc_load_account_idle(struct rq *this_rq);
|
||
|
static void update_sysctl(void);
|
||
|
static int get_update_sysctl_factor(void);
|
||
|
static void update_cpu_load(struct rq *this_rq);
|
||
|
@@ -3401,11 +3400,73 @@ unsigned long this_cpu_load(void)
|
||
|
}
|
||
|
|
||
|
|
||
|
+/*
|
||
|
+ * Global load-average calculations
|
||
|
+ *
|
||
|
+ * We take a distributed and async approach to calculating the global load-avg
|
||
|
+ * in order to minimize overhead.
|
||
|
+ *
|
||
|
+ * The global load average is an exponentially decaying average of nr_running +
|
||
|
+ * nr_uninterruptible.
|
||
|
+ *
|
||
|
+ * Once every LOAD_FREQ:
|
||
|
+ *
|
||
|
+ * nr_active = 0;
|
||
|
+ * for_each_possible_cpu(cpu)
|
||
|
+ * nr_active += cpu_of(cpu)->nr_running + cpu_of(cpu)->nr_uninterruptible;
|
||
|
+ *
|
||
|
+ * avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n)
|
||
|
+ *
|
||
|
+ * Due to a number of reasons the above turns in the mess below:
|
||
|
+ *
|
||
|
+ * - for_each_possible_cpu() is prohibitively expensive on machines with
|
||
|
+ * serious number of cpus, therefore we need to take a distributed approach
|
||
|
+ * to calculating nr_active.
|
||
|
+ *
|
||
|
+ * \Sum_i x_i(t) = \Sum_i x_i(t) - x_i(t_0) | x_i(t_0) := 0
|
||
|
+ * = \Sum_i { \Sum_j=1 x_i(t_j) - x_i(t_j-1) }
|
||
|
+ *
|
||
|
+ * So assuming nr_active := 0 when we start out -- true per definition, we
|
||
|
+ * can simply take per-cpu deltas and fold those into a global accumulate
|
||
|
+ * to obtain the same result. See calc_load_fold_active().
|
||
|
+ *
|
||
|
+ * Furthermore, in order to avoid synchronizing all per-cpu delta folding
|
||
|
+ * across the machine, we assume 10 ticks is sufficient time for every
|
||
|
+ * cpu to have completed this task.
|
||
|
+ *
|
||
|
+ * This places an upper-bound on the IRQ-off latency of the machine. Then
|
||
|
+ * again, being late doesn't loose the delta, just wrecks the sample.
|
||
|
+ *
|
||
|
+ * - cpu_rq()->nr_uninterruptible isn't accurately tracked per-cpu because
|
||
|
+ * this would add another cross-cpu cacheline miss and atomic operation
|
||
|
+ * to the wakeup path. Instead we increment on whatever cpu the task ran
|
||
|
+ * when it went into uninterruptible state and decrement on whatever cpu
|
||
|
+ * did the wakeup. This means that only the sum of nr_uninterruptible over
|
||
|
+ * all cpus yields the correct result.
|
||
|
+ *
|
||
|
+ * This covers the NO_HZ=n code, for extra head-aches, see the comment below.
|
||
|
+ */
|
||
|
+
|
||
|
/* Variables and functions for calc_load */
|
||
|
static atomic_long_t calc_load_tasks;
|
||
|
static unsigned long calc_load_update;
|
||
|
unsigned long avenrun[3];
|
||
|
-EXPORT_SYMBOL(avenrun);
|
||
|
+EXPORT_SYMBOL(avenrun); /* should be removed */
|
||
|
+
|
||
|
+/**
|
||
|
+ * get_avenrun - get the load average array
|
||
|
+ * @loads: pointer to dest load array
|
||
|
+ * @offset: offset to add
|
||
|
+ * @shift: shift count to shift the result left
|
||
|
+ *
|
||
|
+ * These values are estimates at best, so no need for locking.
|
||
|
+ */
|
||
|
+void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
|
||
|
+{
|
||
|
+ loads[0] = (avenrun[0] + offset) << shift;
|
||
|
+ loads[1] = (avenrun[1] + offset) << shift;
|
||
|
+ loads[2] = (avenrun[2] + offset) << shift;
|
||
|
+}
|
||
|
|
||
|
static long calc_load_fold_active(struct rq *this_rq)
|
||
|
{
|
||
|
@@ -3422,6 +3483,9 @@ static long calc_load_fold_active(struct rq *this_rq)
|
||
|
return delta;
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * a1 = a0 * e + a * (1 - e)
|
||
|
+ */
|
||
|
static unsigned long
|
||
|
calc_load(unsigned long load, unsigned long exp, unsigned long active)
|
||
|
{
|
||
|
@@ -3433,30 +3497,118 @@ calc_load(unsigned long load, unsigned long exp, unsigned long active)
|
||
|
|
||
|
#ifdef CONFIG_NO_HZ
|
||
|
/*
|
||
|
- * For NO_HZ we delay the active fold to the next LOAD_FREQ update.
|
||
|
+ * Handle NO_HZ for the global load-average.
|
||
|
+ *
|
||
|
+ * Since the above described distributed algorithm to compute the global
|
||
|
+ * load-average relies on per-cpu sampling from the tick, it is affected by
|
||
|
+ * NO_HZ.
|
||
|
+ *
|
||
|
+ * The basic idea is to fold the nr_active delta into a global idle-delta upon
|
||
|
+ * entering NO_HZ state such that we can include this as an 'extra' cpu delta
|
||
|
+ * when we read the global state.
|
||
|
+ *
|
||
|
+ * Obviously reality has to ruin such a delightfully simple scheme:
|
||
|
+ *
|
||
|
+ * - When we go NO_HZ idle during the window, we can negate our sample
|
||
|
+ * contribution, causing under-accounting.
|
||
|
+ *
|
||
|
+ * We avoid this by keeping two idle-delta counters and flipping them
|
||
|
+ * when the window starts, thus separating old and new NO_HZ load.
|
||
|
+ *
|
||
|
+ * The only trick is the slight shift in index flip for read vs write.
|
||
|
+ *
|
||
|
+ * 0s 5s 10s 15s
|
||
|
+ * +10 +10 +10 +10
|
||
|
+ * |-|-----------|-|-----------|-|-----------|-|
|
||
|
+ * r:0 0 1 1 0 0 1 1 0
|
||
|
+ * w:0 1 1 0 0 1 1 0 0
|
||
|
+ *
|
||
|
+ * This ensures we'll fold the old idle contribution in this window while
|
||
|
+ * accumlating the new one.
|
||
|
+ *
|
||
|
+ * - When we wake up from NO_HZ idle during the window, we push up our
|
||
|
+ * contribution, since we effectively move our sample point to a known
|
||
|
+ * busy state.
|
||
|
+ *
|
||
|
+ * This is solved by pushing the window forward, and thus skipping the
|
||
|
+ * sample, for this cpu (effectively using the idle-delta for this cpu which
|
||
|
+ * was in effect at the time the window opened). This also solves the issue
|
||
|
+ * of having to deal with a cpu having been in NOHZ idle for multiple
|
||
|
+ * LOAD_FREQ intervals.
|
||
|
*
|
||
|
* When making the ILB scale, we should try to pull this in as well.
|
||
|
*/
|
||
|
-static atomic_long_t calc_load_tasks_idle;
|
||
|
+static atomic_long_t calc_load_idle[2];
|
||
|
+static int calc_load_idx;
|
||
|
|
||
|
-static void calc_load_account_idle(struct rq *this_rq)
|
||
|
+static inline int calc_load_write_idx(void)
|
||
|
{
|
||
|
+ int idx = calc_load_idx;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * See calc_global_nohz(), if we observe the new index, we also
|
||
|
+ * need to observe the new update time.
|
||
|
+ */
|
||
|
+ smp_rmb();
|
||
|
+
|
||
|
+ /*
|
||
|
+ * If the folding window started, make sure we start writing in the
|
||
|
+ * next idle-delta.
|
||
|
+ */
|
||
|
+ if (!time_before(jiffies, calc_load_update))
|
||
|
+ idx++;
|
||
|
+
|
||
|
+ return idx & 1;
|
||
|
+}
|
||
|
+
|
||
|
+static inline int calc_load_read_idx(void)
|
||
|
+{
|
||
|
+ return calc_load_idx & 1;
|
||
|
+}
|
||
|
+
|
||
|
+void calc_load_enter_idle(void)
|
||
|
+{
|
||
|
+ struct rq *this_rq = this_rq();
|
||
|
long delta;
|
||
|
|
||
|
+ /*
|
||
|
+ * We're going into NOHZ mode, if there's any pending delta, fold it
|
||
|
+ * into the pending idle delta.
|
||
|
+ */
|
||
|
delta = calc_load_fold_active(this_rq);
|
||
|
- if (delta)
|
||
|
- atomic_long_add(delta, &calc_load_tasks_idle);
|
||
|
+ if (delta) {
|
||
|
+ int idx = calc_load_write_idx();
|
||
|
+ atomic_long_add(delta, &calc_load_idle[idx]);
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
-static long calc_load_fold_idle(void)
|
||
|
+void calc_load_exit_idle(void)
|
||
|
{
|
||
|
- long delta = 0;
|
||
|
+ struct rq *this_rq = this_rq();
|
||
|
+
|
||
|
+ /*
|
||
|
+ * If we're still before the sample window, we're done.
|
||
|
+ */
|
||
|
+ if (time_before(jiffies, this_rq->calc_load_update))
|
||
|
+ return;
|
||
|
|
||
|
/*
|
||
|
- * Its got a race, we don't care...
|
||
|
+ * We woke inside or after the sample window, this means we're already
|
||
|
+ * accounted through the nohz accounting, so skip the entire deal and
|
||
|
+ * sync up for the next window.
|
||
|
*/
|
||
|
- if (atomic_long_read(&calc_load_tasks_idle))
|
||
|
- delta = atomic_long_xchg(&calc_load_tasks_idle, 0);
|
||
|
+ this_rq->calc_load_update = calc_load_update;
|
||
|
+ if (time_before(jiffies, this_rq->calc_load_update + 10))
|
||
|
+ this_rq->calc_load_update += LOAD_FREQ;
|
||
|
+}
|
||
|
+
|
||
|
+static long calc_load_fold_idle(void)
|
||
|
+{
|
||
|
+ int idx = calc_load_read_idx();
|
||
|
+ long delta = 0;
|
||
|
+
|
||
|
+ if (atomic_long_read(&calc_load_idle[idx]))
|
||
|
+ delta = atomic_long_xchg(&calc_load_idle[idx], 0);
|
||
|
|
||
|
return delta;
|
||
|
}
|
||
|
@@ -3542,66 +3694,39 @@ static void calc_global_nohz(void)
|
||
|
{
|
||
|
long delta, active, n;
|
||
|
|
||
|
- /*
|
||
|
- * If we crossed a calc_load_update boundary, make sure to fold
|
||
|
- * any pending idle changes, the respective CPUs might have
|
||
|
- * missed the tick driven calc_load_account_active() update
|
||
|
- * due to NO_HZ.
|
||
|
- */
|
||
|
- delta = calc_load_fold_idle();
|
||
|
- if (delta)
|
||
|
- atomic_long_add(delta, &calc_load_tasks);
|
||
|
-
|
||
|
- /*
|
||
|
- * It could be the one fold was all it took, we done!
|
||
|
- */
|
||
|
- if (time_before(jiffies, calc_load_update + 10))
|
||
|
- return;
|
||
|
-
|
||
|
- /*
|
||
|
- * Catch-up, fold however many we are behind still
|
||
|
- */
|
||
|
- delta = jiffies - calc_load_update - 10;
|
||
|
- n = 1 + (delta / LOAD_FREQ);
|
||
|
+ if (!time_before(jiffies, calc_load_update + 10)) {
|
||
|
+ /*
|
||
|
+ * Catch-up, fold however many we are behind still
|
||
|
+ */
|
||
|
+ delta = jiffies - calc_load_update - 10;
|
||
|
+ n = 1 + (delta / LOAD_FREQ);
|
||
|
|
||
|
- active = atomic_long_read(&calc_load_tasks);
|
||
|
- active = active > 0 ? active * FIXED_1 : 0;
|
||
|
+ active = atomic_long_read(&calc_load_tasks);
|
||
|
+ active = active > 0 ? active * FIXED_1 : 0;
|
||
|
|
||
|
- avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n);
|
||
|
- avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n);
|
||
|
- avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n);
|
||
|
+ avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n);
|
||
|
+ avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n);
|
||
|
+ avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n);
|
||
|
|
||
|
- calc_load_update += n * LOAD_FREQ;
|
||
|
-}
|
||
|
-#else
|
||
|
-static void calc_load_account_idle(struct rq *this_rq)
|
||
|
-{
|
||
|
-}
|
||
|
+ calc_load_update += n * LOAD_FREQ;
|
||
|
+ }
|
||
|
|
||
|
-static inline long calc_load_fold_idle(void)
|
||
|
-{
|
||
|
- return 0;
|
||
|
+ /*
|
||
|
+ * Flip the idle index...
|
||
|
+ *
|
||
|
+ * Make sure we first write the new time then flip the index, so that
|
||
|
+ * calc_load_write_idx() will see the new time when it reads the new
|
||
|
+ * index, this avoids a double flip messing things up.
|
||
|
+ */
|
||
|
+ smp_wmb();
|
||
|
+ calc_load_idx++;
|
||
|
}
|
||
|
+#else /* !CONFIG_NO_HZ */
|
||
|
|
||
|
-static void calc_global_nohz(void)
|
||
|
-{
|
||
|
-}
|
||
|
-#endif
|
||
|
+static inline long calc_load_fold_idle(void) { return 0; }
|
||
|
+static inline void calc_global_nohz(void) { }
|
||
|
|
||
|
-/**
|
||
|
- * get_avenrun - get the load average array
|
||
|
- * @loads: pointer to dest load array
|
||
|
- * @offset: offset to add
|
||
|
- * @shift: shift count to shift the result left
|
||
|
- *
|
||
|
- * These values are estimates at best, so no need for locking.
|
||
|
- */
|
||
|
-void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
|
||
|
-{
|
||
|
- loads[0] = (avenrun[0] + offset) << shift;
|
||
|
- loads[1] = (avenrun[1] + offset) << shift;
|
||
|
- loads[2] = (avenrun[2] + offset) << shift;
|
||
|
-}
|
||
|
+#endif /* CONFIG_NO_HZ */
|
||
|
|
||
|
/*
|
||
|
* calc_load - update the avenrun load estimates 10 ticks after the
|
||
|
@@ -3609,11 +3734,18 @@ void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
|
||
|
*/
|
||
|
void calc_global_load(unsigned long ticks)
|
||
|
{
|
||
|
- long active;
|
||
|
+ long active, delta;
|
||
|
|
||
|
if (time_before(jiffies, calc_load_update + 10))
|
||
|
return;
|
||
|
|
||
|
+ /*
|
||
|
+ * Fold the 'old' idle-delta to include all NO_HZ cpus.
|
||
|
+ */
|
||
|
+ delta = calc_load_fold_idle();
|
||
|
+ if (delta)
|
||
|
+ atomic_long_add(delta, &calc_load_tasks);
|
||
|
+
|
||
|
active = atomic_long_read(&calc_load_tasks);
|
||
|
active = active > 0 ? active * FIXED_1 : 0;
|
||
|
|
||
|
@@ -3624,12 +3756,7 @@ void calc_global_load(unsigned long ticks)
|
||
|
calc_load_update += LOAD_FREQ;
|
||
|
|
||
|
/*
|
||
|
- * Account one period with whatever state we found before
|
||
|
- * folding in the nohz state and ageing the entire idle period.
|
||
|
- *
|
||
|
- * This avoids loosing a sample when we go idle between
|
||
|
- * calc_load_account_active() (10 ticks ago) and now and thus
|
||
|
- * under-accounting.
|
||
|
+ * In case we idled for multiple LOAD_FREQ intervals, catch up in bulk.
|
||
|
*/
|
||
|
calc_global_nohz();
|
||
|
}
|
||
|
@@ -3646,7 +3773,6 @@ static void calc_load_account_active(struct rq *this_rq)
|
||
|
return;
|
||
|
|
||
|
delta = calc_load_fold_active(this_rq);
|
||
|
- delta += calc_load_fold_idle();
|
||
|
if (delta)
|
||
|
atomic_long_add(delta, &calc_load_tasks);
|
||
|
|
||
|
@@ -3654,6 +3780,10 @@ static void calc_load_account_active(struct rq *this_rq)
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
+ * End of global load-average stuff
|
||
|
+ */
|
||
|
+
|
||
|
+/*
|
||
|
* The exact cpuload at various idx values, calculated at every tick would be
|
||
|
* load = (2^idx - 1) / 2^idx * load + 1 / 2^idx * cur_load
|
||
|
*
|
||
|
diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c
|
||
|
index 0a51882..be92bfe 100644
|
||
|
--- a/kernel/sched_idletask.c
|
||
|
+++ b/kernel/sched_idletask.c
|
||
|
@@ -23,7 +23,6 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl
|
||
|
static struct task_struct *pick_next_task_idle(struct rq *rq)
|
||
|
{
|
||
|
schedstat_inc(rq, sched_goidle);
|
||
|
- calc_load_account_idle(rq);
|
||
|
return rq->idle;
|
||
|
}
|
||
|
|
||
|
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
|
||
|
index 4b85a7a..f1eb182 100644
|
||
|
--- a/kernel/time/ntp.c
|
||
|
+++ b/kernel/time/ntp.c
|
||
|
@@ -31,8 +31,6 @@ unsigned long tick_nsec;
|
||
|
u64 tick_length;
|
||
|
static u64 tick_length_base;
|
||
|
|
||
|
-static struct hrtimer leap_timer;
|
||
|
-
|
||
|
#define MAX_TICKADJ 500LL /* usecs */
|
||
|
#define MAX_TICKADJ_SCALED \
|
||
|
(((MAX_TICKADJ * NSEC_PER_USEC) << NTP_SCALE_SHIFT) / NTP_INTERVAL_FREQ)
|
||
|
@@ -350,60 +348,60 @@ void ntp_clear(void)
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- * Leap second processing. If in leap-insert state at the end of the
|
||
|
- * day, the system clock is set back one second; if in leap-delete
|
||
|
- * state, the system clock is set ahead one second.
|
||
|
+ * this routine handles the overflow of the microsecond field
|
||
|
+ *
|
||
|
+ * The tricky bits of code to handle the accurate clock support
|
||
|
+ * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
|
||
|
+ * They were originally developed for SUN and DEC kernels.
|
||
|
+ * All the kudos should go to Dave for this stuff.
|
||
|
+ *
|
||
|
+ * Also handles leap second processing, and returns leap offset
|
||
|
*/
|
||
|
-static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer)
|
||
|
+int second_overflow(unsigned long secs)
|
||
|
{
|
||
|
- enum hrtimer_restart res = HRTIMER_NORESTART;
|
||
|
-
|
||
|
- write_seqlock(&xtime_lock);
|
||
|
+ int leap = 0;
|
||
|
+ s64 delta;
|
||
|
|
||
|
+ /*
|
||
|
+ * Leap second processing. If in leap-insert state at the end of the
|
||
|
+ * day, the system clock is set back one second; if in leap-delete
|
||
|
+ * state, the system clock is set ahead one second.
|
||
|
+ */
|
||
|
switch (time_state) {
|
||
|
case TIME_OK:
|
||
|
+ if (time_status & STA_INS)
|
||
|
+ time_state = TIME_INS;
|
||
|
+ else if (time_status & STA_DEL)
|
||
|
+ time_state = TIME_DEL;
|
||
|
break;
|
||
|
case TIME_INS:
|
||
|
- timekeeping_leap_insert(-1);
|
||
|
- time_state = TIME_OOP;
|
||
|
- printk(KERN_NOTICE
|
||
|
- "Clock: inserting leap second 23:59:60 UTC\n");
|
||
|
- hrtimer_add_expires_ns(&leap_timer, NSEC_PER_SEC);
|
||
|
- res = HRTIMER_RESTART;
|
||
|
+ if (secs % 86400 == 0) {
|
||
|
+ leap = -1;
|
||
|
+ time_state = TIME_OOP;
|
||
|
+ time_tai++;
|
||
|
+ printk(KERN_NOTICE
|
||
|
+ "Clock: inserting leap second 23:59:60 UTC\n");
|
||
|
+ }
|
||
|
break;
|
||
|
case TIME_DEL:
|
||
|
- timekeeping_leap_insert(1);
|
||
|
- time_tai--;
|
||
|
- time_state = TIME_WAIT;
|
||
|
- printk(KERN_NOTICE
|
||
|
- "Clock: deleting leap second 23:59:59 UTC\n");
|
||
|
+ if ((secs + 1) % 86400 == 0) {
|
||
|
+ leap = 1;
|
||
|
+ time_tai--;
|
||
|
+ time_state = TIME_WAIT;
|
||
|
+ printk(KERN_NOTICE
|
||
|
+ "Clock: deleting leap second 23:59:59 UTC\n");
|
||
|
+ }
|
||
|
break;
|
||
|
case TIME_OOP:
|
||
|
- time_tai++;
|
||
|
time_state = TIME_WAIT;
|
||
|
- /* fall through */
|
||
|
+ break;
|
||
|
+
|
||
|
case TIME_WAIT:
|
||
|
if (!(time_status & (STA_INS | STA_DEL)))
|
||
|
time_state = TIME_OK;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
- write_sequnlock(&xtime_lock);
|
||
|
-
|
||
|
- return res;
|
||
|
-}
|
||
|
-
|
||
|
-/*
|
||
|
- * this routine handles the overflow of the microsecond field
|
||
|
- *
|
||
|
- * The tricky bits of code to handle the accurate clock support
|
||
|
- * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
|
||
|
- * They were originally developed for SUN and DEC kernels.
|
||
|
- * All the kudos should go to Dave for this stuff.
|
||
|
- */
|
||
|
-void second_overflow(void)
|
||
|
-{
|
||
|
- s64 delta;
|
||
|
|
||
|
/* Bump the maxerror field */
|
||
|
time_maxerror += MAXFREQ / NSEC_PER_USEC;
|
||
|
@@ -423,23 +421,25 @@ void second_overflow(void)
|
||
|
pps_dec_valid();
|
||
|
|
||
|
if (!time_adjust)
|
||
|
- return;
|
||
|
+ goto out;
|
||
|
|
||
|
if (time_adjust > MAX_TICKADJ) {
|
||
|
time_adjust -= MAX_TICKADJ;
|
||
|
tick_length += MAX_TICKADJ_SCALED;
|
||
|
- return;
|
||
|
+ goto out;
|
||
|
}
|
||
|
|
||
|
if (time_adjust < -MAX_TICKADJ) {
|
||
|
time_adjust += MAX_TICKADJ;
|
||
|
tick_length -= MAX_TICKADJ_SCALED;
|
||
|
- return;
|
||
|
+ goto out;
|
||
|
}
|
||
|
|
||
|
tick_length += (s64)(time_adjust * NSEC_PER_USEC / NTP_INTERVAL_FREQ)
|
||
|
<< NTP_SCALE_SHIFT;
|
||
|
time_adjust = 0;
|
||
|
+out:
|
||
|
+ return leap;
|
||
|
}
|
||
|
|
||
|
#ifdef CONFIG_GENERIC_CMOS_UPDATE
|
||
|
@@ -501,27 +501,6 @@ static void notify_cmos_timer(void)
|
||
|
static inline void notify_cmos_timer(void) { }
|
||
|
#endif
|
||
|
|
||
|
-/*
|
||
|
- * Start the leap seconds timer:
|
||
|
- */
|
||
|
-static inline void ntp_start_leap_timer(struct timespec *ts)
|
||
|
-{
|
||
|
- long now = ts->tv_sec;
|
||
|
-
|
||
|
- if (time_status & STA_INS) {
|
||
|
- time_state = TIME_INS;
|
||
|
- now += 86400 - now % 86400;
|
||
|
- hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS);
|
||
|
-
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- if (time_status & STA_DEL) {
|
||
|
- time_state = TIME_DEL;
|
||
|
- now += 86400 - (now + 1) % 86400;
|
||
|
- hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS);
|
||
|
- }
|
||
|
-}
|
||
|
|
||
|
/*
|
||
|
* Propagate a new txc->status value into the NTP state:
|
||
|
@@ -546,22 +525,6 @@ static inline void process_adj_status(struct timex *txc, struct timespec *ts)
|
||
|
time_status &= STA_RONLY;
|
||
|
time_status |= txc->status & ~STA_RONLY;
|
||
|
|
||
|
- switch (time_state) {
|
||
|
- case TIME_OK:
|
||
|
- ntp_start_leap_timer(ts);
|
||
|
- break;
|
||
|
- case TIME_INS:
|
||
|
- case TIME_DEL:
|
||
|
- time_state = TIME_OK;
|
||
|
- ntp_start_leap_timer(ts);
|
||
|
- case TIME_WAIT:
|
||
|
- if (!(time_status & (STA_INS | STA_DEL)))
|
||
|
- time_state = TIME_OK;
|
||
|
- break;
|
||
|
- case TIME_OOP:
|
||
|
- hrtimer_restart(&leap_timer);
|
||
|
- break;
|
||
|
- }
|
||
|
}
|
||
|
/*
|
||
|
* Called with the xtime lock held, so we can access and modify
|
||
|
@@ -643,9 +606,6 @@ int do_adjtimex(struct timex *txc)
|
||
|
(txc->tick < 900000/USER_HZ ||
|
||
|
txc->tick > 1100000/USER_HZ))
|
||
|
return -EINVAL;
|
||
|
-
|
||
|
- if (txc->modes & ADJ_STATUS && time_state != TIME_OK)
|
||
|
- hrtimer_cancel(&leap_timer);
|
||
|
}
|
||
|
|
||
|
if (txc->modes & ADJ_SETOFFSET) {
|
||
|
@@ -967,6 +927,4 @@ __setup("ntp_tick_adj=", ntp_tick_adj_setup);
|
||
|
void __init ntp_init(void)
|
||
|
{
|
||
|
ntp_clear();
|
||
|
- hrtimer_init(&leap_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
|
||
|
- leap_timer.function = ntp_leap_second;
|
||
|
}
|
||
|
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
|
||
|
index c923640..9955ebd 100644
|
||
|
--- a/kernel/time/tick-sched.c
|
||
|
+++ b/kernel/time/tick-sched.c
|
||
|
@@ -430,6 +430,7 @@ void tick_nohz_stop_sched_tick(int inidle)
|
||
|
*/
|
||
|
if (!ts->tick_stopped) {
|
||
|
select_nohz_load_balancer(1);
|
||
|
+ calc_load_enter_idle();
|
||
|
|
||
|
ts->idle_tick = hrtimer_get_expires(&ts->sched_timer);
|
||
|
ts->tick_stopped = 1;
|
||
|
@@ -563,6 +564,7 @@ void tick_nohz_restart_sched_tick(void)
|
||
|
account_idle_ticks(ticks);
|
||
|
#endif
|
||
|
|
||
|
+ calc_load_exit_idle();
|
||
|
touch_softlockup_watchdog();
|
||
|
/*
|
||
|
* Cancel the scheduled timer and restore the tick
|
||
|
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
|
||
|
index 2378413..03e67d4 100644
|
||
|
--- a/kernel/time/timekeeping.c
|
||
|
+++ b/kernel/time/timekeeping.c
|
||
|
@@ -161,23 +161,43 @@ static struct timespec xtime __attribute__ ((aligned (16)));
|
||
|
static struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
|
||
|
static struct timespec total_sleep_time;
|
||
|
|
||
|
+/* Offset clock monotonic -> clock realtime */
|
||
|
+static ktime_t offs_real;
|
||
|
+
|
||
|
+/* Offset clock monotonic -> clock boottime */
|
||
|
+static ktime_t offs_boot;
|
||
|
+
|
||
|
/*
|
||
|
* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock.
|
||
|
*/
|
||
|
static struct timespec raw_time;
|
||
|
|
||
|
-/* flag for if timekeeping is suspended */
|
||
|
-int __read_mostly timekeeping_suspended;
|
||
|
+/* must hold write on xtime_lock */
|
||
|
+static void update_rt_offset(void)
|
||
|
+{
|
||
|
+ struct timespec tmp, *wtm = &wall_to_monotonic;
|
||
|
|
||
|
-/* must hold xtime_lock */
|
||
|
-void timekeeping_leap_insert(int leapsecond)
|
||
|
+ set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec);
|
||
|
+ offs_real = timespec_to_ktime(tmp);
|
||
|
+}
|
||
|
+
|
||
|
+/* must hold write on xtime_lock */
|
||
|
+static void timekeeping_update(bool clearntp)
|
||
|
{
|
||
|
- xtime.tv_sec += leapsecond;
|
||
|
- wall_to_monotonic.tv_sec -= leapsecond;
|
||
|
- update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
|
||
|
- timekeeper.mult);
|
||
|
+ if (clearntp) {
|
||
|
+ timekeeper.ntp_error = 0;
|
||
|
+ ntp_clear();
|
||
|
+ }
|
||
|
+ update_rt_offset();
|
||
|
+ update_vsyscall(&xtime, &wall_to_monotonic,
|
||
|
+ timekeeper.clock, timekeeper.mult);
|
||
|
}
|
||
|
|
||
|
+
|
||
|
+
|
||
|
+/* flag for if timekeeping is suspended */
|
||
|
+int __read_mostly timekeeping_suspended;
|
||
|
+
|
||
|
/**
|
||
|
* timekeeping_forward_now - update clock to the current time
|
||
|
*
|
||
|
@@ -375,11 +395,7 @@ int do_settimeofday(const struct timespec *tv)
|
||
|
|
||
|
xtime = *tv;
|
||
|
|
||
|
- timekeeper.ntp_error = 0;
|
||
|
- ntp_clear();
|
||
|
-
|
||
|
- update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
|
||
|
- timekeeper.mult);
|
||
|
+ timekeeping_update(true);
|
||
|
|
||
|
write_sequnlock_irqrestore(&xtime_lock, flags);
|
||
|
|
||
|
@@ -412,11 +428,7 @@ int timekeeping_inject_offset(struct timespec *ts)
|
||
|
xtime = timespec_add(xtime, *ts);
|
||
|
wall_to_monotonic = timespec_sub(wall_to_monotonic, *ts);
|
||
|
|
||
|
- timekeeper.ntp_error = 0;
|
||
|
- ntp_clear();
|
||
|
-
|
||
|
- update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
|
||
|
- timekeeper.mult);
|
||
|
+ timekeeping_update(true);
|
||
|
|
||
|
write_sequnlock_irqrestore(&xtime_lock, flags);
|
||
|
|
||
|
@@ -591,6 +603,7 @@ void __init timekeeping_init(void)
|
||
|
}
|
||
|
set_normalized_timespec(&wall_to_monotonic,
|
||
|
-boot.tv_sec, -boot.tv_nsec);
|
||
|
+ update_rt_offset();
|
||
|
total_sleep_time.tv_sec = 0;
|
||
|
total_sleep_time.tv_nsec = 0;
|
||
|
write_sequnlock_irqrestore(&xtime_lock, flags);
|
||
|
@@ -599,6 +612,12 @@ void __init timekeeping_init(void)
|
||
|
/* time in seconds when suspend began */
|
||
|
static struct timespec timekeeping_suspend_time;
|
||
|
|
||
|
+static void update_sleep_time(struct timespec t)
|
||
|
+{
|
||
|
+ total_sleep_time = t;
|
||
|
+ offs_boot = timespec_to_ktime(t);
|
||
|
+}
|
||
|
+
|
||
|
/**
|
||
|
* __timekeeping_inject_sleeptime - Internal function to add sleep interval
|
||
|
* @delta: pointer to a timespec delta value
|
||
|
@@ -616,7 +635,7 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta)
|
||
|
|
||
|
xtime = timespec_add(xtime, *delta);
|
||
|
wall_to_monotonic = timespec_sub(wall_to_monotonic, *delta);
|
||
|
- total_sleep_time = timespec_add(total_sleep_time, *delta);
|
||
|
+ update_sleep_time(timespec_add(total_sleep_time, *delta));
|
||
|
}
|
||
|
|
||
|
|
||
|
@@ -645,10 +664,7 @@ void timekeeping_inject_sleeptime(struct timespec *delta)
|
||
|
|
||
|
__timekeeping_inject_sleeptime(delta);
|
||
|
|
||
|
- timekeeper.ntp_error = 0;
|
||
|
- ntp_clear();
|
||
|
- update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
|
||
|
- timekeeper.mult);
|
||
|
+ timekeeping_update(true);
|
||
|
|
||
|
write_sequnlock_irqrestore(&xtime_lock, flags);
|
||
|
|
||
|
@@ -683,6 +699,7 @@ static void timekeeping_resume(void)
|
||
|
timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock);
|
||
|
timekeeper.ntp_error = 0;
|
||
|
timekeeping_suspended = 0;
|
||
|
+ timekeeping_update(false);
|
||
|
write_sequnlock_irqrestore(&xtime_lock, flags);
|
||
|
|
||
|
touch_softlockup_watchdog();
|
||
|
@@ -942,9 +959,14 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
|
||
|
|
||
|
timekeeper.xtime_nsec += timekeeper.xtime_interval << shift;
|
||
|
while (timekeeper.xtime_nsec >= nsecps) {
|
||
|
+ int leap;
|
||
|
timekeeper.xtime_nsec -= nsecps;
|
||
|
xtime.tv_sec++;
|
||
|
- second_overflow();
|
||
|
+ leap = second_overflow(xtime.tv_sec);
|
||
|
+ xtime.tv_sec += leap;
|
||
|
+ wall_to_monotonic.tv_sec -= leap;
|
||
|
+ if (leap)
|
||
|
+ clock_was_set_delayed();
|
||
|
}
|
||
|
|
||
|
/* Accumulate raw time */
|
||
|
@@ -1050,14 +1072,17 @@ static void update_wall_time(void)
|
||
|
* xtime.tv_nsec isn't larger then NSEC_PER_SEC
|
||
|
*/
|
||
|
if (unlikely(xtime.tv_nsec >= NSEC_PER_SEC)) {
|
||
|
+ int leap;
|
||
|
xtime.tv_nsec -= NSEC_PER_SEC;
|
||
|
xtime.tv_sec++;
|
||
|
- second_overflow();
|
||
|
+ leap = second_overflow(xtime.tv_sec);
|
||
|
+ xtime.tv_sec += leap;
|
||
|
+ wall_to_monotonic.tv_sec -= leap;
|
||
|
+ if (leap)
|
||
|
+ clock_was_set_delayed();
|
||
|
}
|
||
|
|
||
|
- /* check to see if there is a new clocksource to use */
|
||
|
- update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
|
||
|
- timekeeper.mult);
|
||
|
+ timekeeping_update(false);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
@@ -1216,6 +1241,40 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,
|
||
|
} while (read_seqretry(&xtime_lock, seq));
|
||
|
}
|
||
|
|
||
|
+#ifdef CONFIG_HIGH_RES_TIMERS
|
||
|
+/**
|
||
|
+ * ktime_get_update_offsets - hrtimer helper
|
||
|
+ * @real: pointer to storage for monotonic -> realtime offset
|
||
|
+ * @_boot: pointer to storage for monotonic -> boottime offset
|
||
|
+ *
|
||
|
+ * Returns current monotonic time and updates the offsets
|
||
|
+ * Called from hrtimer_interupt() or retrigger_next_event()
|
||
|
+ */
|
||
|
+ktime_t ktime_get_update_offsets(ktime_t *real, ktime_t *boot)
|
||
|
+{
|
||
|
+ ktime_t now;
|
||
|
+ unsigned int seq;
|
||
|
+ u64 secs, nsecs;
|
||
|
+
|
||
|
+ do {
|
||
|
+ seq = read_seqbegin(&xtime_lock);
|
||
|
+
|
||
|
+ secs = xtime.tv_sec;
|
||
|
+ nsecs = xtime.tv_nsec;
|
||
|
+ nsecs += timekeeping_get_ns();
|
||
|
+ /* If arch requires, add in gettimeoffset() */
|
||
|
+ nsecs += arch_gettimeoffset();
|
||
|
+
|
||
|
+ *real = offs_real;
|
||
|
+ *boot = offs_boot;
|
||
|
+ } while (read_seqretry(&xtime_lock, seq));
|
||
|
+
|
||
|
+ now = ktime_add_ns(ktime_set(secs, 0), nsecs);
|
||
|
+ now = ktime_sub(now, *real);
|
||
|
+ return now;
|
||
|
+}
|
||
|
+#endif
|
||
|
+
|
||
|
/**
|
||
|
* ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format
|
||
|
*/
|
||
|
diff --git a/mm/compaction.c b/mm/compaction.c
|
||
|
index 8fb8a40..50f1c60 100644
|
||
|
--- a/mm/compaction.c
|
||
|
+++ b/mm/compaction.c
|
||
|
@@ -592,8 +592,11 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
|
||
|
if (err) {
|
||
|
putback_lru_pages(&cc->migratepages);
|
||
|
cc->nr_migratepages = 0;
|
||
|
+ if (err == -ENOMEM) {
|
||
|
+ ret = COMPACT_PARTIAL;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
}
|
||
|
-
|
||
|
}
|
||
|
|
||
|
out:
|
||
|
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
|
||
|
index 5f5c545..7c535b0 100644
|
||
|
--- a/mm/hugetlb.c
|
||
|
+++ b/mm/hugetlb.c
|
||
|
@@ -53,6 +53,84 @@ static unsigned long __initdata default_hstate_size;
|
||
|
*/
|
||
|
static DEFINE_SPINLOCK(hugetlb_lock);
|
||
|
|
||
|
+static inline void unlock_or_release_subpool(struct hugepage_subpool *spool)
|
||
|
+{
|
||
|
+ bool free = (spool->count == 0) && (spool->used_hpages == 0);
|
||
|
+
|
||
|
+ spin_unlock(&spool->lock);
|
||
|
+
|
||
|
+ /* If no pages are used, and no other handles to the subpool
|
||
|
+ * remain, free the subpool the subpool remain */
|
||
|
+ if (free)
|
||
|
+ kfree(spool);
|
||
|
+}
|
||
|
+
|
||
|
+struct hugepage_subpool *hugepage_new_subpool(long nr_blocks)
|
||
|
+{
|
||
|
+ struct hugepage_subpool *spool;
|
||
|
+
|
||
|
+ spool = kmalloc(sizeof(*spool), GFP_KERNEL);
|
||
|
+ if (!spool)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ spin_lock_init(&spool->lock);
|
||
|
+ spool->count = 1;
|
||
|
+ spool->max_hpages = nr_blocks;
|
||
|
+ spool->used_hpages = 0;
|
||
|
+
|
||
|
+ return spool;
|
||
|
+}
|
||
|
+
|
||
|
+void hugepage_put_subpool(struct hugepage_subpool *spool)
|
||
|
+{
|
||
|
+ spin_lock(&spool->lock);
|
||
|
+ BUG_ON(!spool->count);
|
||
|
+ spool->count--;
|
||
|
+ unlock_or_release_subpool(spool);
|
||
|
+}
|
||
|
+
|
||
|
+static int hugepage_subpool_get_pages(struct hugepage_subpool *spool,
|
||
|
+ long delta)
|
||
|
+{
|
||
|
+ int ret = 0;
|
||
|
+
|
||
|
+ if (!spool)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ spin_lock(&spool->lock);
|
||
|
+ if ((spool->used_hpages + delta) <= spool->max_hpages) {
|
||
|
+ spool->used_hpages += delta;
|
||
|
+ } else {
|
||
|
+ ret = -ENOMEM;
|
||
|
+ }
|
||
|
+ spin_unlock(&spool->lock);
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static void hugepage_subpool_put_pages(struct hugepage_subpool *spool,
|
||
|
+ long delta)
|
||
|
+{
|
||
|
+ if (!spool)
|
||
|
+ return;
|
||
|
+
|
||
|
+ spin_lock(&spool->lock);
|
||
|
+ spool->used_hpages -= delta;
|
||
|
+ /* If hugetlbfs_put_super couldn't free spool due to
|
||
|
+ * an outstanding quota reference, free it now. */
|
||
|
+ unlock_or_release_subpool(spool);
|
||
|
+}
|
||
|
+
|
||
|
+static inline struct hugepage_subpool *subpool_inode(struct inode *inode)
|
||
|
+{
|
||
|
+ return HUGETLBFS_SB(inode->i_sb)->spool;
|
||
|
+}
|
||
|
+
|
||
|
+static inline struct hugepage_subpool *subpool_vma(struct vm_area_struct *vma)
|
||
|
+{
|
||
|
+ return subpool_inode(vma->vm_file->f_dentry->d_inode);
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* Region tracking -- allows tracking of reservations and instantiated pages
|
||
|
* across the pages in a mapping.
|
||
|
@@ -533,9 +611,9 @@ static void free_huge_page(struct page *page)
|
||
|
*/
|
||
|
struct hstate *h = page_hstate(page);
|
||
|
int nid = page_to_nid(page);
|
||
|
- struct address_space *mapping;
|
||
|
+ struct hugepage_subpool *spool =
|
||
|
+ (struct hugepage_subpool *)page_private(page);
|
||
|
|
||
|
- mapping = (struct address_space *) page_private(page);
|
||
|
set_page_private(page, 0);
|
||
|
page->mapping = NULL;
|
||
|
BUG_ON(page_count(page));
|
||
|
@@ -551,8 +629,7 @@ static void free_huge_page(struct page *page)
|
||
|
enqueue_huge_page(h, page);
|
||
|
}
|
||
|
spin_unlock(&hugetlb_lock);
|
||
|
- if (mapping)
|
||
|
- hugetlb_put_quota(mapping, 1);
|
||
|
+ hugepage_subpool_put_pages(spool, 1);
|
||
|
}
|
||
|
|
||
|
static void prep_new_huge_page(struct hstate *h, struct page *page, int nid)
|
||
|
@@ -966,11 +1043,12 @@ static void return_unused_surplus_pages(struct hstate *h,
|
||
|
/*
|
||
|
* Determine if the huge page at addr within the vma has an associated
|
||
|
* reservation. Where it does not we will need to logically increase
|
||
|
- * reservation and actually increase quota before an allocation can occur.
|
||
|
- * Where any new reservation would be required the reservation change is
|
||
|
- * prepared, but not committed. Once the page has been quota'd allocated
|
||
|
- * an instantiated the change should be committed via vma_commit_reservation.
|
||
|
- * No action is required on failure.
|
||
|
+ * reservation and actually increase subpool usage before an allocation
|
||
|
+ * can occur. Where any new reservation would be required the
|
||
|
+ * reservation change is prepared, but not committed. Once the page
|
||
|
+ * has been allocated from the subpool and instantiated the change should
|
||
|
+ * be committed via vma_commit_reservation. No action is required on
|
||
|
+ * failure.
|
||
|
*/
|
||
|
static long vma_needs_reservation(struct hstate *h,
|
||
|
struct vm_area_struct *vma, unsigned long addr)
|
||
|
@@ -1019,24 +1097,24 @@ static void vma_commit_reservation(struct hstate *h,
|
||
|
static struct page *alloc_huge_page(struct vm_area_struct *vma,
|
||
|
unsigned long addr, int avoid_reserve)
|
||
|
{
|
||
|
+ struct hugepage_subpool *spool = subpool_vma(vma);
|
||
|
struct hstate *h = hstate_vma(vma);
|
||
|
struct page *page;
|
||
|
- struct address_space *mapping = vma->vm_file->f_mapping;
|
||
|
- struct inode *inode = mapping->host;
|
||
|
long chg;
|
||
|
|
||
|
/*
|
||
|
- * Processes that did not create the mapping will have no reserves and
|
||
|
- * will not have accounted against quota. Check that the quota can be
|
||
|
- * made before satisfying the allocation
|
||
|
- * MAP_NORESERVE mappings may also need pages and quota allocated
|
||
|
- * if no reserve mapping overlaps.
|
||
|
+ * Processes that did not create the mapping will have no
|
||
|
+ * reserves and will not have accounted against subpool
|
||
|
+ * limit. Check that the subpool limit can be made before
|
||
|
+ * satisfying the allocation MAP_NORESERVE mappings may also
|
||
|
+ * need pages and subpool limit allocated allocated if no reserve
|
||
|
+ * mapping overlaps.
|
||
|
*/
|
||
|
chg = vma_needs_reservation(h, vma, addr);
|
||
|
if (chg < 0)
|
||
|
return ERR_PTR(-VM_FAULT_OOM);
|
||
|
if (chg)
|
||
|
- if (hugetlb_get_quota(inode->i_mapping, chg))
|
||
|
+ if (hugepage_subpool_get_pages(spool, chg))
|
||
|
return ERR_PTR(-VM_FAULT_SIGBUS);
|
||
|
|
||
|
spin_lock(&hugetlb_lock);
|
||
|
@@ -1046,12 +1124,12 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma,
|
||
|
if (!page) {
|
||
|
page = alloc_buddy_huge_page(h, NUMA_NO_NODE);
|
||
|
if (!page) {
|
||
|
- hugetlb_put_quota(inode->i_mapping, chg);
|
||
|
+ hugepage_subpool_put_pages(spool, chg);
|
||
|
return ERR_PTR(-VM_FAULT_SIGBUS);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- set_page_private(page, (unsigned long) mapping);
|
||
|
+ set_page_private(page, (unsigned long)spool);
|
||
|
|
||
|
vma_commit_reservation(h, vma, addr);
|
||
|
|
||
|
@@ -2081,6 +2159,7 @@ static void hugetlb_vm_op_close(struct vm_area_struct *vma)
|
||
|
{
|
||
|
struct hstate *h = hstate_vma(vma);
|
||
|
struct resv_map *reservations = vma_resv_map(vma);
|
||
|
+ struct hugepage_subpool *spool = subpool_vma(vma);
|
||
|
unsigned long reserve;
|
||
|
unsigned long start;
|
||
|
unsigned long end;
|
||
|
@@ -2096,7 +2175,7 @@ static void hugetlb_vm_op_close(struct vm_area_struct *vma)
|
||
|
|
||
|
if (reserve) {
|
||
|
hugetlb_acct_memory(h, -reserve);
|
||
|
- hugetlb_put_quota(vma->vm_file->f_mapping, reserve);
|
||
|
+ hugepage_subpool_put_pages(spool, reserve);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
@@ -2326,7 +2405,7 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma,
|
||
|
address = address & huge_page_mask(h);
|
||
|
pgoff = ((address - vma->vm_start) >> PAGE_SHIFT)
|
||
|
+ (vma->vm_pgoff >> PAGE_SHIFT);
|
||
|
- mapping = (struct address_space *)page_private(page);
|
||
|
+ mapping = vma->vm_file->f_dentry->d_inode->i_mapping;
|
||
|
|
||
|
/*
|
||
|
* Take the mapping lock for the duration of the table walk. As
|
||
|
@@ -2865,11 +2944,12 @@ int hugetlb_reserve_pages(struct inode *inode,
|
||
|
{
|
||
|
long ret, chg;
|
||
|
struct hstate *h = hstate_inode(inode);
|
||
|
+ struct hugepage_subpool *spool = subpool_inode(inode);
|
||
|
|
||
|
/*
|
||
|
* Only apply hugepage reservation if asked. At fault time, an
|
||
|
* attempt will be made for VM_NORESERVE to allocate a page
|
||
|
- * and filesystem quota without using reserves
|
||
|
+ * without using reserves
|
||
|
*/
|
||
|
if (vm_flags & VM_NORESERVE)
|
||
|
return 0;
|
||
|
@@ -2898,19 +2978,19 @@ int hugetlb_reserve_pages(struct inode *inode,
|
||
|
goto out_err;
|
||
|
}
|
||
|
|
||
|
- /* There must be enough filesystem quota for the mapping */
|
||
|
- if (hugetlb_get_quota(inode->i_mapping, chg)) {
|
||
|
+ /* There must be enough pages in the subpool for the mapping */
|
||
|
+ if (hugepage_subpool_get_pages(spool, chg)) {
|
||
|
ret = -ENOSPC;
|
||
|
goto out_err;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Check enough hugepages are available for the reservation.
|
||
|
- * Hand back the quota if there are not
|
||
|
+ * Hand the pages back to the subpool if there are not
|
||
|
*/
|
||
|
ret = hugetlb_acct_memory(h, chg);
|
||
|
if (ret < 0) {
|
||
|
- hugetlb_put_quota(inode->i_mapping, chg);
|
||
|
+ hugepage_subpool_put_pages(spool, chg);
|
||
|
goto out_err;
|
||
|
}
|
||
|
|
||
|
@@ -2938,12 +3018,13 @@ void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
|
||
|
{
|
||
|
struct hstate *h = hstate_inode(inode);
|
||
|
long chg = region_truncate(&inode->i_mapping->private_list, offset);
|
||
|
+ struct hugepage_subpool *spool = subpool_inode(inode);
|
||
|
|
||
|
spin_lock(&inode->i_lock);
|
||
|
inode->i_blocks -= (blocks_per_huge_page(h) * freed);
|
||
|
spin_unlock(&inode->i_lock);
|
||
|
|
||
|
- hugetlb_put_quota(inode->i_mapping, (chg - freed));
|
||
|
+ hugepage_subpool_put_pages(spool, (chg - freed));
|
||
|
hugetlb_acct_memory(h, -(chg - freed));
|
||
|
}
|
||
|
|
||
|
diff --git a/mm/vmscan.c b/mm/vmscan.c
|
||
|
index fbe2d2c..8342119 100644
|
||
|
--- a/mm/vmscan.c
|
||
|
+++ b/mm/vmscan.c
|
||
|
@@ -2824,7 +2824,10 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx)
|
||
|
* them before going back to sleep.
|
||
|
*/
|
||
|
set_pgdat_percpu_threshold(pgdat, calculate_normal_threshold);
|
||
|
- schedule();
|
||
|
+
|
||
|
+ if (!kthread_should_stop())
|
||
|
+ schedule();
|
||
|
+
|
||
|
set_pgdat_percpu_threshold(pgdat, calculate_pressure_threshold);
|
||
|
} else {
|
||
|
if (remaining)
|
||
|
@@ -3090,14 +3093,17 @@ int kswapd_run(int nid)
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- * Called by memory hotplug when all memory in a node is offlined.
|
||
|
+ * Called by memory hotplug when all memory in a node is offlined. Caller must
|
||
|
+ * hold lock_memory_hotplug().
|
||
|
*/
|
||
|
void kswapd_stop(int nid)
|
||
|
{
|
||
|
struct task_struct *kswapd = NODE_DATA(nid)->kswapd;
|
||
|
|
||
|
- if (kswapd)
|
||
|
+ if (kswapd) {
|
||
|
kthread_stop(kswapd);
|
||
|
+ NODE_DATA(nid)->kswapd = NULL;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
static int __init kswapd_init(void)
|
||
|
diff --git a/net/can/raw.c b/net/can/raw.c
|
||
|
index cde1b4a..46cca3a 100644
|
||
|
--- a/net/can/raw.c
|
||
|
+++ b/net/can/raw.c
|
||
|
@@ -681,9 +681,6 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||
|
if (err < 0)
|
||
|
goto free_skb;
|
||
|
|
||
|
- /* to be able to check the received tx sock reference in raw_rcv() */
|
||
|
- skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF;
|
||
|
-
|
||
|
skb->dev = dev;
|
||
|
skb->sk = sk;
|
||
|
|
||
|
diff --git a/net/core/dev.c b/net/core/dev.c
|
||
|
index 1cbddc9..5738654 100644
|
||
|
--- a/net/core/dev.c
|
||
|
+++ b/net/core/dev.c
|
||
|
@@ -2079,25 +2079,6 @@ static int dev_gso_segment(struct sk_buff *skb, int features)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
-/*
|
||
|
- * Try to orphan skb early, right before transmission by the device.
|
||
|
- * We cannot orphan skb if tx timestamp is requested or the sk-reference
|
||
|
- * is needed on driver level for other reasons, e.g. see net/can/raw.c
|
||
|
- */
|
||
|
-static inline void skb_orphan_try(struct sk_buff *skb)
|
||
|
-{
|
||
|
- struct sock *sk = skb->sk;
|
||
|
-
|
||
|
- if (sk && !skb_shinfo(skb)->tx_flags) {
|
||
|
- /* skb_tx_hash() wont be able to get sk.
|
||
|
- * We copy sk_hash into skb->rxhash
|
||
|
- */
|
||
|
- if (!skb->rxhash)
|
||
|
- skb->rxhash = sk->sk_hash;
|
||
|
- skb_orphan(skb);
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
static bool can_checksum_protocol(unsigned long features, __be16 protocol)
|
||
|
{
|
||
|
return ((features & NETIF_F_GEN_CSUM) ||
|
||
|
@@ -2182,8 +2163,6 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
|
||
|
if (!list_empty(&ptype_all))
|
||
|
dev_queue_xmit_nit(skb, dev);
|
||
|
|
||
|
- skb_orphan_try(skb);
|
||
|
-
|
||
|
features = netif_skb_features(skb);
|
||
|
|
||
|
if (vlan_tx_tag_present(skb) &&
|
||
|
@@ -2293,7 +2272,7 @@ u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb,
|
||
|
if (skb->sk && skb->sk->sk_hash)
|
||
|
hash = skb->sk->sk_hash;
|
||
|
else
|
||
|
- hash = (__force u16) skb->protocol ^ skb->rxhash;
|
||
|
+ hash = (__force u16) skb->protocol;
|
||
|
hash = jhash_1word(hash, hashrnd);
|
||
|
|
||
|
return (u16) (((u64) hash * qcount) >> 32) + qoffset;
|
||
|
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
|
||
|
index 9726927..32e6ca2 100644
|
||
|
--- a/net/ipv4/tcp_input.c
|
||
|
+++ b/net/ipv4/tcp_input.c
|
||
|
@@ -5836,6 +5836,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
|
||
|
goto discard;
|
||
|
|
||
|
if (th->syn) {
|
||
|
+ if (th->fin)
|
||
|
+ goto discard;
|
||
|
if (icsk->icsk_af_ops->conn_request(sk, skb) < 0)
|
||
|
return 1;
|
||
|
|
||
|
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
|
||
|
index 274d150..cf98d62 100644
|
||
|
--- a/net/iucv/af_iucv.c
|
||
|
+++ b/net/iucv/af_iucv.c
|
||
|
@@ -380,7 +380,6 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock,
|
||
|
skb_trim(skb, skb->dev->mtu);
|
||
|
}
|
||
|
skb->protocol = ETH_P_AF_IUCV;
|
||
|
- skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF;
|
||
|
nskb = skb_clone(skb, GFP_ATOMIC);
|
||
|
if (!nskb)
|
||
|
return -ENOMEM;
|
||
|
diff --git a/net/wireless/util.c b/net/wireless/util.c
|
||
|
index d38815d..74d5292 100644
|
||
|
--- a/net/wireless/util.c
|
||
|
+++ b/net/wireless/util.c
|
||
|
@@ -813,7 +813,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||
|
ntype == NL80211_IFTYPE_P2P_CLIENT))
|
||
|
return -EBUSY;
|
||
|
|
||
|
- if (ntype != otype) {
|
||
|
+ if (ntype != otype && netif_running(dev)) {
|
||
|
err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
|
||
|
ntype);
|
||
|
if (err)
|
||
|
diff --git a/scripts/depmod.sh b/scripts/depmod.sh
|
||
|
index a272356..2ae4817 100755
|
||
|
--- a/scripts/depmod.sh
|
||
|
+++ b/scripts/depmod.sh
|
||
|
@@ -9,12 +9,6 @@ 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
|
||
|
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
|
||
|
index 9f614b4..272407c 100644
|
||
|
--- a/virt/kvm/irq_comm.c
|
||
|
+++ b/virt/kvm/irq_comm.c
|
||
|
@@ -318,6 +318,7 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt,
|
||
|
*/
|
||
|
hlist_for_each_entry(ei, n, &rt->map[ue->gsi], link)
|
||
|
if (ei->type == KVM_IRQ_ROUTING_MSI ||
|
||
|
+ ue->type == KVM_IRQ_ROUTING_MSI ||
|
||
|
ue->u.irqchip.irqchip == ei->irqchip.irqchip)
|
||
|
return r;
|
||
|
|