linux-moblin: Add 2.6.31.5

Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
This commit is contained in:
Richard Purdie 2010-01-26 15:59:18 +00:00
parent 3a32c2c6e9
commit 684d263e75
35 changed files with 73102 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,38 @@
diff --git a/drivers/staging/rt2860/rt_linux.c b/drivers/staging/rt2860/rt_linux.c
index 80176b2..fc682be 100644
--- a/drivers/staging/rt2860/rt_linux.c
+++ b/drivers/staging/rt2860/rt_linux.c
@@ -27,7 +27,7 @@
#include "rt_config.h"
-ULONG RTDebugLevel = RT_DEBUG_ERROR;
+ULONG RTDebugLevel = RT_DEBUG_OFF;
BUILD_TIMER_FUNCTION(MlmePeriodicExec);
BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout);
diff --git a/drivers/staging/rt2860/rt_linux.h b/drivers/staging/rt2860/rt_linux.h
index 25b53ac..56ac9ac 100644
--- a/drivers/staging/rt2860/rt_linux.h
+++ b/drivers/staging/rt2860/rt_linux.h
@@ -375,18 +375,9 @@ extern ULONG RTDebugLevel;
#define DBGPRINT(Level, Fmt) DBGPRINT_RAW(Level, Fmt)
+#define DBGPRINT_ERR(Fmt)
-#define DBGPRINT_ERR(Fmt) \
-{ \
- printk("ERROR!!! "); \
- printk Fmt; \
-}
-
-#define DBGPRINT_S(Status, Fmt) \
-{ \
- printk Fmt; \
-}
-
+#define DBGPRINT_S(Status, Fmt)
#else
#define DBGPRINT(Level, Fmt)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,142 @@
From e412ebbb8cea2aaf32f689ffc630b57cfe13bde5 Mon Sep 17 00:00:00 2001
From: Alan Olsen <alanx.r.olsen@intel.com>
Date: Tue, 21 Jul 2009 13:14:25 -0700
Subject: [PATCH] linux-2.6-build-nonintconfig.patch
Signed-off-by: Alan Olsen <alanx.r.olsen@intel.com>
---
scripts/kconfig/Makefile | 5 +++++
scripts/kconfig/conf.c | 36 ++++++++++++++++++++++++++++++++----
2 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 5ddf8be..a4365db 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -28,6 +28,11 @@ oldconfig: $(obj)/conf
silentoldconfig: $(obj)/conf
$< -s $(Kconfig)
+nonint_oldconfig: $(obj)/conf
+ $< -b $(Kconfig)
+loose_nonint_oldconfig: $(obj)/conf
+ $< -B $(Kconfig)
+
# Create new linux.pot file
# Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files
# The symlink is used to repair a deficiency in arch/um
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 3baaaec..2a81742 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -23,6 +23,8 @@ enum {
ask_all,
ask_new,
ask_silent,
+ dont_ask,
+ dont_ask_dont_tell,
set_default,
set_yes,
set_mod,
@@ -40,6 +42,8 @@ static struct menu *rootEntry;
static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
+static int return_value = 0;
+
static const char *get_help(struct menu *menu)
{
if (menu_has_help(menu))
@@ -360,7 +364,10 @@ static void conf(struct menu *menu)
switch (prop->type) {
case P_MENU:
- if (input_mode == ask_silent && rootEntry != menu) {
+ if ((input_mode == ask_silent ||
+ input_mode == dont_ask ||
+ input_mode == dont_ask_dont_tell) &&
+ rootEntry != menu) {
check_conf(menu);
return;
}
@@ -418,12 +425,21 @@ static void check_conf(struct menu *menu)
if (sym && !sym_has_value(sym)) {
if (sym_is_changable(sym) ||
(sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
+ if (input_mode == dont_ask ||
+ input_mode == dont_ask_dont_tell) {
+ if (input_mode == dont_ask &&
+ sym->name && !sym_is_choice_value(sym)) {
+ fprintf(stderr,"CONFIG_%s\n",sym->name);
+ ++return_value;
+ }
+ } else {
if (!conf_cnt++)
printf(_("*\n* Restart config...\n*\n"));
rootEntry = menu_get_parent_menu(menu);
conf(rootEntry);
}
}
+ }
for (child = menu->list; child; child = child->next)
check_conf(child);
@@ -439,7 +455,7 @@ int main(int ac, char **av)
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) {
+ while ((opt = getopt(ac, av, "osbBdD:nmyrh")) != -1) {
switch (opt) {
case 'o':
input_mode = ask_silent;
@@ -448,6 +464,12 @@ int main(int ac, char **av)
input_mode = ask_silent;
sync_kconfig = 1;
break;
+ case 'b':
+ input_mode = dont_ask;
+ break;
+ case 'B':
+ input_mode = dont_ask_dont_tell;
+ break;
case 'd':
input_mode = set_default;
break;
@@ -525,6 +547,8 @@ int main(int ac, char **av)
case ask_silent:
case ask_all:
case ask_new:
+ case dont_ask:
+ case dont_ask_dont_tell:
conf_read(NULL);
break;
case set_no:
@@ -586,12 +610,16 @@ int main(int ac, char **av)
conf(&rootmenu);
input_mode = ask_silent;
/* fall through */
+ case dont_ask:
+ case dont_ask_dont_tell:
case ask_silent:
/* Update until a loop caused no more changes */
do {
conf_cnt = 0;
check_conf(&rootmenu);
- } while (conf_cnt);
+ } while (conf_cnt &&
+ (input_mode != dont_ask &&
+ input_mode != dont_ask_dont_tell));
break;
}
@@ -613,5 +641,5 @@ int main(int ac, char **av)
exit(1);
}
}
- return 0;
+ return return_value;
}
--
1.6.0.6

View File

@ -0,0 +1,61 @@
commit 0f592e33934bf6108e33e34f00b425f98ee833ef
Author: Matthew Garrett <mjg@redhat.com>
Date: Wed Jul 8 19:04:23 2009 +0100
usb: Allow drivers to enable USB autosuspend on a per-device basis
USB autosuspend is currently only enabled by default for hubs. On other
hardware the decision is made by userspace. This is unnecessary in cases
where we know that the hardware supports autosuspend, so this patch adds
a function to allow drivers to enable it at probe time.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 69e5773..6e81caa 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1560,6 +1560,21 @@ void usb_autopm_put_interface_async(struct usb_interface *intf)
EXPORT_SYMBOL_GPL(usb_autopm_put_interface_async);
/**
+ * usb_device_autosuspend_enable - enable autosuspend on a device
+ * @udev: the usb_device to be autosuspended
+ *
+ * This routine should be called by an interface driver when it knows that
+ * the device in question supports USB autosuspend.
+ *
+ */
+void usb_device_autosuspend_enable(struct usb_device *udev)
+{
+ udev->autosuspend_disabled = 0;
+ udev->autoresume_disabled = 0;
+}
+EXPORT_SYMBOL_GPL(usb_device_autosuspend_enable);
+
+/**
* usb_autopm_get_interface - increment a USB interface's PM-usage counter
* @intf: the usb_interface whose counter should be incremented
*
diff --git a/include/linux/usb.h b/include/linux/usb.h
index b1e3c2f..61bddbe 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -543,6 +543,7 @@ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
/* USB autosuspend and autoresume */
#ifdef CONFIG_USB_SUSPEND
+extern void usb_device_autosuspend_enable(struct usb_device *udev);
extern int usb_autopm_set_interface(struct usb_interface *intf);
extern int usb_autopm_get_interface(struct usb_interface *intf);
extern void usb_autopm_put_interface(struct usb_interface *intf);
@@ -568,6 +569,9 @@ static inline void usb_mark_last_busy(struct usb_device *udev)
#else
+static inline void usb_device_autosuspend_enable(struct usb_device *udev)
+{ }
+
static inline int usb_autopm_set_interface(struct usb_interface *intf)
{ return 0; }

View File

@ -0,0 +1,19 @@
commit 9d4c919bcfa794c054cc33155c7e3c53ac2c5684
Author: Matthew Garrett <mjg@redhat.com>
Date: Sun Jul 19 02:24:49 2009 +0100
Enable autosuspend on UVC by default
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 89927b7..8de516b 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -1647,6 +1647,8 @@ static int uvc_probe(struct usb_interface *intf,
"supported.\n", ret);
}
+ usb_device_autosuspend_enable(udev);
+
uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");
return 0;

View File

@ -0,0 +1,47 @@
From dce8113d033975f56630cf6d2a6a908cfb66059d Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <arjan@linux.intel.com>
Date: Sun, 20 Jul 2008 13:12:16 -0700
Subject: [PATCH] fastboot: remove "wait for all devices before mounting root" delay
In the non-initrd case, we wait for all devices to finish their
probing before we try to mount the rootfs.
In practice, this means that we end up waiting 2 extra seconds for
the PS/2 mouse probing even though the root holding device has been
ready since a long time.
The previous two patches in this series made the RAID autodetect code
do it's own "wait for probing to be done" code, and added
"wait and retry" functionality in case the root device isn't actually
available.
These two changes should make it safe to remove the delay itself,
and this patch does this. On my test laptop, this reduces the boot time
by 2 seconds (kernel time goes from 3.9 to 1.9 seconds).
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
---
---
init/do_mounts.c | 3 +++
1 file changed, 3 insertions(+)
Index: linux-2.6.29/init/do_mounts.c
===================================================================
--- linux-2.6.29.orig/init/do_mounts.c
+++ linux-2.6.29/init/do_mounts.c
@@ -370,6 +370,7 @@ void __init prepare_namespace(void)
ssleep(root_delay);
}
+#if 0
/*
* wait for the known devices to complete their probing
*
@@ -378,6 +379,8 @@ void __init prepare_namespace(void)
* for the touchpad of a laptop to initialize.
*/
wait_for_device_probe();
+#endif
+ async_synchronize_full();
md_run_setup();

View File

