diff -druN linux-libre-3.0.27-gnu/arch/m68k/mac/config.c linux-libre-3.0.28-gnu/arch/m68k/mac/config.c
--- linux-libre-3.0.27-gnu/arch/m68k/mac/config.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/arch/m68k/mac/config.c	2012-04-13 11:26:29.000000000 -0400
@@ -950,6 +950,9 @@
 {
 	u8 *swim_base;
 
+	if (!MACH_IS_MAC)
+		return -ENODEV;
+
 	/*
 	 * Serial devices
 	 */
diff -druN linux-libre-3.0.27-gnu/arch/x86/include/asm/timer.h linux-libre-3.0.28-gnu/arch/x86/include/asm/timer.h
--- linux-libre-3.0.27-gnu/arch/x86/include/asm/timer.h	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/arch/x86/include/asm/timer.h	2012-04-13 11:26:29.000000000 -0400
@@ -57,14 +57,10 @@
 
 static inline unsigned long long __cycles_2_ns(unsigned long long cyc)
 {
-	unsigned long long quot;
-	unsigned long long rem;
 	int cpu = smp_processor_id();
 	unsigned long long ns = per_cpu(cyc2ns_offset, cpu);
-	quot = (cyc >> CYC2NS_SCALE_FACTOR);
-	rem = cyc & ((1ULL << CYC2NS_SCALE_FACTOR) - 1);
-	ns += quot * per_cpu(cyc2ns, cpu) +
-		((rem * per_cpu(cyc2ns, cpu)) >> CYC2NS_SCALE_FACTOR);
+	ns += mult_frac(cyc, per_cpu(cyc2ns, cpu),
+			(1UL << CYC2NS_SCALE_FACTOR));
 	return ns;
 }
 
diff -druN linux-libre-3.0.27-gnu/arch/x86/kernel/amd_iommu_init.c linux-libre-3.0.28-gnu/arch/x86/kernel/amd_iommu_init.c
--- linux-libre-3.0.27-gnu/arch/x86/kernel/amd_iommu_init.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/arch/x86/kernel/amd_iommu_init.c	2012-04-13 11:26:29.000000000 -0400
@@ -1031,8 +1031,9 @@
 {
 	int r;
 
-	if (pci_enable_msi(iommu->dev))
-		return 1;
+	r = pci_enable_msi(iommu->dev);
+	if (r)
+		return r;
 
 	r = request_threaded_irq(iommu->dev->irq,
 				 amd_iommu_int_handler,
@@ -1042,24 +1043,33 @@
 
 	if (r) {
 		pci_disable_msi(iommu->dev);
-		return 1;
+		return r;
 	}
 
 	iommu->int_enabled = true;
-	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
 
 	return 0;
 }
 
 static int iommu_init_msi(struct amd_iommu *iommu)
 {
+	int ret;
+
 	if (iommu->int_enabled)
-		return 0;
+		goto enable_faults;
 
 	if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
-		return iommu_setup_msi(iommu);
+		ret = iommu_setup_msi(iommu);
+	else
+		ret = -ENODEV;
 
-	return 1;
+	if (ret)
+		return ret;
+
+enable_faults:
+	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
+
+	return 0;
 }
 
 /****************************************************************************
diff -druN linux-libre-3.0.27-gnu/arch/x86/kernel/apic/io_apic.c linux-libre-3.0.28-gnu/arch/x86/kernel/apic/io_apic.c
--- linux-libre-3.0.27-gnu/arch/x86/kernel/apic/io_apic.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/arch/x86/kernel/apic/io_apic.c	2012-04-13 11:26:29.000000000 -0400
@@ -3927,33 +3927,15 @@
 static __init int bad_ioapic(unsigned long address)
 {
 	if (nr_ioapics >= MAX_IO_APICS) {
-		pr_warn("WARNING: Max # of I/O APICs (%d) exceeded (found %d), skipping\n",
-			MAX_IO_APICS, nr_ioapics);
+		printk(KERN_WARNING "WARNING: Max # of I/O APICs (%d) exceeded "
+		       "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics);
 		return 1;
 	}
 	if (!address) {
-		pr_warn("WARNING: Bogus (zero) I/O APIC address found in table, skipping!\n");
-		return 1;
-	}
-	return 0;
-}
-
-static __init int bad_ioapic_register(int idx)
-{
-	union IO_APIC_reg_00 reg_00;
-	union IO_APIC_reg_01 reg_01;
-	union IO_APIC_reg_02 reg_02;
-
-	reg_00.raw = io_apic_read(idx, 0);
-	reg_01.raw = io_apic_read(idx, 1);
-	reg_02.raw = io_apic_read(idx, 2);
-
-	if (reg_00.raw == -1 && reg_01.raw == -1 && reg_02.raw == -1) {
-		pr_warn("I/O APIC 0x%x registers return all ones, skipping!\n",
-			mpc_ioapic_addr(idx));
+		printk(KERN_WARNING "WARNING: Bogus (zero) I/O APIC address"
+		       " found in table, skipping!\n");
 		return 1;
 	}
-
 	return 0;
 }
 
@@ -3973,12 +3955,6 @@
 	ioapics[idx].mp_config.apicaddr = address;
 
 	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
-
-	if (bad_ioapic_register(idx)) {
-		clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
-		return;
-	}
-
 	ioapics[idx].mp_config.apicid = io_apic_unique_id(id);
 	ioapics[idx].mp_config.apicver = io_apic_get_version(idx);
 
@@ -3999,10 +3975,10 @@
 	if (gsi_cfg->gsi_end >= gsi_top)
 		gsi_top = gsi_cfg->gsi_end + 1;
 
-	pr_info("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, GSI %d-%d\n",
-		idx, mpc_ioapic_id(idx),
-		mpc_ioapic_ver(idx), mpc_ioapic_addr(idx),
-		gsi_cfg->gsi_base, gsi_cfg->gsi_end);
+	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
+	       "GSI %d-%d\n", idx, mpc_ioapic_id(idx),
+	       mpc_ioapic_ver(idx), mpc_ioapic_addr(idx),
+	       gsi_cfg->gsi_base, gsi_cfg->gsi_end);
 
 	nr_ioapics++;
 }
diff -druN linux-libre-3.0.27-gnu/arch/x86/kernel/kgdb.c linux-libre-3.0.28-gnu/arch/x86/kernel/kgdb.c
--- linux-libre-3.0.27-gnu/arch/x86/kernel/kgdb.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/arch/x86/kernel/kgdb.c	2012-04-13 11:26:29.000000000 -0400
@@ -43,6 +43,8 @@
 #include <linux/smp.h>
 #include <linux/nmi.h>
 #include <linux/hw_breakpoint.h>
+#include <linux/uaccess.h>
+#include <linux/memory.h>
 
 #include <asm/debugreg.h>
 #include <asm/apicdef.h>
@@ -710,6 +712,64 @@
 	regs->ip = ip;
 }
 
+int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
+{
+	int err;
+	char opc[BREAK_INSTR_SIZE];
+
+	bpt->type = BP_BREAKPOINT;
+	err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+				BREAK_INSTR_SIZE);
+	if (err)
+		return err;
+	err = probe_kernel_write((char *)bpt->bpt_addr,
+				 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
+#ifdef CONFIG_DEBUG_RODATA
+	if (!err)
+		return err;
+	/*
+	 * It is safe to call text_poke() because normal kernel execution
+	 * is stopped on all cores, so long as the text_mutex is not locked.
+	 */
+	if (mutex_is_locked(&text_mutex))
+		return -EBUSY;
+	text_poke((void *)bpt->bpt_addr, arch_kgdb_ops.gdb_bpt_instr,
+		  BREAK_INSTR_SIZE);
+	err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
+	if (err)
+		return err;
+	if (memcmp(opc, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE))
+		return -EINVAL;
+	bpt->type = BP_POKE_BREAKPOINT;
+#endif /* CONFIG_DEBUG_RODATA */
+	return err;
+}
+
+int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
+{
+#ifdef CONFIG_DEBUG_RODATA
+	int err;
+	char opc[BREAK_INSTR_SIZE];
+
+	if (bpt->type != BP_POKE_BREAKPOINT)
+		goto knl_write;
+	/*
+	 * It is safe to call text_poke() because normal kernel execution
+	 * is stopped on all cores, so long as the text_mutex is not locked.
+	 */
+	if (mutex_is_locked(&text_mutex))
+		goto knl_write;
+	text_poke((void *)bpt->bpt_addr, bpt->saved_instr, BREAK_INSTR_SIZE);
+	err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
+	if (err || memcmp(opc, bpt->saved_instr, BREAK_INSTR_SIZE))
+		goto knl_write;
+	return err;
+knl_write:
+#endif /* CONFIG_DEBUG_RODATA */
+	return probe_kernel_write((char *)bpt->bpt_addr,
+				  (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
+}
+
 struct kgdb_arch arch_kgdb_ops = {
 	/* Breakpoint instruction: */
 	.gdb_bpt_instr		= { 0xcc },
diff -druN linux-libre-3.0.27-gnu/arch/x86/kernel/tsc.c linux-libre-3.0.28-gnu/arch/x86/kernel/tsc.c
--- linux-libre-3.0.27-gnu/arch/x86/kernel/tsc.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/arch/x86/kernel/tsc.c	2012-04-13 11:26:29.000000000 -0400
@@ -623,7 +623,8 @@
 
 	if (cpu_khz) {
 		*scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
-		*offset = ns_now - (tsc_now * *scale >> CYC2NS_SCALE_FACTOR);
+		*offset = ns_now - mult_frac(tsc_now, *scale,
+					     (1UL << CYC2NS_SCALE_FACTOR));
 	}
 
 	sched_clock_idle_wakeup_event(0);
diff -druN linux-libre-3.0.27-gnu/arch/x86/net/bpf_jit_comp.c linux-libre-3.0.28-gnu/arch/x86/net/bpf_jit_comp.c
--- linux-libre-3.0.27-gnu/arch/x86/net/bpf_jit_comp.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/arch/x86/net/bpf_jit_comp.c	2012-04-13 11:26:29.000000000 -0400
@@ -289,7 +289,7 @@
 					EMIT2(0x24, K & 0xFF); /* and imm8,%al */
 				} else if (K >= 0xFFFF0000) {
 					EMIT2(0x66, 0x25);	/* and imm16,%ax */
-					EMIT2(K, 2);
+					EMIT(K, 2);
 				} else {
 					EMIT1_off32(0x25, K);	/* and imm32,%eax */
 				}
diff -druN linux-libre-3.0.27-gnu/arch/x86/pci/acpi.c linux-libre-3.0.28-gnu/arch/x86/pci/acpi.c
--- linux-libre-3.0.27-gnu/arch/x86/pci/acpi.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/arch/x86/pci/acpi.c	2012-04-13 11:26:29.000000000 -0400
@@ -54,6 +54,16 @@
 			DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
 		},
 	},
+	/* https://bugzilla.kernel.org/show_bug.cgi?id=42619 */
+	{
+		.callback = set_use_crs,
+		.ident = "MSI MS-7253",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+			DMI_MATCH(DMI_BOARD_NAME, "MS-7253"),
+			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"),
+		},
+	},
 	{}
 };
 
diff -druN linux-libre-3.0.27-gnu/drivers/acpi/acpica/tbfadt.c linux-libre-3.0.28-gnu/drivers/acpi/acpica/tbfadt.c
--- linux-libre-3.0.27-gnu/drivers/acpi/acpica/tbfadt.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/acpi/acpica/tbfadt.c	2012-04-13 11:26:29.000000000 -0400
@@ -350,10 +350,6 @@
 	u32 address32;
 	u32 i;
 
-	/* Update the local FADT table header length */
-
-	acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
-
 	/*
 	 * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
 	 * Later code will always use the X 64-bit field. Also, check for an
@@ -395,6 +391,10 @@
 		acpi_gbl_FADT.boot_flags = 0;
 	}
 
+	/* Update the local FADT table header length */
+
+	acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
+
 	/*
 	 * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
 	 * generic address structures as necessary. Later code will always use
diff -druN linux-libre-3.0.27-gnu/drivers/acpi/processor_thermal.c linux-libre-3.0.28-gnu/drivers/acpi/processor_thermal.c
--- linux-libre-3.0.27-gnu/drivers/acpi/processor_thermal.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/acpi/processor_thermal.c	2012-04-13 11:26:29.000000000 -0400
@@ -58,6 +58,27 @@
 static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg);
 static unsigned int acpi_thermal_cpufreq_is_init = 0;
 
+#define reduction_pctg(cpu) \
+	per_cpu(cpufreq_thermal_reduction_pctg, phys_package_first_cpu(cpu))
+
+/*
+ * Emulate "per package data" using per cpu data (which should really be
+ * provided elsewhere)
+ *
+ * Note we can lose a CPU on cpu hotunplug, in this case we forget the state
+ * temporarily. Fortunately that's not a big issue here (I hope)
+ */
+static int phys_package_first_cpu(int cpu)
+{
+	int i;
+	int id = topology_physical_package_id(cpu);
+
+	for_each_online_cpu(i)
+		if (topology_physical_package_id(i) == id)
+			return i;
+	return 0;
+}
+
 static int cpu_has_cpufreq(unsigned int cpu)
 {
 	struct cpufreq_policy policy;
@@ -77,7 +98,7 @@
 
 	max_freq = (
 	    policy->cpuinfo.max_freq *
-	    (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20)
+	    (100 - reduction_pctg(policy->cpu) * 20)
 	) / 100;
 
 	cpufreq_verify_within_limits(policy, 0, max_freq);
@@ -103,16 +124,28 @@
 	if (!cpu_has_cpufreq(cpu))
 		return 0;
 
-	return per_cpu(cpufreq_thermal_reduction_pctg, cpu);
+	return reduction_pctg(cpu);
 }
 
 static int cpufreq_set_cur_state(unsigned int cpu, int state)
 {
+	int i;
+
 	if (!cpu_has_cpufreq(cpu))
 		return 0;
 
-	per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state;
-	cpufreq_update_policy(cpu);
+	reduction_pctg(cpu) = state;
+
+	/*
+	 * Update all the CPUs in the same package because they all
+	 * contribute to the temperature and often share the same
+	 * frequency.
+	 */
+	for_each_online_cpu(i) {
+		if (topology_physical_package_id(i) ==
+		    topology_physical_package_id(cpu))
+			cpufreq_update_policy(i);
+	}
 	return 0;
 }
 
@@ -120,10 +153,6 @@
 {
 	int i;
 
-	for (i = 0; i < nr_cpu_ids; i++)
-		if (cpu_present(i))
-			per_cpu(cpufreq_thermal_reduction_pctg, i) = 0;
-
 	i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block,
 				      CPUFREQ_POLICY_NOTIFIER);
 	if (!i)
diff -druN linux-libre-3.0.27-gnu/drivers/gpu/drm/drm_fb_helper.c linux-libre-3.0.28-gnu/drivers/gpu/drm/drm_fb_helper.c
--- linux-libre-3.0.27-gnu/drivers/gpu/drm/drm_fb_helper.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/gpu/drm/drm_fb_helper.c	2012-04-13 11:26:29.000000000 -0400
@@ -610,9 +610,13 @@
 		return -EINVAL;
 
 	/* Need to resize the fb object !!! */
-	if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) {
+	if (var->bits_per_pixel > fb->bits_per_pixel ||
+	    var->xres > fb->width || var->yres > fb->height ||
+	    var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
 		DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb "
-			  "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel,
+			  "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
+			  var->xres, var->yres, var->bits_per_pixel,
+			  var->xres_virtual, var->yres_virtual,
 			  fb->width, fb->height, fb->bits_per_pixel);
 		return -EINVAL;
 	}