@ -0,0 +1,25 @@
From 0143f8eb8afcaccba5a78196fb3db4361e0097a7 Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <arjan@linux.intel.com>
Date: Mon, 9 Feb 2009 21:25:32 -0800
Subject: [PATCH] jbd: longer commit interval
... 5 seconds is rather harsh on ssd's..
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
---
include/linux/jbd.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: linux-2.6.29/include/linux/jbd.h
===================================================================
--- linux-2.6.29.orig/include/linux/jbd.h
+++ linux-2.6.29/include/linux/jbd.h
@@ -46,7 +46,7 @@
/*
* The default maximum commit age, in seconds.
*/
-#define JBD_DEFAULT_MAX_COMMIT_AGE 5
+#define JBD_DEFAULT_MAX_COMMIT_AGE 15
#ifdef CONFIG_JBD_DEBUG
/*

View File

@ -0,0 +1,38 @@
---
drivers/Makefile | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
Index: linux-2.6.29/drivers/Makefile
===================================================================
--- linux-2.6.29.orig/drivers/Makefile
+++ linux-2.6.29/drivers/Makefile
@@ -25,15 +25,8 @@ obj-$(CONFIG_REGULATOR) += regulator/
# default.
obj-y += char/
-# gpu/ comes after char for AGP vs DRM startup
-obj-y += gpu/
-
obj-$(CONFIG_CONNECTOR) += connector/
-# i810fb and intelfb depend on char/agp/
-obj-$(CONFIG_FB_I810) += video/i810/
-obj-$(CONFIG_FB_INTEL) += video/intelfb/
-
obj-y += serial/
obj-$(CONFIG_PARPORT) += parport/
obj-y += base/ block/ misc/ mfd/ media/
@@ -43,6 +36,13 @@ obj-$(CONFIG_IDE) += ide/
obj-$(CONFIG_SCSI) += scsi/
obj-$(CONFIG_ATA) += ata/
obj-y += net/
+
+# gpu/ comes after char for AGP vs DRM startup
+obj-y += gpu/
+# i810fb and intelfb depend on char/agp/
+obj-$(CONFIG_FB_I810) += video/i810/
+obj-$(CONFIG_FB_INTEL) += video/intelfb/
+
obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_FUSION) += message/
obj-$(CONFIG_FIREWIRE) += firewire/

View File

@ -0,0 +1,33 @@
--- vanilla-2.6.31-rc4/drivers/gpu/drm/i915/intel_lvds.c~ 2009-07-31 11:23:05.000000000 -0700
+++ vanilla-2.6.31-rc4/drivers/gpu/drm/i915/intel_lvds.c 2009-07-31 11:23:05.000000000 -0700
@@ -111,19 +111,12 @@ static void intel_lvds_set_power(struct
if (on) {
I915_WRITE(ctl_reg, I915_READ(ctl_reg) |
POWER_TARGET_ON);
- do {
- pp_status = I915_READ(status_reg);
- } while ((pp_status & PP_ON) == 0);
-
intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle);
} else {
intel_lvds_set_backlight(dev, 0);
I915_WRITE(ctl_reg, I915_READ(ctl_reg) &
~POWER_TARGET_ON);
- do {
- pp_status = I915_READ(status_reg);
- } while (pp_status & PP_ON);
}
}
--- linux-2.6.31/drivers/gpu/drm/i915/intel_lvds.c~ 2009-10-11 10:13:38.000000000 -0700
+++ linux-2.6.31/drivers/gpu/drm/i915/intel_lvds.c 2009-10-11 10:13:38.000000000 -0700
@@ -98,7 +98,7 @@
static void intel_lvds_set_power(struct drm_device *dev, bool on)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 pp_status, ctl_reg, status_reg;
+ u32 ctl_reg, status_reg;
if (IS_IGDNG(dev)) {
ctl_reg = PCH_PP_CONTROL;

View File

@ -0,0 +1,58 @@
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 004541c..b218780 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -81,6 +81,7 @@ struct intel_output {
int type;
struct i2c_adapter *i2c_bus;
struct i2c_adapter *ddc_bus;
+ struct edid *edid;
bool load_detect_temp;
bool needs_tv_clock;
void *dev_priv;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 9ab38ef..9fba800 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -657,6 +657,7 @@ static void intel_lvds_destroy(struct drm_connector *connector)
intel_i2c_destroy(intel_output->ddc_bus);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
+ kfree(intel_output->edid);
kfree(connector);
}
@@ -1017,5 +1018,6 @@ failed:
if (intel_output->ddc_bus)
intel_i2c_destroy(intel_output->ddc_bus);
drm_connector_cleanup(connector);
+ kfree(intel_output->edid);
kfree(intel_output);
}
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
index 67e2f46..5ac537f 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -74,6 +74,10 @@ int intel_ddc_get_modes(struct intel_output *intel_output)
int ret = 0;
intel_i2c_quirk_set(intel_output->base.dev, true);
+ if (intel_output->edid && intel_output->type == INTEL_OUTPUT_LVDS) {
+ printk(KERN_INFO "Skipping EDID probe due to cached edid\n");
+ return ret;
+ }
edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus);
intel_i2c_quirk_set(intel_output->base.dev, false);
if (edid) {
@@ -81,7 +85,10 @@ int intel_ddc_get_modes(struct intel_output *intel_output)
edid);
ret = drm_add_edid_modes(&intel_output->base, edid);
intel_output->base.display_info.raw_edid = NULL;
- kfree(edid);
+ if (intel_output->type == INTEL_OUTPUT_LVDS)
+ intel_output->edid = edid;
+ else
+ kfree(edid);
}
return ret;

View File

@ -0,0 +1,118 @@
Index: b/drivers/gpu/drm/drm_crtc_helper.c
===================================================================
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -29,6 +29,8 @@
* Jesse Barnes <jesse.barnes@intel.com>
*/
+#include <linux/async.h>
+
#include "drmP.h"
#include "drm_crtc.h"
#include "drm_crtc_helper.h"
@@ -62,6 +64,8 @@ static void drm_mode_validate_flag(struc
return;
}
+LIST_HEAD(drm_async_list);
+
/**
* drm_helper_probe_connector_modes - get complete set of display modes
* @dev: DRM device
@@ -916,6 +920,7 @@ bool drm_helper_plugged_event(struct drm
/* FIXME: send hotplug event */
return true;
}
+
/**
* drm_initial_config - setup a sane initial connector configuration
* @dev: DRM device
@@ -953,13 +958,26 @@ bool drm_helper_initial_config(struct dr
drm_setup_crtcs(dev);
- /* alert the driver fb layer */
dev->mode_config.funcs->fb_changed(dev);
-
return 0;
}
EXPORT_SYMBOL(drm_helper_initial_config);
+static void drm_helper_initial_config_helper(void *ptr, async_cookie_t cookie)
+{
+ struct drm_device *dev = ptr;
+ drm_helper_initial_config(dev);
+}
+
+void drm_helper_initial_config_async(struct drm_device *dev)
+{
+ async_schedule_domain(drm_helper_initial_config_helper,
+ dev, &drm_async_list);
+}
+EXPORT_SYMBOL(drm_helper_initial_config_async);
+
+
+
static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
{
int dpms = DRM_MODE_DPMS_OFF;
Index: b/drivers/gpu/drm/drm_drv.c
===================================================================
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -49,6 +49,7 @@
#include <linux/debugfs.h>
#include "drmP.h"
#include "drm_core.h"
+#include <linux/async.h>
static int drm_version(struct drm_device *dev, void *data,
@@ -290,6 +291,9 @@ void drm_exit(struct drm_driver *driver)
struct drm_device *dev, *tmp;
DRM_DEBUG("\n");
+ /* make sure all async DRM operations are finished */
+ async_synchronize_full_domain(&drm_async_list);
+
if (driver->driver_features & DRIVER_MODESET) {
pci_unregister_driver(&driver->pci_driver);
} else {
Index: b/include/drm/drmP.h
===================================================================
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -328,6 +328,7 @@ struct drm_vma_entry {
pid_t pid;
};
+extern struct list_head drm_async_list;
/**
* DMA buffer.
*/
Index: b/include/drm/drm_crtc_helper.h
===================================================================
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -92,6 +92,7 @@ extern int drm_helper_probe_single_conne
extern void drm_helper_disable_unused_functions(struct drm_device *dev);
extern int drm_helper_hotplug_stage_two(struct drm_device *dev);
extern bool drm_helper_initial_config(struct drm_device *dev);
+extern void drm_helper_initial_config_async(struct drm_device *dev);
extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
struct drm_display_mode *mode,
Index: b/drivers/gpu/drm/i915/i915_dma.c
===================================================================
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1045,7 +1045,7 @@ static int i915_load_modeset_init(struct
intel_modeset_init(dev);
- drm_helper_initial_config(dev);
+ drm_helper_initial_config_async(dev);
return 0;

View File

@ -0,0 +1,22 @@
From: Arjan van de Ven <arjan@linux.intel.com>
Date: Fri, 23 Jan 2009
Small fix changing error msg to info msg in acer wmi driver
---
---
drivers/platform/x86/acer-wmi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: linux-2.6.29/drivers/platform/x86/acer-wmi.c
===================================================================
--- linux-2.6.29.orig/drivers/platform/x86/acer-wmi.c
+++ linux-2.6.29/drivers/platform/x86/acer-wmi.c
@@ -1290,7 +1290,7 @@ static int __init acer_wmi_init(void)
AMW0_find_mailled();
if (!interface) {
- printk(ACER_ERR "No or unsupported WMI interface, unable to "
+ printk(ACER_INFO "No or unsupported WMI interface, unable to "
"load\n");
return -ENODEV;
}

View File

@ -0,0 +1,66 @@
From 4d690855d6bdc15b753ac3c21bf507ad94d46aac Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <arjan@linux.intel.com>
Date: Sun, 21 Sep 2008 11:58:27 -0700
Subject: [PATCH] superreadahead patch
---
fs/ext3/ioctl.c | 3 +++
fs/ext3/super.c | 1 +
include/linux/ext3_fs.h | 1 +
include/linux/fs.h | 2 ++
4 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 8897481..08f4854 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -276,6 +276,9 @@ group_add_out:
mnt_drop_write(filp->f_path.mnt);
return err;
}
+ case EXT3_IOC_INODE_JIFFIES: {
+ return inode->created_when;
+ }
default:
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 524b349..e6e8514 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -466,6 +466,7 @@ static struct inode *ext3_alloc_inode(struct super_block *sb)
return NULL;
ei->i_block_alloc_info = NULL;
ei->vfs_inode.i_version = 1;
+ ei->vfs_inode.created_when = jiffies;
return &ei->vfs_inode;
}
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 634a5e5..84d5394 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -250,6 +250,7 @@ struct ext3_new_group_data {
#endif
#define EXT3_IOC_GETRSVSZ _IOR('f', 5, long)
#define EXT3_IOC_SETRSVSZ _IOW('f', 6, long)
+#define EXT3_IOC_INODE_JIFFIES _IOR('f', 19, long)
/*
* ioctl commands in 32 bit emulation
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0872372..078e3fd 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -781,6 +781,8 @@ struct inode {
struct posix_acl *i_default_acl;
#endif
void *i_private; /* fs or device private pointer */
+
+ unsigned long created_when; /* jiffies of creation time */
};
/*
--
1.6.0.6

View File

@ -0,0 +1,146 @@
From 3281da09528ca94f1b1fd39cae388f5b5423aa46 Mon Sep 17 00:00:00 2001
From: Alan Olsen <alanx.r.olsen@intel.com>
Date: Tue, 21 Jul 2009 13:26:58 -0700
Subject: [PATCH] linux-2.6.29-touchkit.patch
Signed-off-by: Alan Olsen <alanx.r.olsen@intel.com>
---
drivers/input/mouse/psmouse-base.c | 9 +++++++
drivers/input/mouse/psmouse.h | 1 +
drivers/input/mouse/touchkit_ps2.c | 45 ++++++++++++++++++++++++++++++++++-
drivers/input/mouse/touchkit_ps2.h | 6 ++++
4 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index b407b35..4c6b184 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -678,6 +678,9 @@ static int psmouse_extensions(struct psmouse *psmouse,
if (touchkit_ps2_detect(psmouse, set_properties) == 0)
return PSMOUSE_TOUCHKIT_PS2;
+
+ if (elftouch_ps2_detect(psmouse, set_properties) == 0)
+ return PSMOUSE_ELFTOUCH_PS2;
}
/*
@@ -788,6 +791,12 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.alias = "trackpoint",
.detect = trackpoint_detect,
},
+ {
+ .type = PSMOUSE_ELFTOUCH_PS2,
+ .name = "elftouchPS2",
+ .alias = "elftouch",
+ .detect = elftouch_ps2_detect,
+ },
#endif
#ifdef CONFIG_MOUSE_PS2_TOUCHKIT
{
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 54ed267..8d1ba79 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -89,6 +89,7 @@ enum psmouse_type {
PSMOUSE_TRACKPOINT,
PSMOUSE_TOUCHKIT_PS2,
PSMOUSE_CORTRON,
+ PSMOUSE_ELFTOUCH_PS2,
PSMOUSE_HGPK,
PSMOUSE_ELANTECH,
PSMOUSE_AUTO /* This one should always be last */
diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c
index 3fadb2a..e9c27f1 100644
--- a/drivers/input/mouse/touchkit_ps2.c
+++ b/drivers/input/mouse/touchkit_ps2.c
@@ -51,6 +51,11 @@
#define TOUCHKIT_GET_X(packet) (((packet)[1] << 7) | (packet)[2])
#define TOUCHKIT_GET_Y(packet) (((packet)[3] << 7) | (packet)[4])
+#define ELFTOUCH_MAX_XC 0x0fff
+#define ELFTOUCH_MAX_YC 0x0fff
+#define ELFTOUCH_GET_X(packet) (((packet)[3] << 7) | (packet)[4])
+#define ELFTOUCH_GET_Y(packet) (((packet)[1] << 7) | (packet)[2])
+
static psmouse_ret_t touchkit_ps2_process_byte(struct psmouse *psmouse)
{
unsigned char *packet = psmouse->packet;
@@ -59,9 +64,15 @@ static psmouse_ret_t touchkit_ps2_process_byte(struct psmouse *psmouse)
if (psmouse->pktcnt != 5)
return PSMOUSE_GOOD_DATA;
- input_report_abs(dev, ABS_X, TOUCHKIT_GET_X(packet));
- input_report_abs(dev, ABS_Y, TOUCHKIT_GET_Y(packet));
+ if(psmouse->type==PSMOUSE_ELFTOUCH_PS2) {
+ input_report_abs(dev, ABS_X, ELFTOUCH_GET_X(packet));
+ input_report_abs(dev, ABS_Y, ELFTOUCH_GET_Y(packet));
+ } else {
+ input_report_abs(dev, ABS_X, TOUCHKIT_GET_X(packet));
+ input_report_abs(dev, ABS_Y, TOUCHKIT_GET_Y(packet));
+ }
input_report_key(dev, BTN_TOUCH, TOUCHKIT_GET_TOUCHED(packet));
+
input_sync(dev);
return PSMOUSE_FULL_PACKET;
@@ -98,3 +109,33 @@ int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties)
return 0;
}
+
+int elftouch_ps2_detect(struct psmouse *psmouse, int set_properties)
+{
+ struct input_dev *dev = psmouse->dev;
+ unsigned char param[16];
+ int command, res;
+
+ param[0]=0x0f4;
+ command = TOUCHKIT_SEND_PARMS(1, 0, TOUCHKIT_CMD);
+ res=ps2_command(&psmouse->ps2dev, param, command);
+ if(res) { return -ENODEV; }
+
+ param[0]=0x0b0;
+ command = TOUCHKIT_SEND_PARMS(1, 1, TOUCHKIT_CMD);
+ res=ps2_command(&psmouse->ps2dev, param, command);
+ if(res) { return -ENODEV; }
+
+ if (set_properties) {
+ dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ set_bit(BTN_TOUCH, dev->keybit);
+ input_set_abs_params(dev, ABS_X, 0, ELFTOUCH_MAX_XC, 0, 0);
+ input_set_abs_params(dev, ABS_Y, 0, ELFTOUCH_MAX_YC, 0, 0);
+
+ psmouse->vendor = "ElfTouch";
+ psmouse->name = "Touchscreen";
+ psmouse->protocol_handler = touchkit_ps2_process_byte;
+ psmouse->pktsize = 5;
+ }
+ return 0;
+}
diff --git a/drivers/input/mouse/touchkit_ps2.h b/drivers/input/mouse/touchkit_ps2.h
index 8a0dd35..f32ef4c 100644
--- a/drivers/input/mouse/touchkit_ps2.h
+++ b/drivers/input/mouse/touchkit_ps2.h
@@ -14,12 +14,18 @@
#ifdef CONFIG_MOUSE_PS2_TOUCHKIT
int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties);
+int elftouch_ps2_detect(struct psmouse *psmouse, int set_properties);
#else
static inline int touchkit_ps2_detect(struct psmouse *psmouse,
int set_properties)
{
return -ENOSYS;
}
+static inline int elftouch_ps2_detect(struct psmouse *psmouse,
+ int set_properties)
+{
+ return -ENOSYS;
+}
#endif /* CONFIG_MOUSE_PS2_TOUCHKIT */
#endif
--
1.6.0.6

View File

@ -0,0 +1,32 @@
From a5a267593c15ac987f78cfc21cae0c8ef723f81e Mon Sep 17 00:00:00 2001
From: Alan Olsen <alan.r.olsen@intel.com>
Date: Mon, 21 Sep 2009 13:58:49 -0700
Subject: [PATCH] linux-2.6.30-non-root-X.patch
Signed-off-by: Alan Olsen <alan.r.olsen@intel.com>
---
drivers/gpu/drm/drm_drv.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 4678f8f..b7f3a41 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -64,12 +64,12 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
--
1.6.0.6

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
From 9de5f61c79361bf6e9394d2f77a2b436d53deee5 Mon Sep 17 00:00:00 2001
From: Yong Wang <yong.y.wang@intel.com>
Date: Tue, 30 Jun 2009 14:17:19 +0800
Subject: [PATCH] Revert "net: num_dma_maps is not used"
This reverts commit eae3f29cc73f83cc3f1891d3ad40021b5172c630.
The IVI driver is a user of num_dma_maps.
Signed-off-by: Yong Wang <yong.y.wang@intel.com>
---
include/linux/skbuff.h | 3 +++
net/core/skb_dma_map.c | 1 +
2 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index b47b3f0..468bc21 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -198,6 +198,9 @@ struct skb_shared_info {
unsigned short gso_type;
__be32 ip6_frag_id;
union skb_shared_tx tx_flags;
+#ifdef CONFIG_HAS_DMA
+ unsigned int num_dma_maps;
+#endif
struct sk_buff *frag_list;
struct skb_shared_hwtstamps hwtstamps;
skb_frag_t frags[MAX_SKB_FRAGS];
diff --git a/net/core/skb_dma_map.c b/net/core/skb_dma_map.c
index 79687df..07d4ac5 100644
--- a/net/core/skb_dma_map.c
+++ b/net/core/skb_dma_map.c
@@ -30,6 +30,7 @@ int skb_dma_map(struct device *dev, struct sk_buff *skb,
goto unwind;
sp->dma_maps[i] = map;
}
+ sp->num_dma_maps = i + 1;
return 0;
--
1.6.0.6

View File

@ -0,0 +1,465 @@
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index e70c57e..8e36fc8 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -35,7 +36,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#define VERSION "0.5"
+#define VERSION "0.6"
static int ignore_dga;
static int ignore_csr;
@@ -145,6 +146,7 @@ static struct usb_device_id blacklist_table[] = {
#define BTUSB_INTR_RUNNING 0
#define BTUSB_BULK_RUNNING 1
#define BTUSB_ISOC_RUNNING 2
+#define BTUSB_SUSPENDING 3
struct btusb_data {
struct hci_dev *hdev;
@@ -157,11 +159,15 @@ struct btusb_data {
unsigned long flags;
struct work_struct work;
+ struct work_struct waker;
struct usb_anchor tx_anchor;
struct usb_anchor intr_anchor;
struct usb_anchor bulk_anchor;
struct usb_anchor isoc_anchor;
+ struct usb_anchor deferred;
+ int tx_in_flight;
+ spinlock_t txlock;
struct usb_endpoint_descriptor *intr_ep;
struct usb_endpoint_descriptor *bulk_tx_ep;
@@ -174,8 +180,26 @@ struct btusb_data {
unsigned int sco_num;
int isoc_altsetting;
int suspend_count;
+ int did_iso_resume:1;
};
+static int inc_tx(struct btusb_data *data)
+{
+ unsigned long flags;
+ int rv;
+
+ spin_lock_irqsave(&data->txlock, flags);
+ rv = test_bit(BTUSB_SUSPENDING, &data->flags);
+ BT_DBG("BTUSB_SUSPENDING bit = %d for intf %p in %s",
+ rv, data->intf, __func__);
+ if (!rv)
+ data->tx_in_flight++;
+ spin_unlock_irqrestore(&data->txlock, flags);
+
+ return rv;
+}
+
+
static void btusb_intr_complete(struct urb *urb)
{
struct hci_dev *hdev = urb->context;
@@ -202,6 +226,7 @@ static void btusb_intr_complete(struct urb *urb)
if (!test_bit(BTUSB_INTR_RUNNING, &data->flags))
return;
+ usb_mark_last_busy(data->udev);
usb_anchor_urb(urb, &data->intr_anchor);
err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -327,6 +352,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
urb->transfer_flags |= URB_FREE_BUFFER;
+ usb_mark_last_busy(data->udev);
usb_anchor_urb(urb, &data->bulk_anchor);
err = usb_submit_urb(urb, mem_flags);
@@ -465,6 +491,33 @@ static void btusb_tx_complete(struct urb *urb)
{
struct sk_buff *skb = urb->context;
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
+ struct btusb_data *data = hdev->driver_data;
+
+ BT_DBG("%s urb %p status %d count %d", hdev->name,
+ urb, urb->status, urb->actual_length);
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags))
+ goto done;
+
+ if (!urb->status)
+ hdev->stat.byte_tx += urb->transfer_buffer_length;
+ else
+ hdev->stat.err_tx++;
+
+done:
+ spin_lock(&data->txlock);
+ data->tx_in_flight--;
+ spin_unlock(&data->txlock);
+
+ kfree(urb->setup_packet);
+
+ kfree_skb(skb);
+}
+
+static void btusb_isoc_tx_complete(struct urb *urb)
+{
+ struct sk_buff *skb = urb->context;
+ struct hci_dev *hdev = (struct hci_dev *) skb->dev;
BT_DBG("%s urb %p status %d count %d", hdev->name,
urb, urb->status, urb->actual_length);
@@ -490,11 +543,16 @@ static int btusb_open(struct hci_dev *hdev)
BT_DBG("%s", hdev->name);
+ err = usb_autopm_get_interface(data->intf);
+ if (err < 0)
+ return err;
+ data->intf->needs_remote_wakeup = 1;
+
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
- return 0;
+ goto out;
if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
- return 0;
+ goto out;
err = btusb_submit_intr_urb(hdev, GFP_KERNEL);
if (err < 0)
@@ -502,6 +560,7 @@ static int btusb_open(struct hci_dev *hdev)
err = btusb_submit_bulk_urb(hdev, GFP_KERNEL);
if (err < 0) {
+ BT_DBG("kill urbs %s", __func__);
usb_kill_anchored_urbs(&data->intr_anchor);
goto failed;
}
@@ -509,17 +568,28 @@ static int btusb_open(struct hci_dev *hdev)
set_bit(BTUSB_BULK_RUNNING, &data->flags);
btusb_submit_bulk_urb(hdev, GFP_KERNEL);
+out:
+ usb_autopm_put_interface(data->intf);
return 0;
failed:
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
clear_bit(HCI_RUNNING, &hdev->flags);
+ usb_autopm_put_interface(data->intf);
return err;
}
+static void btusb_stop_traffic(struct btusb_data *data)
+{
+ usb_kill_anchored_urbs(&data->intr_anchor);
+ usb_kill_anchored_urbs(&data->bulk_anchor);
+ usb_kill_anchored_urbs(&data->isoc_anchor);
+}
+
static int btusb_close(struct hci_dev *hdev)
{
struct btusb_data *data = hdev->driver_data;
+ int err;
BT_DBG("%s", hdev->name);
@@ -529,13 +599,16 @@ static int btusb_close(struct hci_dev *hdev)
cancel_work_sync(&data->work);
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
- usb_kill_anchored_urbs(&data->isoc_anchor);
-
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
- usb_kill_anchored_urbs(&data->bulk_anchor);
-
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
- usb_kill_anchored_urbs(&data->intr_anchor);
+
+ BT_DBG("kill urbs %s", __func__);
+ btusb_stop_traffic(data);
+ err = usb_autopm_get_interface(data->intf);
+ if (!err) {
+ data->intf->needs_remote_wakeup = 0;
+ usb_autopm_put_interface(data->intf);
+ }
return 0;
}
@@ -546,6 +619,7 @@ static int btusb_flush(struct hci_dev *hdev)
BT_DBG("%s", hdev->name);
+ BT_DBG("kill urbs %s", __func__);
usb_kill_anchored_urbs(&data->tx_anchor);
return 0;
@@ -622,7 +696,7 @@ static int btusb_send_frame(struct sk_buff *skb)
urb->dev = data->udev;
urb->pipe = pipe;
urb->context = skb;
- urb->complete = btusb_tx_complete;
+ urb->complete = btusb_isoc_tx_complete;
urb->interval = data->isoc_tx_ep->bInterval;
urb->transfer_flags = URB_ISO_ASAP;
@@ -633,12 +707,23 @@ static int btusb_send_frame(struct sk_buff *skb)
le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
hdev->stat.sco_tx++;
- break;
+ goto skip_waking;
default:
return -EILSEQ;
}
+ err = inc_tx(data);
+ if (err) {
+
+ usb_anchor_urb(urb, &data->deferred);
+ schedule_work(&data->waker);
+ err = 0;
+ goto out;
+ } else {
+
+ }
+skip_waking:
usb_anchor_urb(urb, &data->tx_anchor);
err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -646,10 +731,13 @@ static int btusb_send_frame(struct sk_buff *skb)
BT_ERR("%s urb %p submission failed", hdev->name, urb);
kfree(urb->setup_packet);
usb_unanchor_urb(urb);
+ } else {
+ usb_mark_last_busy(data->udev);
}
usb_free_urb(urb);
+out:
return err;
}
@@ -721,10 +809,23 @@ static void btusb_work(struct work_struct *work)
{
struct btusb_data *data = container_of(work, struct btusb_data, work);
struct hci_dev *hdev = data->hdev;
+ int err;
if (hdev->conn_hash.sco_num > 0) {
+ if (!data->did_iso_resume) {
+ err = usb_autopm_get_interface(data->isoc);
+ if (!err) {
+ data->did_iso_resume = 1;
+ } else {
+ clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ BT_DBG("kill urbs %s", __func__);
+ usb_kill_anchored_urbs(&data->isoc_anchor);
+ return;
+ }
+ }
if (data->isoc_altsetting != 2) {
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ BT_DBG("kill urbs %s", __func__);
usb_kill_anchored_urbs(&data->isoc_anchor);
if (__set_isoc_interface(hdev, 2) < 0)
@@ -739,12 +840,28 @@ static void btusb_work(struct work_struct *work)
}
} else {
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+ BT_DBG("kill urbs %s", __func__);
usb_kill_anchored_urbs(&data->isoc_anchor);
__set_isoc_interface(hdev, 0);
+ if (data->did_iso_resume) {
+ data->did_iso_resume = 0;
+ usb_autopm_put_interface(data->isoc);
+ }
}
}
+static void btusb_waker(struct work_struct *work)
+{
+ struct btusb_data *data = container_of(work, struct btusb_data, waker);
+ int err;
+
+
+ err = usb_autopm_get_interface(data->intf);
+ if (!err)
+ usb_autopm_put_interface(data->intf);
+}
+
static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -814,11 +931,14 @@ static int btusb_probe(struct usb_interface *intf,
spin_lock_init(&data->lock);
INIT_WORK(&data->work, btusb_work);
+ INIT_WORK(&data->waker, btusb_waker);
+ spin_lock_init(&data->txlock);
init_usb_anchor(&data->tx_anchor);
init_usb_anchor(&data->intr_anchor);
init_usb_anchor(&data->bulk_anchor);
init_usb_anchor(&data->isoc_anchor);
+ init_usb_anchor(&data->deferred);
hdev = hci_alloc_dev();
if (!hdev) {
@@ -949,39 +1069,78 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
BT_DBG("intf %p", intf);
- if (data->suspend_count++)
+ if (data->suspend_count++) {
+ BT_DBG("data->suspend_count = %d for intf %p, returning from %s",
+ data->suspend_count, intf, __func__);
return 0;
+ }
+ BT_DBG("data->suspend_count = %d for intf %p, continuing %s",
+ data->suspend_count, intf, __func__);
+
+ spin_lock_irq(&data->txlock);
+ if (!(interface_to_usbdev(intf)->auto_pm && data->tx_in_flight)) {
+ BT_DBG("Setting BTUSB_SUSPENDING bit in %s for intf %p",
+ __func__, intf);
+ set_bit(BTUSB_SUSPENDING, &data->flags);
+ spin_unlock_irq(&data->txlock);
+ } else {
+ spin_unlock_irq(&data->txlock);
+ BT_DBG("%d URBs in flight", data->tx_in_flight);
+ data->suspend_count--;
+ return -EBUSY;
+ }
cancel_work_sync(&data->work);
+ BT_DBG("kill urbs %s", __func__);
+ btusb_stop_traffic(data);
usb_kill_anchored_urbs(&data->tx_anchor);
- usb_kill_anchored_urbs(&data->isoc_anchor);
- usb_kill_anchored_urbs(&data->bulk_anchor);
- usb_kill_anchored_urbs(&data->intr_anchor);
-
return 0;
}
+static void play_deferred(struct btusb_data *data)
+{
+ struct urb *urb;
+ int err;
+
+ while ((urb = usb_get_from_anchor(&data->deferred))) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0)
+ break;
+ else
+ data->tx_in_flight++;
+
+ }
+ usb_scuttle_anchored_urbs(&data->deferred);
+}
+
static int btusb_resume(struct usb_interface *intf)
{
struct btusb_data *data = usb_get_intfdata(intf);
struct hci_dev *hdev = data->hdev;
- int err;
+ int err = 0;
BT_DBG("intf %p", intf);
- if (--data->suspend_count)
+ if (--data->suspend_count) {
+ BT_DBG("data->suspend_count = %d for intf %p, returning from %s",
+ data->suspend_count, intf, __func__);
return 0;
+ }
- if (!test_bit(HCI_RUNNING, &hdev->flags))
- return 0;
+ if (!test_bit(HCI_RUNNING, &hdev->flags)) {
+ BT_DBG("HCI not running, returning from %s", __func__);
+ goto no_io_needed;
+ }
if (test_bit(BTUSB_INTR_RUNNING, &data->flags)) {
err = btusb_submit_intr_urb(hdev, GFP_NOIO);
if (err < 0) {
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
- return err;
+ BT_DBG("Error (%d) submitting interrupt URB, returning from %s",
+ err, __func__);
+ goto err_out;
}
}
@@ -989,9 +1148,12 @@ static int btusb_resume(struct usb_interface *intf)
err = btusb_submit_bulk_urb(hdev, GFP_NOIO);
if (err < 0) {
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
- return err;
- } else
+ BT_DBG("Error (%d) submitting bulk URB, returning from %s",
+ err, __func__);
+ goto err_out;
+ } else {
btusb_submit_bulk_urb(hdev, GFP_NOIO);
+ }
}
if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
@@ -1001,7 +1163,24 @@ static int btusb_resume(struct usb_interface *intf)
btusb_submit_isoc_urb(hdev, GFP_NOIO);
}
+ spin_lock_irq(&data->txlock);
+ play_deferred(data);
+ BT_DBG("Clearing BTUSB_SUSPENDING bit in %s for intf %p", __func__, intf);
+ clear_bit(BTUSB_SUSPENDING, &data->flags);
+ spin_unlock_irq(&data->txlock);
+ schedule_work(&data->work);
+
return 0;
+
+err_out:
+ usb_scuttle_anchored_urbs(&data->deferred);
+no_io_needed:
+ spin_lock_irq(&data->txlock);
+ BT_DBG("Clearing BTUSB_SUSPENDING bit in %s for intf %p", __func__, intf);
+ clear_bit(BTUSB_SUSPENDING, &data->flags);
+ spin_unlock_irq(&data->txlock);
+
+ return err;
}
static struct usb_driver btusb_driver = {
@@ -1011,6 +1190,7 @@ static struct usb_driver btusb_driver = {
.suspend = btusb_suspend,
.resume = btusb_resume,
.id_table = btusb_table,
+ .supports_autosuspend = 1,
};
static int __init btusb_init(void)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index e70c57e..ac94f91 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -908,6 +967,7 @@ static int btusb_probe(struct usb_interface *intf,
}
usb_set_intfdata(intf, data);
+ usb_device_autosuspend_enable(data->udev);
return 0;
}

View File

@ -0,0 +1,26 @@
From 70ae749d15e012ab4a33aa2abe7a4d97a4dcebdb Mon Sep 17 00:00:00 2001
From: Li Peng <peng.li@intel.com>
Date: Thu, 20 Aug 2009 13:54:04 +0800
Subject: Add G33 series in VGA hotplug support category
Test on the IGD chip, which is a G33-like graphic device.
---
drivers/gpu/drm/i915/i915_drv.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7537f57..940ee4c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -892,7 +892,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev))
#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev))
#define SUPPORTS_EDP(dev) (IS_IGDNG_M(dev))
-#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev))
+#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev) || IS_I965G(dev))
/* dsparb controlled by hw only */
#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev))
--
1.6.1.3

View File

@ -0,0 +1,43 @@
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c
index e4b4e88..2d51935 100644
--- a/drivers/gpu/drm/i915/i915_opregion.c
+++ b/drivers/gpu/drm/i915/i915_opregion.c
@@ -148,6 +148,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
struct drm_i915_private *dev_priv = dev->dev_private;
struct opregion_asle *asle = dev_priv->opregion.asle;
u32 blc_pwm_ctl, blc_pwm_ctl2;
+ u32 max_backlight, level, shift;
if (!(bclp & ASLE_BCLP_VALID))
return ASLE_BACKLIGHT_FAIL;
@@ -157,14 +158,25 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
return ASLE_BACKLIGHT_FAIL;
blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
- blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
blc_pwm_ctl2 = I915_READ(BLC_PWM_CTL2);
- if (blc_pwm_ctl2 & BLM_COMBINATION_MODE)
+ if (IS_I965G(dev) && (blc_pwm_ctl2 & BLM_COMBINATION_MODE))
pci_write_config_dword(dev->pdev, PCI_LBPC, bclp);
- else
- I915_WRITE(BLC_PWM_CTL, blc_pwm_ctl | ((bclp * 0x101)-1));
-
+ else {
+ if (IS_IGD(dev)) {
+ blc_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1);
+ max_backlight = (blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >>
+ BACKLIGHT_MODULATION_FREQ_SHIFT;
+ shift = BACKLIGHT_DUTY_CYCLE_SHIFT + 1;
+ } else {
+ blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
+ max_backlight = ((blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >>
+ BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+ shift = BACKLIGHT_DUTY_CYCLE_SHIFT;
+ }
+ level = (bclp * max_backlight) / 255;
+ I915_WRITE(BLC_PWM_CTL, blc_pwm_ctl | (level << shift));
+ }
asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
return 0;

View File

@ -0,0 +1,26 @@
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index f85aaf2..2e5841e 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -412,6 +412,9 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
dev->vblank_enabled[crtc] = 1;
drm_update_vblank_count(dev, crtc);
}
+ } else if (atomic_read(&dev->vblank_refcount[crtc]) > 1) {
+ atomic_dec(&dev->vblank_refcount[crtc]);
+ ret = -EINVAL;
}
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 748ed50..9cb07a5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1549,6 +1549,7 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
/* Wait for vblank for the disable to take effect. */
intel_wait_for_vblank(dev);
+ dev->vblank_enabled[pipe] = 0;
temp = I915_READ(dpll_reg);
if ((temp & DPLL_VCO_ENABLE) != 0) {

View File

@ -0,0 +1,307 @@
From 4e8354884daa2ee3e491bae69a81f85a2d1ca8ba Mon Sep 17 00:00:00 2001
From: Fei Jiang <fei.jiang@intel.com>
Date: Mon, 3 Aug 2009 11:31:53 -0400
Subject: [PATCH] change for general drm code to implement kms-flip feature
Signed-off-by: Fei Jiang <fei.jiang@intel.com>
---
drivers/gpu/drm/drm_crtc.c | 128 ++++++++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/drm_drv.c | 1 +
drivers/gpu/drm/drm_irq.c | 30 ++++++++++
include/drm/drm.h | 1 +
include/drm/drmP.h | 9 +++
include/drm/drm_crtc.h | 12 ++++
include/drm/drm_mode.h | 16 ++++++
7 files changed, 197 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 8fab789..3ada446
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2452,3 +2452,131 @@ out:
mutex_unlock(&dev->mode_config.mutex);
return ret;
}
+
+/**
+ * drm_mode_page_flip_ioctl - page flip ioctl
+ * @dev: DRM device
+ * @data: ioctl args
+ * @file_priv: file private data
+ *
+ * The page flip ioctl replaces the current front buffer with a new
+ * one, using the CRTC's set_base function, which should just update
+ * the front buffer base pointer. It's up to set_base to make
+ * sure the update doesn't result in tearing (on some hardware the
+ * base register is double buffered, so this is easy).
+ *
+ * Note that this covers just the simple case of flipping the front
+ * buffer immediately. Interval handling and interlaced modes have to
+ * be handled by userspace, or with new ioctls.
+ */
+int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+#if 0
+ struct drm_pending_flip *pending;
+#endif
+
+ struct drm_mode_page_flip *flip_data = data;
+ struct drm_mode_object *drm_obj, *fb_obj;
+ struct drm_crtc *crtc;
+ int ret = 0;
+
+ if (!(drm_core_check_feature(dev, DRIVER_MODESET)))
+ return -ENODEV;
+
+ /*
+ * Reject unknown flags so future userspace knows what we (don't)
+ * support
+ */
+ if (flip_data->flags & (~DRM_MODE_PAGE_FLIP_FLAGS_MASK)) {
+ DRM_DEBUG("bad page flip flags\n");
+ return -EINVAL;
+ }
+#if 0
+ pending = kzalloc(sizeof *pending, GFP_KERNEL);
+ if (pending == NULL)
+ return -ENOMEM;
+#endif
+ mutex_lock(&dev->struct_mutex);
+
+ fb_obj = drm_mode_object_find(dev, flip_data->fb_id,
+ DRM_MODE_OBJECT_FB);
+ if (!fb_obj) {
+ DRM_DEBUG("unknown fb %d\n", flip_data->fb_id);
+ ret = -ENOENT;
+ goto out_unlock;
+ }
+
+ drm_obj = drm_mode_object_find(dev, flip_data->crtc_id,
+ DRM_MODE_OBJECT_CRTC);
+ if (!drm_obj) {
+ DRM_DEBUG("unknown crtc %d\n", flip_data->crtc_id);
+ ret = -ENOENT;
+ goto out_unlock;
+ }
+ crtc = obj_to_crtc(drm_obj);
+ if (!crtc->enabled) {
+ DRM_DEBUG("crtc %d not enabled\n", flip_data->crtc_id);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+#if 0
+ if (crtc->fb->funcs->unpin == NULL) {
+ DRM_DEBUG("fb for crtc %d does not support delayed unpin\n",
+ flip_data->crtc_id);
+ ret = -ENODEV;
+ goto out_unlock;
+ }
+
+ pending->crtc = crtc;
+ pending->old_fb = crtc->fb;
+ pending->pipe = crtc->pipe;
+ pending->event.base.type = DRM_EVENT_MODE_PAGE_FLIP;
+ pending->event.base.length = sizeof pending->event;
+ pending->event.user_data = flip_data->user_data;
+ pending->pending_event.event = &pending->event.base;
+ pending->pending_event.file_priv = file_priv;
+ pending->pending_event.destroy =
+ (void (*) (struct drm_pending_event *)) kfree;
+
+ /* Get vblank ref for completion handling */
+ ret = drm_vblank_get(dev, crtc->pipe);
+ if (ret) {
+ DRM_DEBUG("failed to take vblank ref\n");
+ goto out_unlock;
+ }
+
+ pending->frame = drm_vblank_count(dev, crtc->pipe);
+ list_add_tail(&pending->link, &dev->flip_list);
+#endif
+
+ /*
+ * The set_base call will change the domain on the new fb,
+ * which will force the rendering to finish and block the
+ * ioctl. We need to do this last part from a work queue, to
+ * avoid blocking userspace here.
+ */
+ crtc->fb = obj_to_fb(fb_obj);
+retry_set:
+ ret = (*crtc->funcs->set_base)(crtc, 0, 0, NULL);
+ if (ret == -ERESTARTSYS)
+ goto retry_set;
+
+ if (ret) {
+ DRM_ERROR("set_base failed: %d\n", ret);
+ goto out_unlock;
+ }
+
+ mutex_unlock(&dev->struct_mutex);
+
+ return 0;
+
+out_unlock:
+ mutex_unlock(&dev->struct_mutex);
+#if 0
+ kfree(pending);
+#endif
+ return ret;
+}
+
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 1ce7977..761c2ec
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -145,6 +145,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
};
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index b4a3dbc..d5104df
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -71,6 +71,28 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
return 0;
}
+#if 0
+static void drm_flip_work_func(struct work_struct *work)
+{
+ struct drm_device *dev =
+ container_of(work, struct drm_device, flip_work);
+#if 0
+ struct drm_pending_flip *f, *t;
+#endif
+ u32 frame;
+
+ mutex_lock(&dev->struct_mutex);
+
+ list_for_each_entry_safe(f, t, &dev->flip_list, link) {
+ frame = drm_vblank_count(dev, f->pipe);
+ if (vblank_after(frame, f->frame))
+ drm_finish_pending_flip(dev, f, frame);
+ }
+
+ mutex_unlock(&dev->struct_mutex);
+}
+#endif
+
static void vblank_disable_fn(unsigned long arg)
{
struct drm_device *dev = (struct drm_device *)arg;
@@ -161,6 +183,11 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
atomic_set(&dev->vblank_refcount[i], 0);
}
+#if 0
+ INIT_LIST_HEAD(&dev->flip_list);
+ INIT_WORK(&dev->flip_work, drm_flip_work_func);
+#endif
+
dev->vblank_disable_allowed = 0;
return 0;
@@ -626,5 +653,8 @@ void drm_handle_vblank(struct drm_device *dev, int crtc)
{
atomic_inc(&dev->_vblank_count[crtc]);
DRM_WAKEUP(&dev->vbl_queue[crtc]);
+#if 0
+ schedule_work(&dev->flip_work);
+#endif
}
EXPORT_SYMBOL(drm_handle_vblank);
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 7cb50bd..78bd91b
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -686,6 +686,7 @@ struct drm_gem_open {
#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int)
+#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOW( 0xB0, struct drm_mode_page_flip)
/**
* Device specific ioctls should only be in their respective headers
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index c5122bf..36f9e6a
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -976,6 +976,15 @@ struct drm_device {
cycles_t ctx_start;
cycles_t lck_start;
+ struct work_struct flip_work;
+
+#if 0
+ /**
+ * List of objects waiting on flip completion
+ */
+ struct list_head flip_list;
+#endif
+
struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
wait_queue_head_t buf_readers; /**< Processes waiting to read */
wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 7300fb8..742c870
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -331,6 +331,16 @@ struct drm_crtc_funcs {
void (*destroy)(struct drm_crtc *crtc);
int (*set_config)(struct drm_mode_set *set);
+
+ /*
+ * Move the crtc on the current fb to the given position.
+ * This function is optional. If old_fb is provided, the
+ * function will wait for vblank and unpin it. If old_fb is
+ * NULL, nothing is unpinned and the caller must call
+ * mode_unpin_fb to release the old framebuffer.
+ */
+ int (*set_base)(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb);
};
/**
@@ -736,4 +746,6 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev,
extern int drm_mode_gamma_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern bool drm_detect_hdmi_monitor(struct edid *edid);
+extern int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
#endif /* __DRM_CRTC_H__ */
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index ae304cc..464b779
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -265,4 +265,20 @@ struct drm_mode_crtc_lut {
__u64 blue;
};
+#define DRM_MODE_PAGE_FLIP_WAIT (1<<0) /* block on previous page flip */
+#define DRM_MODE_PAGE_FLIP_FLAGS_MASK (DRM_MODE_PAGE_FLIP_WAIT)
+
+struct drm_mode_page_flip {
+ /** Handle of new front buffer */
+ __u32 fb_id;
+ __u32 crtc_id;
+
+ /* 64 bit cookie returned to userspace in the page flip event. */
+ __u64 user_data;
+ /**
+ * page flip flags (wait on flip only for now)
+ */
+ __u32 flags;
+};
+
#endif
--
1.5.3.4

View File

@ -0,0 +1,140 @@
From 5deab387f5b9ec79a6bf7edc52b0653c2a6d44b5 Mon Sep 17 00:00:00 2001
From: Alan Olsen <alan.r.olsen@intel.com>
Date: Fri, 11 Sep 2009 15:57:46 -0700
Subject: [PATCH] linux-2.6.31-drm-mem-info.patch
Signed-off-by: Alan Olsen <alan.r.olsen@intel.com>
---
drivers/gpu/drm/Makefile | 4 +++
drivers/gpu/drm/drm_info.c | 58 ++++++++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/drm_proc.c | 2 +
include/drm/drmP.h | 2 +
4 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index fe23f29..d76f167 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -4,6 +4,10 @@
ccflags-y := -Iinclude/drm
+ifeq ($(CONFIG_DRM_PSB),y)
+ ccflags-y += -Idrivers/gpu/drm/psb
+endif
+
drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm_context.o drm_dma.o drm_drawable.o \
drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index f0f6c6b..0ecc778 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -36,6 +36,10 @@
#include <linux/seq_file.h>
#include "drmP.h"
+#ifdef CONFIG_DRM_PSB
+#include "psb/psb_drv.h"
+#endif
+
/**
* Called when "/proc/dri/.../name" is read.
*
@@ -211,6 +215,33 @@ int drm_vblank_info(struct seq_file *m, void *data)
return 0;
}
+int drm_gem_object_mem_info(int id, void *ptr, void *data)
+{
+ struct drm_gem_object *obj = ptr;
+ struct seq_file *m = data;
+
+ seq_printf(m, "object 0x%p name %2d memory %8zd\n",
+ obj, obj->name, obj->size);
+
+ return 0;
+}
+
+int drm_gem_clients_info(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct drm_file *priv;
+
+ mutex_lock(&dev->struct_mutex);
+ list_for_each_entry(priv, &dev->filelist, lhead) {
+ seq_printf(m, "pid %5d \n", priv->pid);
+ idr_for_each(&priv->object_idr, &drm_gem_object_mem_info, m);
+ seq_printf(m, "\n");
+ }
+ mutex_unlock(&dev->struct_mutex);
+ return 0;
+}
+
/**
* Called when "/proc/dri/.../clients" is read.
*
@@ -273,6 +304,33 @@ int drm_gem_object_info(struct seq_file *m, void* data)
return 0;
}
+#ifdef CONFIG_DRM_PSB
+int drm_ttm_mem_info(struct seq_file *m, void* data)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+
+ if (!strncmp("psb", dev->devname, 3)) {
+ struct ttm_bo_device *bdev = &psb_priv(dev)->bdev;
+ struct ttm_mem_global *glob = bdev->mem_glob;
+
+ spin_lock(&glob->lock);
+ seq_printf(m, "used memory %llu \n", glob->used_memory);
+ seq_printf(m, "used total memory %llu \n", glob->used_total_memory);
+ spin_unlock(&glob->lock);
+ } else {
+ seq_printf(m, "This is not a PSB device, no ttm mem info available\n");
+ }
+ return 0;
+}
+#else
+int drm_ttm_mem_info(struct seq_file *m, void* data)
+{
+ seq_printf(m, "ttm is not used\n");
+ return 0;
+}
+#endif
+
#if DRM_DEBUG_CODE
int drm_vma_info(struct seq_file *m, void *data)
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c
index bbd4b3d..26e64ec 100644
--- a/drivers/gpu/drm/drm_proc.c
+++ b/drivers/gpu/drm/drm_proc.c
@@ -55,6 +55,8 @@ static struct drm_info_list drm_proc_list[] = {
{"bufs", drm_bufs_info, 0},
{"gem_names", drm_gem_name_info, DRIVER_GEM},
{"gem_objects", drm_gem_object_info, DRIVER_GEM},
+ {"gem_clients", drm_gem_clients_info, DRIVER_GEM},
+ {"ttm_meminfo", drm_ttm_mem_info, 0},
#if DRM_DEBUG_CODE
{"vma", drm_vma_info, 0},
#endif
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index dbd40f1..5575b9a 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1355,6 +1355,8 @@ extern int drm_vblank_info(struct seq_file *m, void *data);
extern int drm_clients_info(struct seq_file *m, void* data);
extern int drm_gem_name_info(struct seq_file *m, void *data);
extern int drm_gem_object_info(struct seq_file *m, void* data);
+extern int drm_gem_clients_info(struct seq_file *m, void *data);
+extern int drm_ttm_mem_info(struct seq_file *m, void* data);
#if DRM_DEBUG_CODE
extern int drm_vma_info(struct seq_file *m, void *data);
--
1.6.0.6

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,206 @@
From: Greg Kroah-Hartman <gregkh@suse.de>
Subject: Samsung backlight driver
This driver implements backlight controls for Samsung laptops that currently do not have ACPI support for this control.
It has been tested on the N130 laptop and properly works there.
Info for the NC10 was provided by Soeren Sonnenburg <bugreports@nn7.de> Info for the NP-Q45 from Jie Huchet <jeremie@lamah.info>
Many thanks to Dmitry Torokhov <dmitry.torokhov@gmail.com> for cleanups and other suggestions on how to make the driver simpler.
Cc: Soeren Sonnenburg <bugreports@nn7.de>
Cc: Jie Huchet <jeremie@lamah.info>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/platform/x86/Kconfig | 12 ++
drivers/platform/x86/Makefile | 1
drivers/platform/x86/samsung-backlight.c | 157
+++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+)
diff -purN vanilla-2.6.31-rc6/drivers/platform/x86/Kconfig linux-2.6.31-rc6/drivers/platform/x86/Kconfig
--- vanilla-2.6.31-rc6/drivers/platform/x86/Kconfig 2009-08-17 20:55:37.000000000 +0000
+++ linux-2.6.31-rc6/drivers/platform/x86/Kconfig 2009-08-17 20:58:25.000000000 +0000
@@ -425,4 +425,16 @@ config ACPI_TOSHIBA
If you have a legacy free Toshiba laptop (such as the Libretto L1
series), say Y.
+
+config SAMSUNG_BACKLIGHT
+ tristate "Samsung Backlight driver"
+ depends on BACKLIGHT_CLASS_DEVICE
+ depends on DMI
+ ---help---
+ This driver adds support to control the backlight on a number of
+ Samsung laptops, like the N130.
+
+ It will only be loaded on laptops that properly need it, so it is
+ safe to say Y here.
+
endif # X86_PLATFORM_DEVICES
diff -purN vanilla-2.6.31-rc6/drivers/platform/x86/Makefile linux-2.6.31-rc6/drivers/platform/x86/Makefile
--- vanilla-2.6.31-rc6/drivers/platform/x86/Makefile 2009-08-17 20:55:37.000000000 +0000
+++ linux-2.6.31-rc6/drivers/platform/x86/Makefile 2009-08-17 20:58:44.000000000 +0000
@@ -20,3 +20,4 @@ obj-$(CONFIG_INTEL_MENLOW) += intel_menl
obj-$(CONFIG_ACPI_WMI) += wmi.o
obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
+obj-$(CONFIG_SAMSUNG_BACKLIGHT) += samsung-backlight.o
diff -purN vanilla-2.6.31-rc6/drivers/platform/x86/samsung-backlight.c linux-2.6.31-rc6/drivers/platform/x86/samsung-backlight.c
--- vanilla-2.6.31-rc6/drivers/platform/x86/samsung-backlight.c 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.31-rc6/drivers/platform/x86/samsung-backlight.c 2009-08-17 21:00:10.000000000 +0000
@@ -0,0 +1,151 @@
+/*
+ * Samsung N130 and NC10 Laptop Backlight driver
+ *
+ * Copyright (C) 2009 Greg Kroah-Hartman (gregkh@suse.de)
+ * Copyright (C) 2009 Novell Inc.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+#include <linux/dmi.h>
+
+#define MAX_BRIGHT 0xff
+#define OFFSET 0xf4
+
+static int offset = OFFSET;
+module_param(offset, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(offset, "The offset into the PCI device for the brightness control");
+static struct pci_dev *pci_device;
+static struct backlight_device *backlight_device;
+
+static u8 read_brightness(void)
+{
+ u8 brightness;
+
+ pci_read_config_byte(pci_device, offset, &brightness);
+ return brightness;
+}
+
+static void set_brightness(u8 brightness) {
+ pci_write_config_byte(pci_device, offset, brightness); }
+
+static int get_brightness(struct backlight_device *bd) {
+ return bd->props.brightness;
+}
+
+static int update_status(struct backlight_device *bd) {
+ set_brightness(bd->props.brightness);
+ return 0;
+}
+
+static struct backlight_ops backlight_ops = {
+ .get_brightness = get_brightness,
+ .update_status = update_status,
+};
+
+static int __init dmi_check_cb(const struct dmi_system_id *id) {
+ printk(KERN_INFO KBUILD_MODNAME ": found laptop model '%s'\n",
+ id->ident);
+ return 0;
+}
+
+static struct dmi_system_id __initdata samsung_dmi_table[] = {
+ {
+ .ident = "N120",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "N120"),
+ DMI_MATCH(DMI_BOARD_NAME, "N120"),
+ },
+ .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"),
+ },
+ .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,
+ },
+ { },
+};
+
+static int __init samsung_init(void)
+{
+ if (!dmi_check_system(samsung_dmi_table))
+ return -ENODEV;
+
+ /*
+ * The Samsung N120, N130, and NC10 use pci device id 0x27ae, while the
+ * NP-Q45 uses 0x2a02. Odds are we might need to add more to the
+ * list over time...
+ */
+ pci_device = pci_get_device(PCI_VENDOR_ID_INTEL, 0x27ae, NULL);
+ if (!pci_device) {
+ pci_device = pci_get_device(PCI_VENDOR_ID_INTEL, 0x2a02, NULL);
+ if (!pci_device)
+ return -ENODEV;
+ }
+
+ /* create a backlight device to talk to this one */
+ backlight_device = backlight_device_register("samsung",
+ &pci_device->dev,
+ NULL, &backlight_ops);
+ if (IS_ERR(backlight_device)) {
+ pci_dev_put(pci_device);
+ return PTR_ERR(backlight_device);
+ }
+
+ backlight_device->props.max_brightness = MAX_BRIGHT;
+ backlight_device->props.brightness = read_brightness();
+ backlight_device->props.power = FB_BLANK_UNBLANK;
+ backlight_update_status(backlight_device);
+
+ return 0;
+}
+
+static void __exit samsung_exit(void)
+{
+ backlight_device_unregister(backlight_device);
+
+ /* we are done with the PCI device, put it back */
+ pci_dev_put(pci_device);
+}
+
+module_init(samsung_init);
+module_exit(samsung_exit);
+
+MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
+MODULE_DESCRIPTION("Samsung Backlight driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("dmi:*:svnSAMSUNGELECTRONICSCO.,LTD.:pnN120:*:rnN120:*");
+MODULE_ALIAS("dmi:*:svnSAMSUNGELECTRONICSCO.,LTD.:pnN130:*:rnN130:*");
+MODULE_ALIAS("dmi:*:svnSAMSUNGELECTRONICSCO.,LTD.:pnNC10:*:rnNC10:*");
+MODULE_ALIAS("dmi:*:svnSAMSUNGELECTRONICSCO.,LTD.:pnSQ45S70S:*:rnSQ45S70S:*");

View File

@ -0,0 +1,14 @@
KERN_ERR is not appropriate for a printk level of a successful operation
--- linux-2.6.30/drivers/hid/hid-wacom.c~ 2009-09-04 10:37:20.000000000 -0700
+++ linux-2.6.30/drivers/hid/hid-wacom.c 2009-09-04 10:37:20.000000000 -0700
@@ -244,7 +244,7 @@
ret = hid_register_driver(&wacom_driver);
if (ret)
printk(KERN_ERR "can't register wacom driver\n");
- printk(KERN_ERR "wacom driver registered\n");
+ printk(KERN_INFO "wacom driver registered\n");
return ret;
}