diff -druN linux-libre-3.0.27-gnu/drivers/gpu/drm/i915/i915_drv.c linux-libre-3.0.28-gnu/drivers/gpu/drm/i915/i915_drv.c
--- linux-libre-3.0.27-gnu/drivers/gpu/drm/i915/i915_drv.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/gpu/drm/i915/i915_drv.c	2012-04-13 11:26:29.000000000 -0400
@@ -442,7 +442,9 @@
 		drm_irq_install(dev);
 
 		/* Resume the modeset for every activated CRTC */
+		mutex_lock(&dev->mode_config.mutex);
 		drm_helper_resume_force_mode(dev);
+		mutex_unlock(&dev->mode_config.mutex);
 
 		if (IS_IRONLAKE_M(dev))
 			ironlake_enable_rc6(dev);
diff -druN linux-libre-3.0.27-gnu/drivers/gpu/drm/i915/i915_reg.h linux-libre-3.0.28-gnu/drivers/gpu/drm/i915/i915_reg.h
--- linux-libre-3.0.27-gnu/drivers/gpu/drm/i915/i915_reg.h	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/gpu/drm/i915/i915_reg.h	2012-04-13 11:26:29.000000000 -0400
@@ -2274,6 +2274,7 @@
 #define   PIPECONF_DISABLE	0
 #define   PIPECONF_DOUBLE_WIDE	(1<<30)
 #define   I965_PIPECONF_ACTIVE	(1<<30)
+#define   PIPECONF_FRAME_START_DELAY_MASK (3<<27)
 #define   PIPECONF_SINGLE_WIDE	0
 #define   PIPECONF_PIPE_UNLOCKED 0
 #define   PIPECONF_PIPE_LOCKED	(1<<25)
diff -druN linux-libre-3.0.27-gnu/drivers/gpu/drm/i915/intel_bios.c linux-libre-3.0.28-gnu/drivers/gpu/drm/i915/intel_bios.c
--- linux-libre-3.0.27-gnu/drivers/gpu/drm/i915/intel_bios.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/gpu/drm/i915/intel_bios.c	2012-04-13 11:26:29.000000000 -0400
@@ -24,6 +24,7 @@
  *    Eric Anholt <eric@anholt.net>
  *
  */
+#include <linux/dmi.h>
 #include <drm/drm_dp_helper.h>
 #include "drmP.h"
 #include "drm.h"
@@ -592,6 +593,26 @@
 	dev_priv->edp.bpp = 18;
 }
 
+static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
+{
+	DRM_DEBUG_KMS("Falling back to manually reading VBT from "
+		      "VBIOS ROM for %s\n",
+		      id->ident);
+	return 1;
+}
+
+static const struct dmi_system_id intel_no_opregion_vbt[] = {
+	{
+		.callback = intel_no_opregion_vbt_callback,
+		.ident = "ThinkCentre A57",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"),
+		},
+	},
+	{ }
+};
+
 /**
  * intel_parse_bios - find VBT and initialize settings from the BIOS
  * @dev: DRM device
@@ -612,7 +633,7 @@
 	init_vbt_defaults(dev_priv);
 
 	/* XXX Should this validation be moved to intel_opregion.c? */
-	if (dev_priv->opregion.vbt) {
+	if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) {
 		struct vbt_header *vbt = dev_priv->opregion.vbt;
 		if (memcmp(vbt->signature, "$VBT", 4) == 0) {
 			DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n",
diff -druN linux-libre-3.0.27-gnu/drivers/gpu/drm/i915/intel_display.c linux-libre-3.0.28-gnu/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-3.0.27-gnu/drivers/gpu/drm/i915/intel_display.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/gpu/drm/i915/intel_display.c	2012-04-13 11:26:29.000000000 -0400
@@ -6580,6 +6580,12 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 reg, val;
 
+	/* Clear any frame start delays used for debugging left by the BIOS */
+	for_each_pipe(pipe) {
+		reg = PIPECONF(pipe);
+		I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+	}
+
 	if (HAS_PCH_SPLIT(dev))
 		return;
 
diff -druN linux-libre-3.0.27-gnu/drivers/gpu/drm/i915/intel_lvds.c linux-libre-3.0.28-gnu/drivers/gpu/drm/i915/intel_lvds.c
--- linux-libre-3.0.27-gnu/drivers/gpu/drm/i915/intel_lvds.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/gpu/drm/i915/intel_lvds.c	2012-04-13 11:26:29.000000000 -0400
@@ -743,6 +743,14 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
 		},
 	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "MSI Wind Box DC500",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+			DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
+		},
+	},
 
 	{ }	/* terminating entry */
 };
diff -druN linux-libre-3.0.27-gnu/drivers/gpu/drm/radeon/atom.c linux-libre-3.0.28-gnu/drivers/gpu/drm/radeon/atom.c
--- linux-libre-3.0.27-gnu/drivers/gpu/drm/radeon/atom.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/gpu/drm/radeon/atom.c	2012-04-13 11:26:29.000000000 -0400
@@ -1301,8 +1301,11 @@
 
 int atom_asic_init(struct atom_context *ctx)
 {
+	struct radeon_device *rdev = ctx->card->dev->dev_private;
 	int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR);
 	uint32_t ps[16];
+	int ret;
+
 	memset(ps, 0, 64);
 
 	ps[0] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFSCLK_PTR));
@@ -1312,7 +1315,17 @@
 
 	if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT))
 		return 1;
-	return atom_execute_table(ctx, ATOM_CMD_INIT, ps);
+	ret = atom_execute_table(ctx, ATOM_CMD_INIT, ps);
+	if (ret)
+		return ret;
+
+	memset(ps, 0, 64);
+
+	if (rdev->family < CHIP_R600) {
+		if (CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_SPDFANCNTL))
+			atom_execute_table(ctx, ATOM_CMD_SPDFANCNTL, ps);
+	}
+	return ret;
 }
 
 void atom_destroy(struct atom_context *ctx)
diff -druN linux-libre-3.0.27-gnu/drivers/gpu/drm/radeon/atom.h linux-libre-3.0.28-gnu/drivers/gpu/drm/radeon/atom.h
--- linux-libre-3.0.27-gnu/drivers/gpu/drm/radeon/atom.h	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/gpu/drm/radeon/atom.h	2012-04-13 11:26:29.000000000 -0400
@@ -44,6 +44,7 @@
 #define ATOM_CMD_SETSCLK	0x0A
 #define ATOM_CMD_SETMCLK	0x0B
 #define ATOM_CMD_SETPCLK	0x0C
+#define ATOM_CMD_SPDFANCNTL	0x39
 
 #define ATOM_DATA_FWI_PTR	0xC
 #define ATOM_DATA_IIO_PTR	0x32
diff -druN linux-libre-3.0.27-gnu/drivers/mfd/twl6030-irq.c linux-libre-3.0.28-gnu/drivers/mfd/twl6030-irq.c
--- linux-libre-3.0.27-gnu/drivers/mfd/twl6030-irq.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/mfd/twl6030-irq.c	2012-04-13 11:26:29.000000000 -0400
@@ -145,8 +145,17 @@
 			}
 		local_irq_enable();
 		}
-		ret = twl_i2c_write(TWL_MODULE_PIH, sts.bytes,
-				REG_INT_STS_A, 3); /* clear INT_STS_A */
+
+		/*
+		 * NOTE:
+		 * Simulation confirms that documentation is wrong w.r.t the
+		 * interrupt status clear operation. A single *byte* write to
+		 * any one of STS_A to STS_C register results in all three
+		 * STS registers being reset. Since it does not matter which
+		 * value is written, all three registers are cleared on a
+		 * single byte write, so we just use 0x0 to clear.
+		 */
+		ret = twl_i2c_write_u8(TWL_MODULE_PIH, 0x00, REG_INT_STS_A);
 		if (ret)
 			pr_warning("twl6030: I2C error in clearing PIH ISR\n");
 
diff -druN linux-libre-3.0.27-gnu/drivers/misc/kgdbts.c linux-libre-3.0.28-gnu/drivers/misc/kgdbts.c
--- linux-libre-3.0.27-gnu/drivers/misc/kgdbts.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/misc/kgdbts.c	2012-04-13 11:26:29.000000000 -0400
@@ -133,12 +133,17 @@
 static int hwbreaks_ok;
 static int hw_break_val;
 static int hw_break_val2;
+static int cont_instead_of_sstep;
+static unsigned long cont_thread_id;
+static unsigned long sstep_thread_id;
 #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC)
 static int arch_needs_sstep_emulation = 1;
 #else
 static int arch_needs_sstep_emulation;
 #endif
+static unsigned long cont_addr;
 static unsigned long sstep_addr;
+static int restart_from_top_after_write;
 static int sstep_state;
 
 /* Storage for the registers, in GDB format. */
@@ -186,7 +191,8 @@
 	 */
 	while (!final_ack)
 		msleep_interruptible(1500);
-
+	/* Pause for any other threads to exit after final ack. */
+	msleep_interruptible(1000);
 	if (configured)
 		kgdb_unregister_io_module(&kgdbts_io_ops);
 	configured = 0;
@@ -210,7 +216,7 @@
 	if (!strcmp(arg, "kgdbts_break_test"))
 		addr = (unsigned long)kgdbts_break_test;
 	else if (!strcmp(arg, "sys_open"))
-		addr = (unsigned long)sys_open;
+		addr = (unsigned long)do_sys_open;
 	else if (!strcmp(arg, "do_fork"))
 		addr = (unsigned long)do_fork;
 	else if (!strcmp(arg, "hw_break_val"))
@@ -282,6 +288,16 @@
 	hw_break_val++;
 }
 