View File

@ -0,0 +1,173 @@
From edeae90d635501a632efa0c7fe0667aa2cbe29be Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <arjan@linux.intel.com>
Date: Mon, 28 Sep 2009 15:14:04 +0200
Subject: [PATCH] acpi: Provide a set of tables to check the BIOS tables for correctness
Today, the BIOS provides us with latency information for each C state.
Unfortunately this information is sometimes put into the BIOS by
apprentice BIOS programmers in a hurry, and as a result, it occasionally
contains utter garbage.
This patch adds a table based verification; if the CPU is known in the table,
the values the BIOS provides to us are corrected for the apprentice-factor
so that the CPUIDLE code can rely on the latency and break-even values
to be reasonably sane.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
---
drivers/acpi/Makefile | 2 +-
drivers/acpi/processor_idle.c | 3 +
drivers/acpi/processor_mwait_table.c | 110 ++++++++++++++++++++++++++++++++++
include/acpi/processor.h | 3 +
4 files changed, 117 insertions(+), 1 deletions(-)
create mode 100644 drivers/acpi/processor_mwait_table.c
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 82cd49d..ab56b28 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -60,5 +60,5 @@ obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o
# processor has its own "processor." module_param namespace
processor-y := processor_core.o processor_throttling.o
-processor-y += processor_idle.o processor_thermal.o
+processor-y += processor_idle.o processor_thermal.o processor_mwait_table.o
processor-$(CONFIG_CPU_FREQ) += processor_perflib.o
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index cc61a62..db444a0 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -1088,6 +1088,9 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
state->target_residency = cx->latency * latency_factor;
state->power_usage = cx->power;
+ if (cx->entry_method == ACPI_CSTATE_FFH)
+ acpi_verify_mwait_data(state, cx);
+
state->flags = 0;
switch (cx->type) {
case ACPI_STATE_C1:
diff --git a/drivers/acpi/processor_mwait_table.c b/drivers/acpi/processor_mwait_table.c
new file mode 100644
index 0000000..f29c28c
--- /dev/null
+++ b/drivers/acpi/processor_mwait_table.c
@@ -0,0 +1,102 @@
+/*
+ * processor_mwait_table.c: BIOS table verification/correction
+ *
+ * (C) Copyright 2009 Intel Corporation
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <asm/processor.h>
+#include <linux/acpi.h>
+#include <acpi/processor.h>
+#include <linux/cpuidle.h>
+
+
+#define ATLEAST 1
+#define ATMOST 2
+#define EXACTLY 3
+
+#define MAX_ENTRIES 12
+
+struct mwait_entry {
+ unsigned int mwait_value;
+ unsigned long exit_latency;
+ unsigned long break_even_point;
+ int compare_method;
+};
+
+struct cpu_entry {
+ int vendor;
+ int family;
+ int model;
+
+ struct mwait_entry entries[MAX_ENTRIES];
+};
+
+static struct cpu_entry mwait_entries[] =
+{
+ /* Intel "Atom" CPUs */
+ {.vendor = X86_VENDOR_INTEL, .family = 6, . model = 28,
+ .entries = {
+ {0x00, 1, 1, ATLEAST},
+ {0x10, 2, 20, ATLEAST},
+ {0x30, 57, 300, ATLEAST},
+ {0x50, 64, 4000, ATLEAST},
+ }
+ },
+
+
+};
+
+
+static unsigned long
+compare_and_set(unsigned long original, unsigned long new, int compare)
+{
+ if (compare == EXACTLY)
+ return new;
+ if (compare == ATLEAST && new > original)
+ return new;
+ if (compare == ATMOST && new < original)
+ return new;
+ return original;
+}
+
+
+void acpi_verify_mwait_data(struct cpuidle_state *state,
+ struct acpi_processor_cx *cx)
+{
+#if defined(__i386__) || defined(__x86_64__)
+ int i;
+
+ struct cpuinfo_x86 *cpudata = &boot_cpu_data;
+
+
+ for (i = 0; i < ARRAY_SIZE(mwait_entries); i++) {
+ int j;
+ if (mwait_entries[i].vendor != cpudata->x86_vendor)
+ continue;
+ if (mwait_entries[i].family != cpudata->x86)
+ continue;
+ if (mwait_entries[i].model != cpudata->x86_model)
+ continue;
+ for (j = 0; j < ARRAY_SIZE(mwait_entries[i].entries); j++) {
+ if (!mwait_entries[i].entries[j].compare_method)
+ continue;
+ if (mwait_entries[i].entries[j].mwait_value != cx->address)
+ continue;
+ state->exit_latency = compare_and_set(state->exit_latency,
+ mwait_entries[i].entries[j].exit_latency,
+ mwait_entries[i].entries[j].compare_method);
+ state->target_residency = compare_and_set(state->target_residency,
+ mwait_entries[i].entries[j].break_even_point,
+ mwait_entries[i].entries[j].compare_method);
+ break;
+ }
+ }
+#endif
+}
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 740ac3a..175e4d1 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -352,5 +352,8 @@ static inline void acpi_thermal_cpufreq_exit(void)
return;
}
#endif
+extern void acpi_verify_mwait_data(struct cpuidle_state *state,
+ struct acpi_processor_cx *cx);
+
#endif
--
1.6.2.5

View File

@ -0,0 +1,407 @@
From f890417fc5dc4450e1dab69d7a870d6e706825a5 Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <arjan@linux.intel.com>
Date: Sun, 20 Sep 2009 08:45:07 +0200
Subject: [PATCH] cpuidle: Fix the menu governor to boost IO performance
Fix the menu idle governor which balances power savings, energy efficiency
and performance impact.
The reason for a reworked governor is that there have been serious
performance issues reported with the existing code on Nehalem server
systems.
To show this I'm sure Andrew wants to see benchmark results:
(benchmark is "fio", "no cstates" is using "idle=poll")
no cstates current linux new algorithm
1 disk 107 Mb/s 85 Mb/s 105 Mb/s
2 disks 215 Mb/s 123 Mb/s 209 Mb/s
12 disks 590 Mb/s 320 Mb/s 585 Mb/s
In various power benchmark measurements, no degredation was found by our
measurement&diagnostics team. Obviously a small percentage more power
was used in the "fio" benchmark, due to the much higher performance.
While it would be a novel idea to describe the new algorithm in this
commit message, I cheaped out and described it in comments in the code
instead.
[changes in v2: spelling fixes from akpm, review feedback,
folded menu-tng into menu.c
changes in v3: use this_rq() as per akpm suggestion]
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Cc: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Cc: Len Brown <lenb@kernel.org>
Acked-by: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Yanmin Zhang <yanmin_zhang@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/cpuidle/governors/menu.c | 251 ++++++++++++++++++++++++++++++++------
include/linux/sched.h | 4 +
kernel/sched.c | 13 ++
3 files changed, 229 insertions(+), 39 deletions(-)
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index f1df59f..9f3d775 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -2,8 +2,12 @@
* menu.c - the menu idle governor
*
* Copyright (C) 2006-2007 Adam Belay <abelay@novell.com>
+ * Copyright (C) 2009 Intel Corporation
+ * Author:
+ * Arjan van de Ven <arjan@linux.intel.com>
*
- * This code is licenced under the GPL.
+ * This code is licenced under the GPL version 2 as described
+ * in the COPYING file that acompanies the Linux Kernel.
*/
#include <linux/kernel.h>
@@ -13,20 +17,153 @@
#include <linux/ktime.h>
#include <linux/hrtimer.h>
#include <linux/tick.h>
+#include <linux/sched.h>
-#define BREAK_FUZZ 4 /* 4 us */
-#define PRED_HISTORY_PCT 50
+#define BUCKETS 12
+#define RESOLUTION 1024
+#define DECAY 4
+#define MAX_INTERESTING 50000
+
+/*
+ * Concepts and ideas behind the menu governor
+ *
+ * For the menu governor, there are 3 decision factors for picking a C
+ * state:
+ * 1) Energy break even point
+ * 2) Performance impact
+ * 3) Latency tolerance (from pmqos infrastructure)
+ * These these three factors are treated independently.
+ *
+ * Energy break even point
+ * -----------------------
+ * C state entry and exit have an energy cost, and a certain amount of time in
+ * the C state is required to actually break even on this cost. CPUIDLE
+ * provides us this duration in the "target_residency" field. So all that we
+ * need is a good prediction of how long we'll be idle. Like the traditional
+ * menu governor, we start with the actual known "next timer event" time.
+ *
+ * Since there are other source of wakeups (interrupts for example) than
+ * the next timer event, this estimation is rather optimistic. To get a
+ * more realistic estimate, a correction factor is applied to the estimate,
+ * that is based on historic behavior. For example, if in the past the actual
+ * duration always was 50% of the next timer tick, the correction factor will
+ * be 0.5.
+ *
+ * menu uses a running average for this correction factor, however it uses a
+ * set of factors, not just a single factor. This stems from the realization
+ * that the ratio is dependent on the order of magnitude of the expected
+ * duration; if we expect 500 milliseconds of idle time the likelihood of
+ * getting an interrupt very early is much higher than if we expect 50 micro
+ * seconds of idle time. A second independent factor that has big impact on
+ * the actual factor is if there is (disk) IO outstanding or not.
+ * (as a special twist, we consider every sleep longer than 50 milliseconds
+ * as perfect; there are no power gains for sleeping longer than this)
+ *
+ * For these two reasons we keep an array of 12 independent factors, that gets
+ * indexed based on the magnitude of the expected duration as well as the
+ * "is IO outstanding" property.
+ *
+ * Limiting Performance Impact
+ * ---------------------------
+ * C states, especially those with large exit latencies, can have a real
+ * noticable impact on workloads, which is not acceptable for most sysadmins,
+ * and in addition, less performance has a power price of its own.
+ *
+ * As a general rule of thumb, menu assumes that the following heuristic
+ * holds:
+ * The busier the system, the less impact of C states is acceptable
+ *
+ * This rule-of-thumb is implemented using a performance-multiplier:
+ * If the exit latency times the performance multiplier is longer than
+ * the predicted duration, the C state is not considered a candidate
+ * for selection due to a too high performance impact. So the higher
+ * this multiplier is, the longer we need to be idle to pick a deep C
+ * state, and thus the less likely a busy CPU will hit such a deep
+ * C state.
+ *
+ * Two factors are used in determing this multiplier:
+ * a value of 10 is added for each point of "per cpu load average" we have.
+ * a value of 5 points is added for each process that is waiting for
+ * IO on this CPU.
+ * (these values are experimentally determined)
+ *
+ * The load average factor gives a longer term (few seconds) input to the
+ * decision, while the iowait value gives a cpu local instantanious input.
+ * The iowait factor may look low, but realize that this is also already
+ * represented in the system load average.
+ *
+ */
struct menu_device {
int last_state_idx;
unsigned int expected_us;
- unsigned int predicted_us;
- unsigned int current_predicted_us;
- unsigned int last_measured_us;
- unsigned int elapsed_us;
+ u64 predicted_us;
+ unsigned int measured_us;
+ unsigned int exit_us;
+ unsigned int bucket;
+ u64 correction_factor[BUCKETS];
};
+
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+
+static int get_loadavg(void)
+{
+ unsigned long this = this_cpu_load();
+
+
+ return LOAD_INT(this) * 10 + LOAD_FRAC(this) / 10;
+}
+
+static inline int which_bucket(unsigned int duration)
+{
+ int bucket = 0;
+
+ /*
+ * We keep two groups of stats; one with no
+ * IO pending, one without.
+ * This allows us to calculate
+ * E(duration)|iowait
+ */
+ if (nr_iowait_cpu())
+ bucket = BUCKETS/2;
+
+ if (duration < 10)
+ return bucket;
+ if (duration < 100)
+ return bucket + 1;
+ if (duration < 1000)
+ return bucket + 2;
+ if (duration < 10000)
+ return bucket + 3;
+ if (duration < 100000)
+ return bucket + 4;
+ return bucket + 5;
+}
+
+/*
+ * Return a multiplier for the exit latency that is intended
+ * to take performance requirements into account.
+ * The more performance critical we estimate the system
+ * to be, the higher this multiplier, and thus the higher
+ * the barrier to go to an expensive C state.
+ */
+static inline int performance_multiplier(void)
+{
+ int mult = 1;
+
+ /* for higher loadavg, we are more reluctant */
+
+ mult += 2 * get_loadavg();
+
+ /* for IO wait tasks (per cpu!) we add 5x each */
+ mult += 10 * nr_iowait_cpu();
+
+ return mult;
+}
+
static DEFINE_PER_CPU(struct menu_device, menu_devices);
/**
@@ -38,37 +175,59 @@ static int menu_select(struct cpuidle_device *dev)
struct menu_device *data = &__get_cpu_var(menu_devices);
int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
int i;
+ int multiplier;
+
+ data->last_state_idx = 0;
+ data->exit_us = 0;
/* Special case when user has set very strict latency requirement */
- if (unlikely(latency_req == 0)) {
- data->last_state_idx = 0;
+ if (unlikely(latency_req == 0))
return 0;
- }
- /* determine the expected residency time */
+ /* determine the expected residency time, round up */
data->expected_us =
- (u32) ktime_to_ns(tick_nohz_get_sleep_length()) / 1000;
+ DIV_ROUND_UP((u32)ktime_to_ns(tick_nohz_get_sleep_length()), 1000);
+
+
+ data->bucket = which_bucket(data->expected_us);
+
+ multiplier = performance_multiplier();
+
+ /*
+ * if the correction factor is 0 (eg first time init or cpu hotplug
+ * etc), we actually want to start out with a unity factor.
+ */
+ if (data->correction_factor[data->bucket] == 0)
+ data->correction_factor[data->bucket] = RESOLUTION * DECAY;
+
+ /* Make sure to round up for half microseconds */
+ data->predicted_us = DIV_ROUND_CLOSEST(
+ data->expected_us * data->correction_factor[data->bucket],
+ RESOLUTION * DECAY);
+
+ /*
+ * We want to default to C1 (hlt), not to busy polling
+ * unless the timer is happening really really soon.
+ */
+ if (data->expected_us > 5)
+ data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
- /* Recalculate predicted_us based on prediction_history_pct */
- data->predicted_us *= PRED_HISTORY_PCT;
- data->predicted_us += (100 - PRED_HISTORY_PCT) *
- data->current_predicted_us;
- data->predicted_us /= 100;
/* find the deepest idle state that satisfies our constraints */
- for (i = CPUIDLE_DRIVER_STATE_START + 1; i < dev->state_count; i++) {
+ for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) {
struct cpuidle_state *s = &dev->states[i];
- if (s->target_residency > data->expected_us)
- break;
if (s->target_residency > data->predicted_us)
break;
if (s->exit_latency > latency_req)
break;
+ if (s->exit_latency * multiplier > data->predicted_us)
+ break;
+ data->exit_us = s->exit_latency;
+ data->last_state_idx = i;
}
- data->last_state_idx = i - 1;
- return i - 1;
+ return data->last_state_idx;
}
/**
@@ -85,35 +244,49 @@ static void menu_reflect(struct cpuidle_device *dev)
unsigned int last_idle_us = cpuidle_get_last_residency(dev);
struct cpuidle_state *target = &dev->states[last_idx];
unsigned int measured_us;
+ u64 new_factor;
/*
* Ugh, this idle state doesn't support residency measurements, so we
* are basically lost in the dark. As a compromise, assume we slept
- * for one full standard timer tick. However, be aware that this
- * could potentially result in a suboptimal state transition.
+ * for the whole expected time.
*/
if (unlikely(!(target->flags & CPUIDLE_FLAG_TIME_VALID)))
- last_idle_us = USEC_PER_SEC / HZ;
+ last_idle_us = data->expected_us;
+
+
+ measured_us = last_idle_us;
/*
- * measured_us and elapsed_us are the cumulative idle time, since the
- * last time we were woken out of idle by an interrupt.
+ * We correct for the exit latency; we are assuming here that the
+ * exit latency happens after the event that we're interested in.
*/
- if (data->elapsed_us <= data->elapsed_us + last_idle_us)
- measured_us = data->elapsed_us + last_idle_us;
+ if (measured_us > data->exit_us)
+ measured_us -= data->exit_us;
+
+
+ /* update our correction ratio */
+
+ new_factor = data->correction_factor[data->bucket]
+ * (DECAY - 1) / DECAY;
+
+ if (data->expected_us > 0 && data->measured_us < MAX_INTERESTING)
+ new_factor += RESOLUTION * measured_us / data->expected_us;
else
- measured_us = -1;
+ /*
+ * we were idle so long that we count it as a perfect
+ * prediction
+ */
+ new_factor += RESOLUTION;
- /* Predict time until next break event */
- data->current_predicted_us = max(measured_us, data->last_measured_us);
+ /*
+ * We don't want 0 as factor; we always want at least
+ * a tiny bit of estimated time.
+ */
+ if (new_factor == 0)
+ new_factor = 1;
- if (last_idle_us + BREAK_FUZZ <
- data->expected_us - target->exit_latency) {
- data->last_measured_us = measured_us;
- data->elapsed_us = 0;
- } else {
- data->elapsed_us = measured_us;
- }
+ data->correction_factor[data->bucket] = new_factor;
}
/**
diff --git a/include/linux/sched.h b/include/linux/sched.h
index cdc1298..d559406 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -140,6 +140,10 @@ extern int nr_processes(void);
extern unsigned long nr_running(void);
extern unsigned long nr_uninterruptible(void);
extern unsigned long nr_iowait(void);
+extern unsigned long nr_iowait_cpu(void);
+extern unsigned long this_cpu_load(void);
+
+
extern void calc_global_load(void);
extern u64 cpu_nr_migrations(int cpu);
diff --git a/kernel/sched.c b/kernel/sched.c
index 4dbe8e7..541b370 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -2910,6 +2910,19 @@ unsigned long nr_iowait(void)
return sum;
}
+unsigned long nr_iowait_cpu(void)
+{
+ struct rq *this = this_rq();
+ return atomic_read(&this->nr_iowait);
+}
+
+unsigned long this_cpu_load(void)
+{
+ struct rq *this = this_rq();
+ return this->cpu_load[0];
+}
+
+
/* Variables and functions for calc_load */
static atomic_long_t calc_load_tasks;
static unsigned long calc_load_update;
--
1.6.0.6