+static int get_thread_id_continue(char *put_str, char *arg)
+{
+	char *ptr = &put_str[11];
+
+	if (put_str[1] != 'T' || put_str[2] != '0')
+		return 1;
+	kgdb_hex2long(&ptr, &cont_thread_id);
+	return 0;
+}
+
 static int check_and_rewind_pc(char *put_str, char *arg)
 {
 	unsigned long addr = lookup_addr(arg);
@@ -298,13 +314,21 @@
 	if (addr + BREAK_INSTR_SIZE == ip)
 		offset = -BREAK_INSTR_SIZE;
 #endif
-	if (strcmp(arg, "silent") && ip + offset != addr) {
+
+	if (arch_needs_sstep_emulation && sstep_addr &&
+	    ip + offset == sstep_addr &&
+	    ((!strcmp(arg, "sys_open") || !strcmp(arg, "do_fork")))) {
+		/* This is special case for emulated single step */
+		v2printk("Emul: rewind hit single step bp\n");
+		restart_from_top_after_write = 1;
+	} else if (strcmp(arg, "silent") && ip + offset != addr) {
 		eprintk("kgdbts: BP mismatch %lx expected %lx\n",
 			   ip + offset, addr);
 		return 1;
 	}
 	/* Readjust the instruction pointer if needed */
 	ip += offset;
+	cont_addr = ip;
 #ifdef GDB_ADJUSTS_BREAK_OFFSET
 	instruction_pointer_set(&kgdbts_regs, ip);
 #endif
@@ -314,6 +338,8 @@
 static int check_single_step(char *put_str, char *arg)
 {
 	unsigned long addr = lookup_addr(arg);
+	static int matched_id;
+
 	/*
 	 * From an arch indepent point of view the instruction pointer
 	 * should be on a different instruction
@@ -323,6 +349,29 @@
 	gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
 	v2printk("Singlestep stopped at IP: %lx\n",
 		   instruction_pointer(&kgdbts_regs));
+
+	if (sstep_thread_id != cont_thread_id) {
+		/*
+		 * Ensure we stopped in the same thread id as before, else the
+		 * debugger should continue until the original thread that was
+		 * single stepped is scheduled again, emulating gdb's behavior.
+		 */
+		v2printk("ThrID does not match: %lx\n", cont_thread_id);
+		if (arch_needs_sstep_emulation) {
+			if (matched_id &&
+			    instruction_pointer(&kgdbts_regs) != addr)
+				goto continue_test;
+			matched_id++;
+			ts.idx -= 2;
+			sstep_state = 0;
+			return 0;
+		}
+		cont_instead_of_sstep = 1;
+		ts.idx -= 4;
+		return 0;
+	}
+continue_test:
+	matched_id = 0;
 	if (instruction_pointer(&kgdbts_regs) == addr) {
 		eprintk("kgdbts: SingleStep failed at %lx\n",
 			   instruction_pointer(&kgdbts_regs));
@@ -364,10 +413,40 @@
 	return 1;
 }
 
+static void get_cont_catch(char *arg)
+{
+	/* Always send detach because the test is completed at this point */
+	fill_get_buf("D");
+}
+
+static int put_cont_catch(char *put_str, char *arg)
+{
+	/* This is at the end of the test and we catch any and all input */
+	v2printk("kgdbts: cleanup task: %lx\n", sstep_thread_id);
+	ts.idx--;
+	return 0;
+}
+
+static int emul_reset(char *put_str, char *arg)
+{
+	if (strncmp(put_str, "$OK", 3))
+		return 1;
+	if (restart_from_top_after_write) {
+		restart_from_top_after_write = 0;
+		ts.idx = -1;
+	}
+	return 0;
+}
+
 static void emul_sstep_get(char *arg)
 {
 	if (!arch_needs_sstep_emulation) {
-		fill_get_buf(arg);
+		if (cont_instead_of_sstep) {
+			cont_instead_of_sstep = 0;
+			fill_get_buf("c");
+		} else {
+			fill_get_buf(arg);
+		}
 		return;
 	}
 	switch (sstep_state) {
@@ -397,9 +476,11 @@
 static int emul_sstep_put(char *put_str, char *arg)
 {
 	if (!arch_needs_sstep_emulation) {
-		if (!strncmp(put_str+1, arg, 2))
-			return 0;
-		return 1;
+		char *ptr = &put_str[11];
+		if (put_str[1] != 'T' || put_str[2] != '0')
+			return 1;
+		kgdb_hex2long(&ptr, &sstep_thread_id);
+		return 0;
 	}
 	switch (sstep_state) {
 	case 1:
@@ -410,8 +491,7 @@
 		v2printk("Stopped at IP: %lx\n",
 			 instruction_pointer(&kgdbts_regs));
 		/* Want to stop at IP + break instruction size by default */
-		sstep_addr = instruction_pointer(&kgdbts_regs) +
-			BREAK_INSTR_SIZE;
+		sstep_addr = cont_addr + BREAK_INSTR_SIZE;
 		break;
 	case 2:
 		if (strncmp(put_str, "$OK", 3)) {
@@ -423,6 +503,9 @@
 		if (strncmp(put_str, "$T0", 3)) {
 			eprintk("kgdbts: failed continue sstep\n");
 			return 1;
+		} else {
+			char *ptr = &put_str[11];
+			kgdb_hex2long(&ptr, &sstep_thread_id);
 		}
 		break;
 	case 4:
@@ -501,10 +584,10 @@
 static struct test_struct singlestep_break_test[] = {
 	{ "?", "S0*" }, /* Clear break points */
 	{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
-	{ "c", "T0*", }, /* Continue */
+	{ "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
+	{ "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
 	{ "g", "kgdbts_break_test", NULL, check_and_rewind_pc },
 	{ "write", "OK", write_regs }, /* Write registers */
-	{ "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
 	{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
 	{ "g", "kgdbts_break_test", NULL, check_single_step },
 	{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
@@ -522,16 +605,16 @@
 static struct test_struct do_fork_test[] = {
 	{ "?", "S0*" }, /* Clear break points */
 	{ "do_fork", "OK", sw_break, }, /* set sw breakpoint */
-	{ "c", "T0*", }, /* Continue */
-	{ "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */
-	{ "write", "OK", write_regs }, /* Write registers */
+	{ "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
 	{ "do_fork", "OK", sw_rem_break }, /*remove breakpoint */
+	{ "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */
+	{ "write", "OK", write_regs, emul_reset }, /* Write registers */
 	{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
 	{ "g", "do_fork", NULL, check_single_step },
 	{ "do_fork", "OK", sw_break, }, /* set sw breakpoint */
 	{ "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
 	{ "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */
-	{ "", "" },
+	{ "", "", get_cont_catch, put_cont_catch },
 };
 
 /* Test for hitting a breakpoint at sys_open for what ever the number
@@ -540,16 +623,16 @@
 static struct test_struct sys_open_test[] = {
 	{ "?", "S0*" }, /* Clear break points */
 	{ "sys_open", "OK", sw_break, }, /* set sw breakpoint */
-	{ "c", "T0*", }, /* Continue */
-	{ "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */
-	{ "write", "OK", write_regs }, /* Write registers */
+	{ "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
 	{ "sys_open", "OK", sw_rem_break }, /*remove breakpoint */
+	{ "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */
+	{ "write", "OK", write_regs, emul_reset }, /* Write registers */
 	{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
 	{ "g", "sys_open", NULL, check_single_step },
 	{ "sys_open", "OK", sw_break, }, /* set sw breakpoint */
 	{ "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
 	{ "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */
-	{ "", "" },
+	{ "", "", get_cont_catch, put_cont_catch },
 };
 
 /*
@@ -692,8 +775,8 @@
 	/* This callback is a put char which is when kgdb sends data to
 	 * this I/O module.
 	 */
-	if (ts.tst[ts.idx].get[0] == '\0' &&
-		ts.tst[ts.idx].put[0] == '\0') {
+	if (ts.tst[ts.idx].get[0] == '\0' && ts.tst[ts.idx].put[0] == '\0' &&
+	    !ts.tst[ts.idx].get_handler) {
 		eprintk("kgdbts: ERROR: beyond end of test on"
 			   " '%s' line %i\n", ts.name, ts.idx);
 		return 0;
@@ -906,6 +989,17 @@
 	if (ptr)
 		sstep_test = simple_strtol(ptr+1, NULL, 10);
 
+	/* All HW break point tests */
+	if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) {
+		hwbreaks_ok = 1;
+		v1printk("kgdbts:RUN hw breakpoint test\n");
+		run_breakpoint_test(1);
+		v1printk("kgdbts:RUN hw write breakpoint test\n");
+		run_hw_break_test(1);
+		v1printk("kgdbts:RUN access write breakpoint test\n");
+		run_hw_break_test(0);
+	}
+
 	/* required internal KGDB tests */
 	v1printk("kgdbts:RUN plant and detach test\n");
 	run_plant_and_detach_test(0);
@@ -923,35 +1017,11 @@
 
 	/* ===Optional tests=== */
 
-	/* All HW break point tests */
-	if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) {
-		hwbreaks_ok = 1;
-		v1printk("kgdbts:RUN hw breakpoint test\n");
-		run_breakpoint_test(1);
-		v1printk("kgdbts:RUN hw write breakpoint test\n");
-		run_hw_break_test(1);
-		v1printk("kgdbts:RUN access write breakpoint test\n");
-		run_hw_break_test(0);
-	}
-
 	if (nmi_sleep) {
 		v1printk("kgdbts:RUN NMI sleep %i seconds test\n", nmi_sleep);
 		run_nmi_sleep_test(nmi_sleep);
 	}
 
-#ifdef CONFIG_DEBUG_RODATA
-	/* Until there is an api to write to read-only text segments, use
-	 * HW breakpoints for the remainder of any tests, else print a
-	 * failure message if hw breakpoints do not work.
-	 */
-	if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) {
-		eprintk("kgdbts: HW breakpoints do not work,"
-			"skipping remaining tests\n");
-		return;
-	}
-	force_hwbrks = 1;
-#endif /* CONFIG_DEBUG_RODATA */
-
 	/* If the do_fork test is run it will be the last test that is
 	 * executed because a kernel thread will be spawned at the very
 	 * end to unregister the debug hooks.
diff -druN linux-libre-3.0.27-gnu/drivers/mmc/host/atmel-mci.c linux-libre-3.0.28-gnu/drivers/mmc/host/atmel-mci.c
--- linux-libre-3.0.27-gnu/drivers/mmc/host/atmel-mci.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/mmc/host/atmel-mci.c	2012-04-13 11:26:29.000000000 -0400
@@ -468,7 +468,14 @@
 static inline unsigned int ns_to_clocks(struct atmel_mci *host,
 					unsigned int ns)
 {
-	return (ns * (host->bus_hz / 1000000) + 999) / 1000;
+	/*
+	 * It is easier here to use us instead of ns for the timeout,
+	 * it prevents from overflows during calculation.
+	 */
+	unsigned int us = DIV_ROUND_UP(ns, 1000);
+
+	/* Maximum clock frequency is host->bus_hz/2 */
+	return us * (DIV_ROUND_UP(host->bus_hz, 2000000));
 }
 
 static void atmci_set_timeout(struct atmel_mci *host,
diff -druN linux-libre-3.0.27-gnu/drivers/mtd/devices/block2mtd.c linux-libre-3.0.28-gnu/drivers/mtd/devices/block2mtd.c
--- linux-libre-3.0.27-gnu/drivers/mtd/devices/block2mtd.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/mtd/devices/block2mtd.c	2012-04-13 11:26:29.000000000 -0400
@@ -284,6 +284,7 @@
 	dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
 	dev->mtd.erasesize = erase_size;
 	dev->mtd.writesize = 1;
+	dev->mtd.writebufsize = PAGE_SIZE;
 	dev->mtd.type = MTD_RAM;
 	dev->mtd.flags = MTD_CAP_RAM;
 	dev->mtd.erase = block2mtd_erase;
diff -druN linux-libre-3.0.27-gnu/drivers/mtd/devices/lart.c linux-libre-3.0.28-gnu/drivers/mtd/devices/lart.c
--- linux-libre-3.0.27-gnu/drivers/mtd/devices/lart.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/mtd/devices/lart.c	2012-04-13 11:26:29.000000000 -0400
@@ -636,6 +636,7 @@
    mtd.name = module_name;
    mtd.type = MTD_NORFLASH;
    mtd.writesize = 1;
+   mtd.writebufsize = 4;
    mtd.flags = MTD_CAP_NORFLASH;
    mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN;
    mtd.erasesize = FLASH_BLOCKSIZE_MAIN;
diff -druN linux-libre-3.0.27-gnu/drivers/mtd/devices/m25p80.c linux-libre-3.0.28-gnu/drivers/mtd/devices/m25p80.c
--- linux-libre-3.0.27-gnu/drivers/mtd/devices/m25p80.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/mtd/devices/m25p80.c	2012-04-13 11:26:29.000000000 -0400
@@ -930,6 +930,7 @@
 
 	flash->mtd.dev.parent = &spi->dev;
 	flash->page_size = info->page_size;
+	flash->mtd.writebufsize = flash->page_size;
 
 	if (info->addr_width)
 		flash->addr_width = info->addr_width;
diff -druN linux-libre-3.0.27-gnu/drivers/mtd/devices/sst25l.c linux-libre-3.0.28-gnu/drivers/mtd/devices/sst25l.c
--- linux-libre-3.0.27-gnu/drivers/mtd/devices/sst25l.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/mtd/devices/sst25l.c	2012-04-13 11:26:29.000000000 -0400
@@ -406,6 +406,7 @@
 	flash->mtd.flags	= MTD_CAP_NORFLASH;
 	flash->mtd.erasesize	= flash_info->erase_size;
 	flash->mtd.writesize	= flash_info->page_size;
+	flash->mtd.writebufsize	= flash_info->page_size;
 	flash->mtd.size		= flash_info->page_size * flash_info->nr_pages;
 	flash->mtd.erase	= sst25l_erase;
 	flash->mtd.read		= sst25l_read;
diff -druN linux-libre-3.0.27-gnu/drivers/net/usb/cdc_eem.c linux-libre-3.0.28-gnu/drivers/net/usb/cdc_eem.c
--- linux-libre-3.0.27-gnu/drivers/net/usb/cdc_eem.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/net/usb/cdc_eem.c	2012-04-13 11:26:29.000000000 -0400
@@ -93,6 +93,7 @@
 	/* no jumbogram (16K) support for now */
 
 	dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN;
+	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
 
 	return 0;
 }
diff -druN linux-libre-3.0.27-gnu/drivers/net/usb/zaurus.c linux-libre-3.0.28-gnu/drivers/net/usb/zaurus.c
--- linux-libre-3.0.27-gnu/drivers/net/usb/zaurus.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/net/usb/zaurus.c	2012-04-13 11:26:29.000000000 -0400
@@ -332,6 +332,11 @@
 	.driver_info = ZAURUS_PXA_INFO,
 },
 {
+	/* Motorola Rokr E6 */
+	USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6027, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &bogus_mdlm_info,
+}, {
 	/* Motorola MOTOMAGX phones */
 	USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM,
 			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
diff -druN linux-libre-3.0.27-gnu/drivers/platform/x86/acer-wmi.c linux-libre-3.0.28-gnu/drivers/platform/x86/acer-wmi.c
--- linux-libre-3.0.27-gnu/drivers/platform/x86/acer-wmi.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/platform/x86/acer-wmi.c	2012-04-13 11:26:29.000000000 -0400
@@ -689,6 +689,7 @@
 	{ "VPC2004", 0},
 	{ "IBM0068", 0},
 	{ "LEN0068", 0},
+	{ "SNY5001", 0},	/* sony-laptop in charge */
 	{ "", 0},
 };
 
diff -druN linux-libre-3.0.27-gnu/drivers/pnp/pnpacpi/core.c linux-libre-3.0.28-gnu/drivers/pnp/pnpacpi/core.c
--- linux-libre-3.0.27-gnu/drivers/pnp/pnpacpi/core.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/drivers/pnp/pnpacpi/core.c	2012-04-13 11:26:29.000000000 -0400
@@ -320,9 +320,14 @@
 {
 	struct acpi_device *acpi = to_acpi_device(dev);
 	struct pnp_dev *pnp = _pnp;
+	struct device *physical_device;
+
+	physical_device = acpi_get_physical_device(acpi->handle);
+	if (physical_device)
+		put_device(physical_device);
 
 	/* true means it matched */
-	return !acpi_get_physical_device(acpi->handle)
+	return !physical_device
 	    && compare_pnp_id(pnp->id, acpi_device_hid(acpi));
 }
 
diff -druN linux-libre-3.0.27-gnu/include/linux/kernel.h linux-libre-3.0.28-gnu/include/linux/kernel.h
--- linux-libre-3.0.27-gnu/include/linux/kernel.h	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/include/linux/kernel.h	2012-04-13 11:26:29.000000000 -0400
@@ -77,6 +77,19 @@
 }							\
 )
 
+/*
+ * Multiplies an integer by a fraction, while avoiding unnecessary
+ * overflow or loss of precision.
+ */
+#define mult_frac(x, numer, denom)(			\
+{							\
+	typeof(x) quot = (x) / (denom);			\
+	typeof(x) rem  = (x) % (denom);			\
+	(quot * (numer)) + ((rem * (numer)) / (denom));	\
+}							\
+)
+
+
 #define _RET_IP_		(unsigned long)__builtin_return_address(0)
 #define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
 
diff -druN linux-libre-3.0.27-gnu/include/linux/kgdb.h linux-libre-3.0.28-gnu/include/linux/kgdb.h
--- linux-libre-3.0.27-gnu/include/linux/kgdb.h	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/include/linux/kgdb.h	2012-04-13 11:26:29.000000000 -0400
@@ -63,7 +63,8 @@
 	BP_HARDWARE_BREAKPOINT,
 	BP_WRITE_WATCHPOINT,
 	BP_READ_WATCHPOINT,
-	BP_ACCESS_WATCHPOINT
+	BP_ACCESS_WATCHPOINT,
+	BP_POKE_BREAKPOINT,
 };
 
 enum kgdb_bpstate {
@@ -207,8 +208,8 @@
 
 /* Optional functions. */
 extern int kgdb_validate_break_address(unsigned long addr);
-extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr);
-extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle);
+extern int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt);
+extern int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt);
 
 /**
  *	kgdb_arch_late - Perform any architecture specific initalization.
diff -druN linux-libre-3.0.27-gnu/kernel/cred.c linux-libre-3.0.28-gnu/kernel/cred.c
--- linux-libre-3.0.27-gnu/kernel/cred.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/kernel/cred.c	2012-04-13 11:26:29.000000000 -0400
@@ -385,6 +385,8 @@
 	struct cred *new;
 	int ret;
 
+	p->replacement_session_keyring = NULL;
+
 	if (
 #ifdef CONFIG_KEYS
 		!p->cred->thread_keyring &&
diff -druN linux-libre-3.0.27-gnu/kernel/debug/debug_core.c linux-libre-3.0.28-gnu/kernel/debug/debug_core.c
--- linux-libre-3.0.27-gnu/kernel/debug/debug_core.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/kernel/debug/debug_core.c	2012-04-13 11:26:29.000000000 -0400
@@ -157,37 +157,39 @@
  * Weak aliases for breakpoint management,
  * can be overriden by architectures when needed:
  */
-int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
+int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 {
 	int err;
 
-	err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE);
+	err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+				BREAK_INSTR_SIZE);
 	if (err)
 		return err;
-
-	return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr,
-				  BREAK_INSTR_SIZE);
+	err = probe_kernel_write((char *)bpt->bpt_addr,
+				 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
+	return err;
 }
 
-int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
+int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
 {
-	return probe_kernel_write((char *)addr,
-				  (char *)bundle, BREAK_INSTR_SIZE);
+	return probe_kernel_write((char *)bpt->bpt_addr,
+				  (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
 }
 
 int __weak kgdb_validate_break_address(unsigned long addr)
 {
-	char tmp_variable[BREAK_INSTR_SIZE];
+	struct kgdb_bkpt tmp;
 	int err;
-	/* Validate setting the breakpoint and then removing it.  In the
+	/* Validate setting the breakpoint and then removing it.  If the
 	 * remove fails, the kernel needs to emit a bad message because we
 	 * are deep trouble not being able to put things back the way we
 	 * found them.
 	 */
-	err = kgdb_arch_set_breakpoint(addr, tmp_variable);
+	tmp.bpt_addr = addr;
+	err = kgdb_arch_set_breakpoint(&tmp);
 	if (err)
 		return err;
-	err = kgdb_arch_remove_breakpoint(addr, tmp_variable);
+	err = kgdb_arch_remove_breakpoint(&tmp);
 	if (err)
 		printk(KERN_ERR "KGDB: Critical breakpoint error, kernel "
 		   "memory destroyed at: %lx", addr);
@@ -231,7 +233,6 @@
  */
 int dbg_activate_sw_breakpoints(void)
 {
-	unsigned long addr;
 	int error;
 	int ret = 0;
 	int i;
@@ -240,16 +241,15 @@
 		if (kgdb_break[i].state != BP_SET)
 			continue;
 
-		addr = kgdb_break[i].bpt_addr;
-		error = kgdb_arch_set_breakpoint(addr,
-				kgdb_break[i].saved_instr);
+		error = kgdb_arch_set_breakpoint(&kgdb_break[i]);
 		if (error) {
 			ret = error;
-			printk(KERN_INFO "KGDB: BP install failed: %lx", addr);
+			printk(KERN_INFO "KGDB: BP install failed: %lx",
+			       kgdb_break[i].bpt_addr);
 			continue;
 		}
 
-		kgdb_flush_swbreak_addr(addr);
+		kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
 		kgdb_break[i].state = BP_ACTIVE;
 	}
 	return ret;
@@ -298,7 +298,6 @@
 
 int dbg_deactivate_sw_breakpoints(void)
 {
-	unsigned long addr;
 	int error;
 	int ret = 0;
 	int i;
@@ -306,15 +305,14 @@
 	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
 		if (kgdb_break[i].state != BP_ACTIVE)
 			continue;
-		addr = kgdb_break[i].bpt_addr;
-		error = kgdb_arch_remove_breakpoint(addr,
-					kgdb_break[i].saved_instr);
+		error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
 		if (error) {
-			printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr);
+			printk(KERN_INFO "KGDB: BP remove failed: %lx\n",
+			       kgdb_break[i].bpt_addr);
 			ret = error;
 		}
 
-		kgdb_flush_swbreak_addr(addr);
+		kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
 		kgdb_break[i].state = BP_SET;
 	}
 	return ret;
@@ -348,7 +346,6 @@
 
 int dbg_remove_all_break(void)
 {
-	unsigned long addr;
 	int error;
 	int i;
 
@@ -356,12 +353,10 @@
 	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
 		if (kgdb_break[i].state != BP_ACTIVE)
 			goto setundefined;
-		addr = kgdb_break[i].bpt_addr;
-		error = kgdb_arch_remove_breakpoint(addr,
-				kgdb_break[i].saved_instr);
+		error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
 		if (error)
 			printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n",
-			   addr);
+			       kgdb_break[i].bpt_addr);
 setundefined:
 		kgdb_break[i].state = BP_UNDEFINED;
 	}
diff -druN linux-libre-3.0.27-gnu/kernel/irq/migration.c linux-libre-3.0.28-gnu/kernel/irq/migration.c
--- linux-libre-3.0.27-gnu/kernel/irq/migration.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/kernel/irq/migration.c	2012-04-13 11:26:29.000000000 -0400
@@ -43,12 +43,16 @@
 	 * masking the irqs.
 	 */
 	if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask)
-		   < nr_cpu_ids))
-		if (!chip->irq_set_affinity(&desc->irq_data,
-					    desc->pending_mask, false)) {
+		   < nr_cpu_ids)) {
+		int ret = chip->irq_set_affinity(&desc->irq_data,
+						 desc->pending_mask, false);
+		switch (ret) {
+		case IRQ_SET_MASK_OK:
 			cpumask_copy(desc->irq_data.affinity, desc->pending_mask);
+		case IRQ_SET_MASK_OK_NOCOPY:
 			irq_set_thread_affinity(desc);
 		}
+	}
 
 	cpumask_clear(desc->pending_mask);
 }
diff -druN linux-libre-3.0.27-gnu/kernel/sysctl.c linux-libre-3.0.28-gnu/kernel/sysctl.c
--- linux-libre-3.0.27-gnu/kernel/sysctl.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/kernel/sysctl.c	2012-04-13 11:26:29.000000000 -0400
@@ -172,7 +172,7 @@
 #endif
 
 #ifdef CONFIG_PRINTK
-static int proc_dmesg_restrict(struct ctl_table *table, int write,
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
 				void __user *buffer, size_t *lenp, loff_t *ppos);
 #endif
 
@@ -709,7 +709,7 @@
 		.data		= &dmesg_restrict,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec_minmax,
+		.proc_handler	= proc_dointvec_minmax_sysadmin,
 		.extra1		= &zero,
 		.extra2		= &one,
 	},
@@ -718,7 +718,7 @@
 		.data		= &kptr_restrict,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dmesg_restrict,
+		.proc_handler	= proc_dointvec_minmax_sysadmin,
 		.extra1		= &zero,
 		.extra2		= &two,
 	},
@@ -2416,7 +2416,7 @@
 }
 
 #ifdef CONFIG_PRINTK
-static int proc_dmesg_restrict(struct ctl_table *table, int write,
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
 				void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	if (write && !capable(CAP_SYS_ADMIN))
diff -druN linux-libre-3.0.27-gnu/kernel/trace/trace_entries.h linux-libre-3.0.28-gnu/kernel/trace/trace_entries.h
--- linux-libre-3.0.27-gnu/kernel/trace/trace_entries.h	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/kernel/trace/trace_entries.h	2012-04-13 11:26:29.000000000 -0400
@@ -156,6 +156,12 @@
 
 #define FTRACE_STACK_ENTRIES	8
 
+#ifndef CONFIG_64BIT
+# define IP_FMT "%08lx"
+#else
+# define IP_FMT "%016lx"
+#endif
+
 FTRACE_ENTRY(kernel_stack, stack_entry,
 
 	TRACE_STACK,
@@ -164,8 +170,9 @@
 		__array(	unsigned long,	caller, FTRACE_STACK_ENTRIES	)
 	),
 
-	F_printk("\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n"
-		 "\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n",
+	F_printk("\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n"
+		 "\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n"
+		 "\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n",
 		 __entry->caller[0], __entry->caller[1], __entry->caller[2],
 		 __entry->caller[3], __entry->caller[4], __entry->caller[5],
 		 __entry->caller[6], __entry->caller[7])
@@ -180,8 +187,9 @@
 		__array(	unsigned long,	caller, FTRACE_STACK_ENTRIES	)
 	),
 
-	F_printk("\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n"
-		 "\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n",
+	F_printk("\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n"
+		 "\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n"
+		 "\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n",
 		 __entry->caller[0], __entry->caller[1], __entry->caller[2],
 		 __entry->caller[3], __entry->caller[4], __entry->caller[5],
 		 __entry->caller[6], __entry->caller[7])
diff -druN linux-libre-3.0.27-gnu/kernel/trace/trace_export.c linux-libre-3.0.28-gnu/kernel/trace/trace_export.c
--- linux-libre-3.0.27-gnu/kernel/trace/trace_export.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/kernel/trace/trace_export.c	2012-04-13 11:26:29.000000000 -0400
@@ -150,7 +150,7 @@
 #define __dynamic_array(type, item)
 
 #undef F_printk
-#define F_printk(fmt, args...) #fmt ", "  __stringify(args)
+#define F_printk(fmt, args...) __stringify(fmt) ", "  __stringify(args)
 
 #undef FTRACE_ENTRY
 #define FTRACE_ENTRY(call, struct_name, etype, tstruct, print)		\
diff -druN linux-libre-3.0.27-gnu/Makefile linux-libre-3.0.28-gnu/Makefile
--- linux-libre-3.0.27-gnu/Makefile	2012-04-03 21:43:57.000000000 -0400
+++ linux-libre-3.0.28-gnu/Makefile	2012-04-14 00:03:12.000000000 -0400
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 0
-SUBLEVEL = 27
+SUBLEVEL = 28
 EXTRAVERSION =-gnu
 NAME = Sneaky Weasel
 
diff -druN linux-libre-3.0.27-gnu/net/bluetooth/hci_conn.c linux-libre-3.0.28-gnu/net/bluetooth/hci_conn.c
--- linux-libre-3.0.27-gnu/net/bluetooth/hci_conn.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/net/bluetooth/hci_conn.c	2012-04-13 11:26:29.000000000 -0400
@@ -548,6 +548,10 @@
 
 	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
 		struct hci_cp_auth_requested cp;
+
+		/* encrypt must be pending if auth is also pending */
+		set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
+
 		cp.handle = cpu_to_le16(conn->handle);
 		hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
 							sizeof(cp), &cp);
diff -druN linux-libre-3.0.27-gnu/net/mac80211/agg-rx.c linux-libre-3.0.28-gnu/net/mac80211/agg-rx.c
--- linux-libre-3.0.27-gnu/net/mac80211/agg-rx.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/net/mac80211/agg-rx.c	2012-04-13 11:26:29.000000000 -0400
@@ -48,6 +48,8 @@
 		container_of(h, struct tid_ampdu_rx, rcu_head);
 	int i;
 
+	del_timer_sync(&tid_rx->reorder_timer);
+
 	for (i = 0; i < tid_rx->buf_size; i++)
 		dev_kfree_skb(tid_rx->reorder_buf[i]);
 	kfree(tid_rx->reorder_buf);
@@ -87,7 +89,6 @@
 				     tid, 0, reason);
 
 	del_timer_sync(&tid_rx->session_timer);
-	del_timer_sync(&tid_rx->reorder_timer);
 
 	call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
 }
diff -druN linux-libre-3.0.27-gnu/net/rose/rose_dev.c linux-libre-3.0.28-gnu/net/rose/rose_dev.c
--- linux-libre-3.0.27-gnu/net/rose/rose_dev.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/net/rose/rose_dev.c	2012-04-13 11:26:29.000000000 -0400
@@ -96,11 +96,11 @@
 	struct sockaddr *sa = addr;
 	int err;
 
-	if (!memcpy(dev->dev_addr, sa->sa_data, dev->addr_len))
+	if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len))
 		return 0;
 
 	if (dev->flags & IFF_UP) {
-		err = rose_add_loopback_node((rose_address *)dev->dev_addr);
+		err = rose_add_loopback_node((rose_address *)sa->sa_data);
 		if (err)
 			return err;
 
diff -druN linux-libre-3.0.27-gnu/scripts/mod/modpost.c linux-libre-3.0.28-gnu/scripts/mod/modpost.c
--- linux-libre-3.0.27-gnu/scripts/mod/modpost.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/scripts/mod/modpost.c	2012-04-13 11:26:29.000000000 -0400
@@ -132,8 +132,10 @@
 	/* strip trailing .o */
 	s = strrchr(p, '.');
 	if (s != NULL)
-		if (strcmp(s, ".o") == 0)
+		if (strcmp(s, ".o") == 0) {
 			*s = '\0';
+			mod->is_dot_o = 1;
+		}
 
 	/* add to list */
 	mod->name = p;
@@ -254,6 +256,28 @@
 	return export_unknown;
 }
 
+static const char *sec_name(struct elf_info *elf, int secindex);
+
+#define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0)
+
+static enum export export_from_secname(struct elf_info *elf, unsigned int sec)
+{
+	const char *secname = sec_name(elf, sec);
+
+	if (strstarts(secname, "___ksymtab+"))
+		return export_plain;
+	else if (strstarts(secname, "___ksymtab_unused+"))
+		return export_unused;
+	else if (strstarts(secname, "___ksymtab_gpl+"))
+		return export_gpl;
+	else if (strstarts(secname, "___ksymtab_unused_gpl+"))
+		return export_unused_gpl;
+	else if (strstarts(secname, "___ksymtab_gpl_future+"))
+		return export_gpl_future;
+	else
+		return export_unknown;
+}
+
 static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
 {
 	if (sec == elf->export_sec)
@@ -563,7 +587,13 @@
 			       Elf_Sym *sym, const char *symname)
 {
 	unsigned int crc;
-	enum export export = export_from_sec(info, get_secindex(info, sym));
+	enum export export;
+
+	if ((!is_vmlinux(mod->name) || mod->is_dot_o) &&
+	    strncmp(symname, "__ksymtab", 9) == 0)
+		export = export_from_secname(info, get_secindex(info, sym));
+	else
+		export = export_from_sec(info, get_secindex(info, sym));
 
 	switch (sym->st_shndx) {
 	case SHN_COMMON:
@@ -822,7 +852,7 @@
 
 #define ALL_INIT_DATA_SECTIONS \
 	".init.setup$", ".init.rodata$", \
-	".devinit.rodata$", ".cpuinit.rodata$", ".meminit.rodata$" \
+	".devinit.rodata$", ".cpuinit.rodata$", ".meminit.rodata$", \
 	".init.data$", ".devinit.data$", ".cpuinit.data$", ".meminit.data$"
 #define ALL_EXIT_DATA_SECTIONS \
 	".exit.data$", ".devexit.data$", ".cpuexit.data$", ".memexit.data$"
diff -druN linux-libre-3.0.27-gnu/scripts/mod/modpost.h linux-libre-3.0.28-gnu/scripts/mod/modpost.h
--- linux-libre-3.0.27-gnu/scripts/mod/modpost.h	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/scripts/mod/modpost.h	2012-04-13 11:26:29.000000000 -0400
@@ -113,6 +113,7 @@
 	int has_cleanup;
 	struct buffer dev_table_buf;
 	char	     srcversion[25];
+	int is_dot_o;
 };
 
 struct elf_info {
diff -druN linux-libre-3.0.27-gnu/security/tomoyo/mount.c linux-libre-3.0.28-gnu/security/tomoyo/mount.c
--- linux-libre-3.0.27-gnu/security/tomoyo/mount.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/security/tomoyo/mount.c	2012-04-13 11:26:29.000000000 -0400
@@ -205,30 +205,32 @@
 	if (flags & MS_REMOUNT) {
 		type = TOMOYO_MOUNT_REMOUNT_KEYWORD;
 		flags &= ~MS_REMOUNT;
-	}
-	if (flags & MS_MOVE) {
-		type = TOMOYO_MOUNT_MOVE_KEYWORD;
-		flags &= ~MS_MOVE;
-	}
-	if (flags & MS_BIND) {
+	} else if (flags & MS_BIND) {
 		type = TOMOYO_MOUNT_BIND_KEYWORD;
 		flags &= ~MS_BIND;
-	}
-	if (flags & MS_UNBINDABLE) {
-		type = TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD;
-		flags &= ~MS_UNBINDABLE;
-	}
-	if (flags & MS_PRIVATE) {
+	} else if (flags & MS_SHARED) {
+		if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
+			return -EINVAL;
+		type = TOMOYO_MOUNT_MAKE_SHARED_KEYWORD;
+		flags &= ~MS_SHARED;
+	} else if (flags & MS_PRIVATE) {
+		if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE))
+			return -EINVAL;
 		type = TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD;
 		flags &= ~MS_PRIVATE;
-	}
-	if (flags & MS_SLAVE) {
+	} else if (flags & MS_SLAVE) {
+		if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE))
+			return -EINVAL;
 		type = TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD;
 		flags &= ~MS_SLAVE;
-	}
-	if (flags & MS_SHARED) {
-		type = TOMOYO_MOUNT_MAKE_SHARED_KEYWORD;
-		flags &= ~MS_SHARED;
+	} else if (flags & MS_UNBINDABLE) {
+		if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
+			return -EINVAL;
+		type = TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD;
+		flags &= ~MS_UNBINDABLE;
+	} else if (flags & MS_MOVE) {
+		type = TOMOYO_MOUNT_MOVE_KEYWORD;
+		flags &= ~MS_MOVE;
 	}
 	if (!type)
 		type = "<NULL>";
diff -druN linux-libre-3.0.27-gnu/sound/soc/codecs/ak4642.c linux-libre-3.0.28-gnu/sound/soc/codecs/ak4642.c
--- linux-libre-3.0.27-gnu/sound/soc/codecs/ak4642.c	2012-04-02 12:28:56.000000000 -0400
+++ linux-libre-3.0.28-gnu/sound/soc/codecs/ak4642.c	2012-04-13 11:26:29.000000000 -0400
@@ -143,7 +143,7 @@
  * min : 0xFE : -115.0 dB
  * mute: 0xFF
  */
-static const DECLARE_TLV_DB_SCALE(out_tlv, -11500, 50, 1);
+static const DECLARE_TLV_DB_SCALE(out_tlv, -11550, 50, 1);
 
 static const struct snd_kcontrol_new ak4642_snd_controls[] = {
 