View File

@ -0,0 +1,86 @@
commit ee5aa7b8b98774f408d20a2f61f97a89ac66c29b
Author: Joe Peterson <joe@skyrush.com>
Date: Wed Sep 9 15:03:13 2009 -0600
n_tty: honor opost flag for echoes
Fixes the following bug:
http://bugs.linuxbase.org/show_bug.cgi?id=2692
Causes processing of echoed characters (output from the echo buffer) to
honor the O_OPOST flag, which is consistent with the old behavior.
Note that this and the next patch ("n_tty: move echoctl check and
clean up logic") were verified together by the bug reporters, and
the test now passes.
Signed-off-by: Joe Peterson <joe@skyrush.com>
Cc: Linux Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 4e28b35..e6eeeb2 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -272,7 +272,8 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty)
*
* This is a helper function that handles one output character
* (including special characters like TAB, CR, LF, etc.),
- * putting the results in the tty driver's write buffer.
+ * doing OPOST processing and putting the results in the
+ * tty driver's write buffer.
*
* Note that Linux currently ignores TABDLY, CRDLY, VTDLY, FFDLY
* and NLDLY. They simply aren't relevant in the world today.
@@ -350,8 +351,9 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
* @c: character (or partial unicode symbol)
* @tty: terminal device
*
- * Perform OPOST processing. Returns -1 when the output device is
- * full and the character must be retried.
+ * Output one character with OPOST processing.
+ * Returns -1 when the output device is full and the character
+ * must be retried.
*
* Locking: output_lock to protect column state and space left
* (also, this is called from n_tty_write under the
@@ -377,8 +379,11 @@ static int process_output(unsigned char c, struct tty_struct *tty)
/**
* process_output_block - block post processor
* @tty: terminal device
- * @inbuf: user buffer
- * @nr: number of bytes
+ * @buf: character buffer
+ * @nr: number of bytes to output
+ *
+ * Output a block of characters with OPOST processing.
+ * Returns the number of characters output.
*
* This path is used to speed up block console writes, among other
* things when processing blocks of output data. It handles only
@@ -605,12 +610,18 @@ static void process_echoes(struct tty_struct *tty)
if (no_space_left)
break;
} else {
- int retval;
-
- retval = do_output_char(c, tty, space);
- if (retval < 0)
- break;
- space -= retval;
+ if (O_OPOST(tty) &&
+ !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) {
+ int retval = do_output_char(c, tty, space);
+ if (retval < 0)
+ break;
+ space -= retval;
+ } else {
+ if (!space)
+ break;
+ tty_put_char(tty, c);
+ space -= 1;
+ }
cp += 1;
nr -= 1;
}

View File

@ -0,0 +1,91 @@
commit 62b263585bb5005d44a764c90d80f9c4bb8188c1
Author: Joe Peterson <joe@skyrush.com>
Date: Wed Sep 9 15:03:47 2009 -0600
n_tty: move echoctl check and clean up logic
Check L_ECHOCTL before insertting a character in the echo buffer
(rather than as the buffer is processed), to be more consistent with
when all other L_ flags are checked. Also cleaned up the related logic.
Note that this and the previous patch ("n_tty: honor opost flag for echoes")
were verified together by the reporters of the bug that patch addresses
(http://bugs.linuxbase.org/show_bug.cgi?id=2692), and the test now passes.
Signed-off-by: Joe Peterson <joe@skyrush.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index e6eeeb2..2e50f4d 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -576,33 +576,23 @@ static void process_echoes(struct tty_struct *tty)
break;
default:
- if (iscntrl(op)) {
- if (L_ECHOCTL(tty)) {
- /*
- * Ensure there is enough space
- * for the whole ctrl pair.
- */
- if (space < 2) {
- no_space_left = 1;
- break;
- }
- tty_put_char(tty, '^');
- tty_put_char(tty, op ^ 0100);
- tty->column += 2;
- space -= 2;
- } else {
- if (!space) {
- no_space_left = 1;
- break;
- }
- tty_put_char(tty, op);
- space--;
- }
- }
/*
- * If above falls through, this was an
- * undefined op.
+ * If the op is not a special byte code,
+ * it is a ctrl char tagged to be echoed
+ * as "^X" (where X is the letter
+ * representing the control char).
+ * Note that we must ensure there is
+ * enough space for the whole ctrl pair.
+ *
*/
+ if (space < 2) {
+ no_space_left = 1;
+ break;
+ }
+ tty_put_char(tty, '^');
+ tty_put_char(tty, op ^ 0100);
+ tty->column += 2;
+ space -= 2;
cp += 2;
nr -= 2;
}
@@ -809,8 +799,8 @@ static void echo_char_raw(unsigned char c, struct tty_struct *tty)
* Echo user input back onto the screen. This must be called only when
* L_ECHO(tty) is true. Called from the driver receive_buf path.
*
- * This variant tags control characters to be possibly echoed as
- * as "^X" (where X is the letter representing the control char).
+ * This variant tags control characters to be echoed as "^X"
+ * (where X is the letter representing the control char).
*
* Locking: echo_lock to protect the echo buffer
*/
@@ -823,7 +813,7 @@ static void echo_char(unsigned char c, struct tty_struct *tty)
add_echo_byte(ECHO_OP_START, tty);
add_echo_byte(ECHO_OP_START, tty);
} else {
- if (iscntrl(c) && c != '\t')
+ if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t')
add_echo_byte(ECHO_OP_START, tty);
add_echo_byte(c, tty);
}

View File

@ -0,0 +1,64 @@
From 33725d4939f457b12d7bc1bcbcc0dfb8b2f5bd48 Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <arjan@linux.intel.com>
Date: Thu, 24 Sep 2009 13:24:16 +0200
Subject: [PATCH] x86, timers: check for pending timers after (device) interrupts
Now that range timers and deferred timers are common, I found a
problem with these using the "perf timechart" tool.
It turns out that on x86, these two 'opportunistic' timers only
get checked when another "real" timer happens.
These opportunistic timers have the objective to save power by
hitchhiking on other wakeups, as to avoid CPU wakeups by themselves
as much as possible.
The change in this patch runs this check not only at timer interrupts,
but at all (device) interrupts. The effect is that
1) the deferred timers/range timers get delayed less
2) the range timers cause less wakeups by themselves because
the percentage of hitchhiking on existing wakeup events goes up.
I've verified the working of the patch using "perf timechart",
the original exposed bug is gone with this patch.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
---
arch/x86/kernel/irq.c | 2 ++
arch/x86/kernel/smp.c | 1 +
2 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 74656d1..3912061 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -244,6 +244,7 @@ unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
__func__, smp_processor_id(), vector, irq);
}
+ run_local_timers();
irq_exit();
set_irq_regs(old_regs);
@@ -268,6 +269,7 @@ void smp_generic_interrupt(struct pt_regs *regs)
if (generic_interrupt_extension)
generic_interrupt_extension();
+ run_local_timers();
irq_exit();
set_irq_regs(old_regs);
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index ec1de97..d915d95 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -198,6 +198,7 @@ void smp_reschedule_interrupt(struct pt_regs *regs)
{
ack_APIC_irq();
inc_irq_stat(irq_resched_count);
+ run_local_timers();
/*
* KVM uses this interrupt to force a cpu out of guest mode
*/
--
1.6.0.6

View File

@ -0,0 +1,275 @@
From 524a1da3c45683cec77480acc6cab1d33ae8d5cb Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <arjan@linux.intel.com>
Date: Sat, 26 Sep 2009 12:36:21 +0200
Subject: [PATCH] x86: Use __builtin_object_size to validate the buffer size for copy_from_user
gcc (4.x) supports the __builtin_object_size() builtin, which reports the
size of an object that a pointer point to, when known at compile time.
If the buffer size is not known at compile time, a constant -1 is returned.
This patch uses this feature to add a sanity check to copy_from_user();
if the target buffer is known to be smaller than the copy size, the copy
is aborted and a WARNing is emitted in memory debug mode.
These extra checks compile away when the object size is not known,
or if both the buffer size and the copy length are constants.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Reviewed-by: Ingo Molnar <mingo@elte.hu>
---
arch/x86/include/asm/uaccess_32.h | 19 ++++++++++++++++++-
arch/x86/include/asm/uaccess_64.h | 19 ++++++++++++++++++-
arch/x86/kernel/x8664_ksyms_64.c | 2 +-
arch/x86/lib/copy_user_64.S | 4 ++--
arch/x86/lib/usercopy_32.c | 4 ++--
include/linux/compiler-gcc4.h | 2 ++
include/linux/compiler.h | 4 ++++
7 files changed, 47 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 632fb44..582d6ae 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -187,9 +187,26 @@ __copy_from_user_inatomic_nocache(void *to, const void __user *from,
unsigned long __must_check copy_to_user(void __user *to,
const void *from, unsigned long n);
-unsigned long __must_check copy_from_user(void *to,
+unsigned long __must_check _copy_from_user(void *to,
const void __user *from,
unsigned long n);
+
+static inline unsigned long __must_check copy_from_user(void *to,
+ const void __user *from,
+ unsigned long n)
+{
+ int sz = __compiletime_object_size(to);
+ int ret = -EFAULT;
+
+ if (likely(sz == -1 || sz >= n))
+ ret = _copy_from_user(to, from, n);
+#ifdef CONFIG_DEBUG_VM
+ else
+ WARN(1, "Buffer overflow detected!\n");
+#endif
+ return ret;
+}
+
long __must_check strncpy_from_user(char *dst, const char __user *src,
long count);
long __must_check __strncpy_from_user(char *dst,
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index db24b21..ce6fec7 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -21,10 +21,27 @@ copy_user_generic(void *to, const void *from, unsigned len);
__must_check unsigned long
copy_to_user(void __user *to, const void *from, unsigned len);
__must_check unsigned long
-copy_from_user(void *to, const void __user *from, unsigned len);
+_copy_from_user(void *to, const void __user *from, unsigned len);
__must_check unsigned long
copy_in_user(void __user *to, const void __user *from, unsigned len);
+static inline unsigned long __must_check copy_from_user(void *to,
+ const void __user *from,
+ unsigned long n)
+{
+ int sz = __compiletime_object_size(to);
+ int ret = -EFAULT;
+
+ if (likely(sz == -1 || sz >= n))
+ ret = _copy_from_user(to, from, n);
+#ifdef CONFIG_DEBUG_VM
+ else
+ WARN(1, "Buffer overflow detected!\n");
+#endif
+ return ret;
+}
+
+
static __always_inline __must_check
int __copy_from_user(void *dst, const void __user *src, unsigned size)
{
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 3909e3b..a0cdd8c 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -30,7 +30,7 @@ EXPORT_SYMBOL(__put_user_8);
EXPORT_SYMBOL(copy_user_generic);
EXPORT_SYMBOL(__copy_user_nocache);
-EXPORT_SYMBOL(copy_from_user);
+EXPORT_SYMBOL(_copy_from_user);
EXPORT_SYMBOL(copy_to_user);
EXPORT_SYMBOL(__copy_from_user_inatomic);
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
index 6ba0f7b..4be3c41 100644
--- a/arch/x86/lib/copy_user_64.S
+++ b/arch/x86/lib/copy_user_64.S
@@ -78,7 +78,7 @@ ENTRY(copy_to_user)
ENDPROC(copy_to_user)
/* Standard copy_from_user with segment limit checking */
-ENTRY(copy_from_user)
+ENTRY(_copy_from_user)
CFI_STARTPROC
GET_THREAD_INFO(%rax)
movq %rsi,%rcx
@@ -88,7 +88,7 @@ ENTRY(copy_from_user)
jae bad_from_user
ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
CFI_ENDPROC
-ENDPROC(copy_from_user)
+ENDPROC(_copy_from_user)
ENTRY(copy_user_generic)
CFI_STARTPROC
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index 1f118d4..8498684 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -874,7 +874,7 @@ EXPORT_SYMBOL(copy_to_user);
* data to the requested size using zero bytes.
*/
unsigned long
-copy_from_user(void *to, const void __user *from, unsigned long n)
+_copy_from_user(void *to, const void __user *from, unsigned long n)
{
if (access_ok(VERIFY_READ, from, n))
n = __copy_from_user(to, from, n);
@@ -882,4 +882,4 @@ copy_from_user(void *to, const void __user *from, unsigned long n)
memset(to, 0, n);
return n;
}
-EXPORT_SYMBOL(copy_from_user);
+EXPORT_SYMBOL(_copy_from_user);
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
index 450fa59..a3aef5d 100644
--- a/include/linux/compiler-gcc4.h
+++ b/include/linux/compiler-gcc4.h
@@ -37,3 +37,5 @@
#define __cold __attribute__((__cold__))
#endif
+
+#define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 9d4c4b0..9c42853 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -185,6 +185,10 @@ extern void __chk_io_ptr(const volatile void __iomem *);
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#endif
+/* Compile time object size, -1 for unknown */
+#ifndef __compiletime_object_size
+# define __compiletime_object_size(obj) -1
+#endif
/*
* Prevent the compiler from merging or refetching accesses. The compiler
* is also forbidden from reordering successive instances of ACCESS_ONCE(),
--
1.6.0.6
From 350cf3cd513e6759ae6852946532a47249f25600 Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <arjan@linux.intel.com>
Date: Wed, 30 Sep 2009 12:57:46 +0200
Subject: [PATCH] x86: Turn the copy_from_user check into an (optional) compile time warning
A previous patch added the buffer size check to copy_from_user().
One of the things learned from analyzing the result of the previous patch
is that in general, gcc is really good at proving that the code contains
sufficient security checks to not need to do a runtime check. But that
for those cases where gcc could not prove this, there was a relatively
high percentage of real security issues.
This patch turns the case of "gcc cannot prove" into a compile time
warning, as long as a sufficiently new gcc is in use.
The objective is that these warnings will trigger developers checking
new cases out before a security hole enters a linux kernel release.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
---
arch/x86/include/asm/uaccess_32.h | 12 +++++++++---
arch/x86/lib/usercopy_32.c | 6 ++++++
include/linux/compiler-gcc4.h | 3 +++
include/linux/compiler.h | 4 ++++
4 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 582d6ae..7826639 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -191,6 +191,13 @@ unsigned long __must_check _copy_from_user(void *to,
const void __user *from,
unsigned long n);
+
+extern void copy_from_user_overflow(void)
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+ __compiletime_warning("copy_from_user buffer size is not provably correct")
+#endif
+;
+
static inline unsigned long __must_check copy_from_user(void *to,
const void __user *from,
unsigned long n)
@@ -200,10 +207,9 @@ static inline unsigned long __must_check copy_from_user(void *to,
if (likely(sz == -1 || sz >= n))
ret = _copy_from_user(to, from, n);
-#ifdef CONFIG_DEBUG_VM
else
- WARN(1, "Buffer overflow detected!\n");
-#endif
+ copy_from_user_overflow();
+
return ret;
}
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index 8498684..e218d5d 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -883,3 +883,9 @@ _copy_from_user(void *to, const void __user *from, unsigned long n)
return n;
}
EXPORT_SYMBOL(_copy_from_user);
+
+void copy_from_user_overflow(void)
+{
+ WARN(1, "Buffer overflow detected!\n");
+}
+EXPORT_SYMBOL(copy_from_user_overflow);
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
index a3aef5d..f1709c1 100644
--- a/include/linux/compiler-gcc4.h
+++ b/include/linux/compiler-gcc4.h
@@ -39,3 +39,6 @@
#endif
#define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
+#if __GNUC_MINOR__ >= 4
+#define __compiletime_warning(message) __attribute__((warning(message)))
+#endif
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 9c42853..241dfd8 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -189,6 +189,10 @@ extern void __chk_io_ptr(const volatile void __iomem *);
#ifndef __compiletime_object_size
# define __compiletime_object_size(obj) -1
#endif
+#ifndef __compiletime_warning
+# define __compiletime_warning(message)
+#endif
+
/*
* Prevent the compiler from merging or refetching accesses. The compiler
* is also forbidden from reordering successive instances of ACCESS_ONCE(),
--
1.6.2.5

View File

@ -0,0 +1,95 @@
From 42cb68d81a218b0fd7c053356d379a93270b40ea Mon Sep 17 00:00:00 2001
From: Yong Wang <yong.y.wang@intel.com>
Date: Fri, 30 Oct 2009 10:33:20 +0800
Subject: [PATCH] x86: Do not unregister PIT clocksource on PIT oneshot setup/shutdown
Backported from upstream commit 8cab02dc3c58a12235c6d463ce684dded9696848
and this fixes bug #7377 "system can not resume from S3". Further information
can be found at http://bugzilla.kernel.org/show_bug.cgi?id=14222.
Signed-off-by: Yong Wang <yong.y.wang@intel.com>
---
arch/x86/kernel/i8253.c | 36 ++----------------------------------
1 files changed, 2 insertions(+), 34 deletions(-)
diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c
index da890f0..23c1679 100644
--- a/arch/x86/kernel/i8253.c
+++ b/arch/x86/kernel/i8253.c
@@ -19,14 +19,6 @@
DEFINE_SPINLOCK(i8253_lock);
EXPORT_SYMBOL(i8253_lock);
-#ifdef CONFIG_X86_32
-static void pit_disable_clocksource(void);
-static void pit_enable_clocksource(void);
-#else
-static inline void pit_disable_clocksource(void) { }
-static inline void pit_enable_clocksource(void) { }
-#endif
-
/*
* HPET replaces the PIT, when enabled. So we need to know, which of
* the two timers is used
@@ -59,17 +51,15 @@ static void init_pit_timer(enum clock_event_mode mode,
outb_pit(0, PIT_CH0);
outb_pit(0, PIT_CH0);
}
- pit_disable_clocksource();
break;
case CLOCK_EVT_MODE_ONESHOT:
/* One shot setup */
- pit_disable_clocksource();
outb_pit(0x38, PIT_MODE);
break;
case CLOCK_EVT_MODE_RESUME:
- pit_enable_clocksource();
+ /* Nothing to do here */
break;
}
spin_unlock(&i8253_lock);
@@ -202,27 +192,8 @@ static struct clocksource pit_cs = {
.shift = 20,
};
-int pit_cs_registered;
-static void pit_disable_clocksource(void)
-{
- if (pit_cs_registered) {
- clocksource_unregister(&pit_cs);
- pit_cs_registered = 0;
- }
-}
-
-static void pit_enable_clocksource(void)
-{
- if (!pit_cs_registered && !clocksource_register(&pit_cs)) {
- pit_cs_registered = 1;
- }
-}
-
-
-
static int __init init_pit_clocksource(void)
{
- int ret;
/*
* Several reasons not to register PIT as a clocksource:
*
@@ -236,10 +207,7 @@ static int __init init_pit_clocksource(void)
pit_cs.mult = clocksource_hz2mult(CLOCK_TICK_RATE, pit_cs.shift);
- ret = clocksource_register(&pit_cs);
- if (!ret)
- pit_cs_registered = 1;
- return ret;
+ return clocksource_register(&pit_cs);
}
arch_initcall(init_pit_clocksource);
--
1.5.5.1

View File

@ -0,0 +1,47 @@
require linux-moblin.inc
PR = "r0"
DEFAULT_PREFERENCE = "-1"
DEFAULT_PREFERENCE_netbook = "1"
#DEFAULT_PREFERENCE_menlow = "1"
SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/linux-2.6.31.5.tar.bz2 \
file://linux-2.6-build-nonintconfig.patch;patch=1 \
file://linux-2.6.32-cpuidle.patch;patch=1 \
file://linux-2.6.32-n_tty-honor-opost-flag-for-echoes.patch;patch=1 \
file://linux-2.6.32-n_tty-move-echoctl-check-and-clean-up-logic.patch;patch=1 \
file://linux-2.6.33-pit-fix.patch;patch=1 \
file://linux-2.6.29-dont-wait-for-mouse.patch;patch=1 \
file://linux-2.6.29-sreadahead.patch;patch=1 \
file://linux-2.6.29-kms-edid-cache.patch;patch=1 \
file://linux-2.6.29-kms-run-async.patch;patch=1 \
file://linux-2.6.29-kms-dont-blank-display.patch;patch=1 \
file://linux-2.6.29-kms-after-sata.patch;patch=1 \
file://linux-2.6.30-non-root-X.patch;patch=1 \
file://linux-2.6.31-drm-kms-flip.patch;patch=1 \
file://linux-2.6.31-drm-mem-info.patch;patch=1 \
file://linux-2.6.31-drm-i915-fix.patch;patch=1 \
file://linux-2.6.31-drm-i915-opregion.patch;patch=1 \
file://linux-2.6.31-drm-i915-vblank-fix.patch;patch=1 \
file://linux-2.6.29-silence-acer-message.patch;patch=1 \
file://linux-2.6.31-silence-wacom.patch;patch=1 \
file://linux-2.6.29-jbd-longer-commit-interval.patch;patch=1 \
file://linux-2.6.29-touchkit.patch;patch=1 \
file://linux-2.6.31-1-2-timberdale.patch;patch=1 \
file://linux-2.6.31-2-2-timberdale.patch;patch=1 \
file://linux-2.6-driver-level-usb-autosuspend.patch;patch=1 \
file://linux-2.6.31-bluetooth-suspend.patch;patch=1 \
file://linux-2.6-usb-uvc-autosuspend.patch;patch=1 \
file://linux-2.6.31-samsung.patch;patch=1 \
file://MRST-GFX-driver-consolidated.patch;patch=1 \
file://linux-2.6.31-iegd.patch;patch=1 \
file://linux-2.6.32-acpi-cstate-fixup.patch;patch=1 \
file://linux-2.6.32-timer-fix.patch;patch=1 \
file://linux-2.6.33-copy-checks.patch;patch=1 \
file://close_debug_info_of_rt2860.patch;patch=1 \
# file://i915_split.patch.patch;patch=1 \
# file://defconfig-menlow \
file://defconfig-netbook"
S = "${WORKDIR}/linux-2.6.31.5"