From fd2489f5fa1b2b670604919143a89f94c80dc2a2 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 28 Nov 2004 23:41:38 -0800 Subject: [PATCH] I2C: Add support for the nForce2 Ultra 400 to i2c-nforce2 This simple patch adds support for the nForce2 Ultra 400 to i2c-nforce2. I just made a similar update on the 2.4/CVS version of the driver. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- include/linux/pci_ids.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 5cfcf8941445..f1946ad646e4 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1087,6 +1087,7 @@ #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065 #define PCI_DEVICE_ID_NVIDIA_NVENET_2 0x0066 #define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a +#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS 0x0084 #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE 0x0085 #define PCI_DEVICE_ID_NVIDIA_NVENET_4 0x0086 #define PCI_DEVICE_ID_NVIDIA_NVENET_5 0x008c -- cgit v1.2.3 From b56211a1a9cfaf3ec49b9ca146446b47d3d704eb Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 29 Nov 2004 13:44:23 +0000 Subject: [SERIAL] Add missing definition for PORT_IMX. --- include/linux/serial_core.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 3fad76b0873c..1dd43bc63800 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -91,12 +91,15 @@ /* MPC52xx type numbers */ #define PORT_MPC52xx 59 -/*IBM icom*/ -#define PORT_ICOM 60 +/* IBM icom */ +#define PORT_ICOM 60 /* Samsung S3C2440 SoC */ #define PORT_S3C2440 61 +/* Motorola i.MX SoC */ +#define PORT_IMX 62 + #ifdef __KERNEL__ #include -- cgit v1.2.3 From 96f79c34e4075cf3e7d7bbf79707c4326a8ea9bf Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 29 Nov 2004 20:10:16 -0800 Subject: USB: move a internal usbfs only structure out of a public header file. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/usb.h | 15 +++++++++++++++ include/linux/usbdevice_fs.h | 25 ------------------------- 2 files changed, 15 insertions(+), 25 deletions(-) (limited to 'include/linux') diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 30d2cf7dd762..4035ff925c99 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -33,3 +33,18 @@ extern struct usb_driver usbfs_driver; extern struct file_operations usbfs_devices_fops; extern struct file_operations usbfs_device_file_operations; extern void usbfs_conn_disc_event(void); + +struct dev_state { + struct list_head list; /* state list */ + struct usb_device *dev; + struct file *file; + spinlock_t lock; /* protects the async urb lists */ + struct list_head async_pending; + struct list_head async_completed; + wait_queue_head_t wait; /* wake up if a request completed */ + unsigned int discsignr; + struct task_struct *disctask; + void __user *disccontext; + unsigned long ifclaimed; +}; + diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h index af49afaf7bb4..aed8193eb420 100644 --- a/include/linux/usbdevice_fs.h +++ b/include/linux/usbdevice_fs.h @@ -144,29 +144,4 @@ struct usbdevfs_hub_portinfo { #define USBDEVFS_DISCONNECT _IO('U', 22) #define USBDEVFS_CONNECT _IO('U', 23) -/* --------------------------------------------------------------------- */ - -#ifdef __KERNEL__ - -#include -#include - - -struct dev_state { - struct list_head list; /* state list */ - struct usb_device *dev; - struct file *file; - spinlock_t lock; /* protects the async urb lists */ - struct list_head async_pending; - struct list_head async_completed; - wait_queue_head_t wait; /* wake up if a request completed */ - unsigned int discsignr; - struct task_struct *disctask; - void __user *disccontext; - unsigned long ifclaimed; -}; - -#endif /* __KERNEL__ */ - -/* --------------------------------------------------------------------- */ #endif /* _LINUX_USBDEVICE_FS_H */ -- cgit v1.2.3 From d3f58c34c2a49bc9691f052ceb524a88ee46eadd Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 30 Nov 2004 06:02:46 -0800 Subject: [GNET_STATS]: kernel-api doc for gnet stats/estimator Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- Documentation/DocBook/kernel-api.tmpl | 5 ++ include/linux/gen_stats.h | 5 ++ net/core/gen_estimator.c | 35 ++++++++++++++ net/core/gen_stats.c | 90 ++++++++++++++++++++++++++++++++++- 4 files changed, 134 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 5f11984a04f3..ef66fdda129f 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -133,6 +133,11 @@ KAO --> Socket Filter !Enet/core/filter.c + Generic Network Statistics +!Iinclude/linux/gen_stats.h +!Enet/core/gen_stats.c +!Enet/core/gen_estimator.c + diff --git a/include/linux/gen_stats.h b/include/linux/gen_stats.h index ab631c3571ce..13f4e74609ac 100644 --- a/include/linux/gen_stats.h +++ b/include/linux/gen_stats.h @@ -14,6 +14,7 @@ enum { #define TCA_STATS_MAX (__TCA_STATS_MAX - 1) /** + * struct gnet_stats_basic - byte/packet throughput statistics * @bytes: number of seen bytes * @packets: number of seen packets */ @@ -24,6 +25,7 @@ struct gnet_stats_basic }; /** + * struct gnet_stats_rate_est - rate estimator * @bps: current byte rate * @pps: current packet rate */ @@ -34,10 +36,12 @@ struct gnet_stats_rate_est }; /** + * struct gnet_stats_queue - queuing statistics * @qlen: queue length * @backlog: backlog size of queue * @drops: number of dropped packets * @requeues: number of requeues + * @overlimits: number of enqueues over the limit */ struct gnet_stats_queue { @@ -49,6 +53,7 @@ struct gnet_stats_queue }; /** + * struct gnet_estimator - rate estimator configuration * @interval: sampling period * @ewma_log: the log of measurement window weight */ diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 00e167827dd7..c9c70c6d0cfb 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -132,6 +132,21 @@ static void est_timer(unsigned long arg) read_unlock(&est_lock); } +/** + * gen_new_estimator - create a new rate estimator + * @bstats: basic statistics + * @rate_est: rate estimator statistics + * @stats_lock: statistics lock + * @opt: rate estimator configuration TLV + * + * Creates a new rate estimator with &bstats as source and &rate_est + * as destination. A new timer with the interval specified in the + * configuration TLV is created. Upon each interval, the latest statistics + * will be read from &bstats and the estimated rate will be stored in + * &rate_est with the statistics lock grabed during this period. + * + * Returns 0 on success or a negative error code. + */ int gen_new_estimator(struct gnet_stats_basic *bstats, struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, struct rtattr *opt) { @@ -173,6 +188,14 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, return 0; } +/** + * gen_kill_estimator - remove a rate estimator + * @bstats: basic statistics + * @rate_est: rate estimator statistics + * + * Removes the rate estimator specified by &bstats and &rate_est + * and deletes the timer. + */ void gen_kill_estimator(struct gnet_stats_basic *bstats, struct gnet_stats_rate_est *rate_est) { @@ -200,6 +223,18 @@ void gen_kill_estimator(struct gnet_stats_basic *bstats, } } +/** + * gen_replace_estimator - replace rate estimator configruation + * @bstats: basic statistics + * @rate_est: rate estimator statistics + * @stats_lock: statistics lock + * @opt: rate estimator configuration TLV + * + * Replaces the configuration of a rate estimator by calling + * gen_kill_estimator() and gen_new_estimator(). + * + * Returns 0 on success or a negative error code. + */ int gen_replace_estimator(struct gnet_stats_basic *bstats, struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c index a35e97b5ad8a..86cd889d0e2b 100644 --- a/net/core/gen_stats.c +++ b/net/core/gen_stats.c @@ -34,6 +34,24 @@ rtattr_failure: return -1; } +/** + * gnet_stats_start_copy_compat - start dumping procedure in compatibility mode + * @skb: socket buffer to put statistics TLVs into + * @type: TLV type for top level statistic TLV + * @tc_stats_type: TLV type for backward compatibility struct tc_stats TLV + * @xstats_type: TLV type for backward compatibility xstats TLV + * @lock: statistics lock + * @d: dumping handle + * + * Initializes the dumping handle, grabs the statistic lock and appends + * an empty TLV header to the socket buffer for use a container for all + * other statistic TLVS. + * + * The dumping handle is marked to be in backward compatibility mode telling + * all gnet_stats_copy_XXX() functions to fill a local copy of struct tc_stats. + * + * Returns 0 on success or -1 if the room in the socket buffer was not sufficient. + */ int gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type, int xstats_type, spinlock_t *lock, struct gnet_dump *d) @@ -52,6 +70,19 @@ gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type, return gnet_stats_copy(d, type, NULL, 0); } +/** + * gnet_stats_start_copy_compat - start dumping procedure in compatibility mode + * @skb: socket buffer to put statistics TLVs into + * @type: TLV type for top level statistic TLV + * @lock: statistics lock + * @d: dumping handle + * + * Initializes the dumping handle, grabs the statistic lock and appends + * an empty TLV header to the socket buffer for use a container for all + * other statistic TLVS. + * + * Returns 0 on success or -1 if the room in the socket buffer was not sufficient. + */ int gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock, struct gnet_dump *d) @@ -59,7 +90,17 @@ gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock, return gnet_stats_start_copy_compat(skb, type, 0, 0, lock, d); } - +/** + * gnet_stats_copy_basic - copy basic statistics into statistic TLV + * @d: dumping handle + * @b: basic statistics + * + * Appends the basic statistics to the top level TLV created by + * gnet_stats_start_copy(). + * + * Returns 0 on success or -1 with the statistic lock released + * if the room in the socket buffer was not sufficient. + */ int gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic *b) { @@ -71,6 +112,17 @@ gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic *b) return gnet_stats_copy(d, TCA_STATS_BASIC, b, sizeof(*b)); } +/** + * gnet_stats_copy_rate_est - copy rate estimator statistics into statistics TLV + * @d: dumping handle + * @r: rate estimator statistics + * + * Appends the rate estimator statistics to the top level TLV created by + * gnet_stats_start_copy(). + * + * Returns 0 on success or -1 with the statistic lock released + * if the room in the socket buffer was not sufficient. + */ int gnet_stats_copy_rate_est(struct gnet_dump *d, struct gnet_stats_rate_est *r) { @@ -82,6 +134,17 @@ gnet_stats_copy_rate_est(struct gnet_dump *d, struct gnet_stats_rate_est *r) return gnet_stats_copy(d, TCA_STATS_RATE_EST, r, sizeof(*r)); } +/** + * gnet_stats_copy_queue - copy queue statistics into statistics TLV + * @d: dumping handle + * @q: queue statistics + * + * Appends the queue statistics to the top level TLV created by + * gnet_stats_start_copy(). + * + * Returns 0 on success or -1 with the statistic lock released + * if the room in the socket buffer was not sufficient. + */ int gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q) { @@ -95,6 +158,19 @@ gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q) return gnet_stats_copy(d, TCA_STATS_QUEUE, q, sizeof(*q)); } +/** + * gnet_stats_copy_app - copy application specific statistics into statistics TLV + * @d: dumping handle + * @st: application specific statistics data + * @len: length of data + * + * Appends the application sepecific statistics to the top level TLV created by + * gnet_stats_start_copy() and remembers the data for XSTATS if the dumping + * handle is in backward compatibility mode. + * + * Returns 0 on success or -1 with the statistic lock released + * if the room in the socket buffer was not sufficient. + */ int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) { @@ -103,6 +179,18 @@ gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) return gnet_stats_copy(d, TCA_STATS_APP, st, len); } +/** + * gnet_stats_finish_copy - finish dumping procedure + * @d: dumping handle + * + * Corrects the length of the top level TLV to include all TLVs added + * by gnet_stats_copy_XXX() calls. Adds the backward compatibility TLVs + * if gnet_stats_start_copy_compat() was used and releases the statistics + * lock. + * + * Returns 0 on success or -1 with the statistic lock released + * if the room in the socket buffer was not sufficient. + */ int gnet_stats_finish_copy(struct gnet_dump *d) { -- cgit v1.2.3 From 211001b963eba0d1e79826b00fc51316220653e6 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 1 Dec 2004 08:25:01 -0500 Subject: [ACPI] update C-state limiting patch Now "max_cstate=" instead of "acpi_cstate_limit=" Delete redundant static cstate flags .c2 and .c3 http://bugme.osdl.org/show_bug.cgi?id=3549 For static processor driver, boot cmdline: processor.max_cstate=2 For processor module, /etc/modprobe.conf: options processor max_cstate=2 or # modprobe processor max_cstate=2 From kernel or kernel module: #include acpi_set_cstate_limit(2); Suggested-by: Pavel Machek Signed-off-by: Len Brown --- Documentation/kernel-parameters.txt | 7 ++--- drivers/acpi/osl.c | 6 ++-- drivers/acpi/processor.c | 62 ++++++++++++++++++------------------- include/acpi/processor.h | 6 ++-- include/linux/acpi.h | 6 ++-- 5 files changed, 42 insertions(+), 45 deletions(-) (limited to 'include/linux') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index c311746b8956..4013d55387c8 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -960,10 +960,9 @@ running once the system is up. (param: profile step/bucket size as a power of 2 for statistical time based profiling) - processor.c2= [HW, ACPI] - processor.c3= [HW, ACPI] - 0 - disable C2 or C3 idle power saving state. - 1 - enable C2 or C3 (default unless DMI blacklist entry) + processor.max_cstate= [HW, ACPI] + Limit processor to maximum C-state + max_cstate=9 overrides any DMI blacklist limit. prompt_ramdisk= [RAM] List of RAM disks to prompt for floppy disk before loading. diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 50ae36382b9c..5d8afd7ab2ca 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1152,10 +1152,10 @@ acpi_wake_gpes_always_on_setup(char *str) __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); /* - * acpi_cstate_limit is defined in the base kernel so modules can + * max_cstate is defined in the base kernel so modules can * change it w/o depending on the state of the processor module. */ -unsigned int acpi_cstate_limit = ACPI_C_STATES_MAX; +unsigned int max_cstate = ACPI_C_STATES_MAX; -EXPORT_SYMBOL(acpi_cstate_limit); +EXPORT_SYMBOL(max_cstate); diff --git a/drivers/acpi/processor.c b/drivers/acpi/processor.c index c7eb59396a92..b7d37b515618 100644 --- a/drivers/acpi/processor.c +++ b/drivers/acpi/processor.c @@ -101,8 +101,6 @@ static struct acpi_driver acpi_processor_driver = { }, }; -static int c2 = -1; -static int c3 = -1; struct acpi_processor_errata { u8 smp; @@ -144,8 +142,6 @@ static struct file_operations acpi_processor_limit_fops = { static struct acpi_processor *processors[NR_CPUS]; static struct acpi_processor_errata errata; -module_param_named(c2, c2, bool, 0); -module_param_named(c3, c3, bool, 0); static void (*pm_idle_save)(void); @@ -338,8 +334,8 @@ acpi_processor_idle (void) { struct acpi_processor *pr = NULL; struct acpi_processor_cx *cx = NULL; - int next_state = 0; - int sleep_ticks = 0; + unsigned int next_state = 0; + unsigned int sleep_ticks = 0; u32 t1, t2 = 0; pr = processors[smp_processor_id()]; @@ -475,9 +471,9 @@ acpi_processor_idle (void) * Track the number of longs (time asleep is greater than threshold) * and promote when the count threshold is reached. Note that bus * mastering activity may prevent promotions. - * Do not promote above acpi_cstate_limit. + * Do not promote above max_cstate. */ - if (cx->promotion.state && (cx->promotion.state <= acpi_cstate_limit)) { + if (cx->promotion.state && (cx->promotion.state <= max_cstate)) { if (sleep_ticks > cx->promotion.threshold.ticks) { cx->promotion.count++; cx->demotion.count = 0; @@ -515,10 +511,10 @@ acpi_processor_idle (void) end: /* - * Demote if current state exceeds acpi_cstate_limit + * Demote if current state exceeds max_cstate */ - if (pr->power.state > acpi_cstate_limit) { - next_state = acpi_cstate_limit; + if (pr->power.state > max_cstate) { + next_state = max_cstate; } /* @@ -672,11 +668,6 @@ acpi_processor_get_power_info ( else if (errata.smp) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "C2 not supported in SMP mode\n")); - - - else if (!c2) - printk(KERN_INFO "C2 disabled\n"); - /* * Otherwise we've met all of our C2 requirements. * Normalize the C2 latency to expidite policy. @@ -732,9 +723,6 @@ acpi_processor_get_power_info ( ACPI_DEBUG_PRINT((ACPI_DB_INFO, "C3 not supported on PIIX4 with Type-F DMA\n")); } - else if (!c3) - printk(KERN_INFO "C3 disabled\n"); - /* * Otherwise we've met all of our C3 requirements. * Normalize the C2 latency to expidite policy. Enable @@ -995,7 +983,7 @@ acpi_processor_get_performance_states ( struct acpi_buffer format = {sizeof("NNNNNN"), "NNNNNN"}; struct acpi_buffer state = {0, NULL}; union acpi_object *pss = NULL; - int i = 0; + unsigned int i; ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states"); @@ -1117,7 +1105,7 @@ static struct file_operations acpi_processor_perf_fops = { static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset) { struct acpi_processor *pr = (struct acpi_processor *)seq->private; - int i = 0; + unsigned int i; ACPI_FUNCTION_TRACE("acpi_processor_perf_seq_show"); @@ -1880,7 +1868,7 @@ static int acpi_processor_info_open_fs(struct inode *inode, struct file *file) static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) { struct acpi_processor *pr = (struct acpi_processor *)seq->private; - int i = 0; + unsigned int i; ACPI_FUNCTION_TRACE("acpi_processor_power_seq_show"); @@ -1889,9 +1877,11 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) seq_printf(seq, "active state: C%d\n" "default state: C%d\n" + "max_cstate: C%d\n" "bus master activity: %08x\n", pr->power.state, pr->power.default_state, + max_cstate, pr->power.bm_activity); seq_puts(seq, "states:\n"); @@ -2478,17 +2468,22 @@ acpi_processor_remove ( return_VALUE(0); } -/* IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. - For now disable this. Probably a bug somewhere else. */ +/* + * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. + * For now disable this. Probably a bug somewhere else. + * + * To skip this limit, boot/load with a large max_cstate limit. + */ static int no_c2c3(struct dmi_system_id *id) { - printk(KERN_INFO - "%s detected - C2,C3 disabled. Overwrite with \"processor.c2=1 processor.c3=1\n\"", - id->ident); - if (c2 == -1) - c2 = 0; - if (c3 == -1) - c3 = 0; + if (max_cstate > ACPI_C_STATES_MAX) + return 0; + + printk(KERN_NOTICE PREFIX "%s detected - C2,C3 disabled." + " Override with \"processor.max_cstate=9\"\n", id->ident); + + max_cstate = 1; + return 0; } @@ -2533,6 +2528,9 @@ acpi_processor_init (void) dmi_check_system(processor_dmi_table); + if (max_cstate < ACPI_C_STATES_MAX) + printk(KERN_NOTICE "ACPI: processor limited to max C-state %d\n", max_cstate); + return_VALUE(0); } @@ -2556,6 +2554,6 @@ acpi_processor_exit (void) module_init(acpi_processor_init); module_exit(acpi_processor_exit); -module_param_named(acpi_cstate_limit, acpi_cstate_limit, uint, 0); +module_param_named(max_cstate, max_cstate, uint, 0); EXPORT_SYMBOL(acpi_processor_set_thermal_limit); diff --git a/include/acpi/processor.h b/include/acpi/processor.h index dab7521d8ac6..700cafd2b5cc 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -17,7 +17,7 @@ struct acpi_processor_cx_policy { u32 count; - int state; + u32 state; struct { u32 time; u32 ticks; @@ -38,8 +38,8 @@ struct acpi_processor_cx { }; struct acpi_processor_power { - int state; - int default_state; + u32 state; + u32 default_state; u32 bm_activity; struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER]; }; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 5960e3c49fe7..9cd73a47fc18 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -483,15 +483,15 @@ static inline int acpi_blacklisted(void) * 2: C2 okay, but not C3 etc. */ -extern unsigned int acpi_cstate_limit; +extern unsigned int max_cstate; static inline unsigned int acpi_get_cstate_limit(void) { - return acpi_cstate_limit; + return max_cstate; } static inline void acpi_set_cstate_limit(unsigned int new_limit) { - acpi_cstate_limit = new_limit; + max_cstate = new_limit; return; } #else -- cgit v1.2.3 From 01eb4811efe377ac2311329186e61f2392dee75c Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Thu, 2 Dec 2004 15:47:45 -0800 Subject: [PATCH] proc_pid_status() oops fix proc_pid_status dereferences pointers in the task structure even if the task is already dead. This is probably the reason for the oops described in http://bugme.osdl.org/show_bug.cgi?id=3812 The attached patch removes the pointer dereferences by using pid_alive() for testing that the task structure contents is still valid before dereferencing them. The task structure itself is guaranteed to be valid - we hold a reference count. Signed-Off-By: Manfred Spraul Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/array.c | 4 ++-- fs/proc/base.c | 5 ----- include/linux/sched.h | 13 +++++++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/fs/proc/array.c b/fs/proc/array.c index 6db46cb190c5..f5ad3980b0ff 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -171,8 +171,8 @@ static inline char * task_state(struct task_struct *p, char *buffer) get_task_state(p), (p->sleep_avg/1024)*100/(1020000000/1024), p->tgid, - p->pid, p->pid ? p->group_leader->real_parent->tgid : 0, - p->pid && p->ptrace ? p->parent->pid : 0, + p->pid, pid_alive(p) ? p->group_leader->real_parent->tgid : 0, + pid_alive(p) && p->ptrace ? p->parent->pid : 0, p->uid, p->euid, p->suid, p->fsuid, p->gid, p->egid, p->sgid, p->fsgid); read_unlock(&tasklist_lock); diff --git a/fs/proc/base.c b/fs/proc/base.c index 7acfee6ece8d..d6fb25eeee7a 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -780,11 +780,6 @@ static struct inode_operations proc_pid_link_inode_operations = { .follow_link = proc_pid_follow_link }; -static inline int pid_alive(struct task_struct *p) -{ - return p->pids[PIDTYPE_PID].nr != 0; -} - #define NUMBUF 10 static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) diff --git a/include/linux/sched.h b/include/linux/sched.h index 0c8262c6d6b8..440393fcd5c7 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -671,6 +671,19 @@ static inline pid_t process_group(struct task_struct *tsk) return tsk->signal->pgrp; } +/** + * pid_alive - check that a task structure is not stale + * @p: Task structure to be checked. + * + * Test if a process is not yet dead (at most zombie state) + * If pid_alive fails, then pointers within the task structure + * can be stale and must not be dereferenced. + */ +static inline int pid_alive(struct task_struct *p) +{ + return p->pids[PIDTYPE_PID].nr != 0; +} + extern void free_task(struct task_struct *tsk); extern void __put_task_struct(struct task_struct *tsk); #define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0) -- cgit v1.2.3 From bb3ddc318e8fc1f0bca18c1d86403c01370fe9df Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 4 Dec 2004 21:09:09 +0000 Subject: [SERIAL] Ensure correct units for close_delay and closing_wait. Use milliseconds internally for these delays, and convert them to centiseconds at the interface boundary to the ioctl configuration controls. --- drivers/serial/serial_core.c | 32 ++++++++++++++++++-------------- include/linux/serial_core.h | 6 +++--- 2 files changed, 21 insertions(+), 17 deletions(-) (limited to 'include/linux') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 9be3fcb9033f..5ed45a7cbdda 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -584,8 +584,10 @@ static int uart_get_info(struct uart_state *state, tmp.flags = port->flags; tmp.xmit_fifo_size = port->fifosize; tmp.baud_base = port->uartclk / 16; - tmp.close_delay = state->close_delay; - tmp.closing_wait = state->closing_wait; + tmp.close_delay = state->close_delay / 10; + tmp.closing_wait = state->closing_wait == USF_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : + state->closing_wait / 10; tmp.custom_divisor = port->custom_divisor; tmp.hub6 = port->hub6; tmp.io_type = port->iotype; @@ -603,8 +605,8 @@ static int uart_set_info(struct uart_state *state, struct serial_struct new_serial; struct uart_port *port = state->port; unsigned long new_port; - unsigned int change_irq, change_port, old_flags; - unsigned int old_custom_divisor; + unsigned int change_irq, change_port, old_flags, closing_wait; + unsigned int old_custom_divisor, close_delay; int retval = 0; if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) @@ -615,6 +617,9 @@ static int uart_set_info(struct uart_state *state, new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; new_serial.irq = irq_canonicalize(new_serial.irq); + close_delay = new_serial.close_delay * 10; + closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + USF_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; /* * This semaphore protects state->count. It is also @@ -646,8 +651,8 @@ static int uart_set_info(struct uart_state *state, retval = -EPERM; if (change_irq || change_port || (new_serial.baud_base != port->uartclk / 16) || - (new_serial.close_delay != state->close_delay) || - (new_serial.closing_wait != state->closing_wait) || + (close_delay != state->close_delay) || + (closing_wait != state->closing_wait) || (new_serial.xmit_fifo_size != port->fifosize) || (((new_serial.flags ^ old_flags) & ~UPF_USR_MASK) != 0)) goto exit; @@ -751,8 +756,8 @@ static int uart_set_info(struct uart_state *state, port->flags = (port->flags & ~UPF_CHANGE_MASK) | (new_serial.flags & UPF_CHANGE_MASK); port->custom_divisor = new_serial.custom_divisor; - state->close_delay = new_serial.close_delay * HZ / 100; - state->closing_wait = new_serial.closing_wait * HZ / 100; + state->close_delay = close_delay; + state->closing_wait = closing_wait; port->fifosize = new_serial.xmit_fifo_size; if (state->info->tty) state->info->tty->low_latency = @@ -1191,7 +1196,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) tty->closing = 1; if (state->closing_wait != USF_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, state->closing_wait); + tty_wait_until_sent(tty, msecs_to_jiffies(state->closing_wait)); /* * At this point, we stop accepting input. To do this, we @@ -1219,9 +1224,8 @@ static void uart_close(struct tty_struct *tty, struct file *filp) state->info->tty = NULL; if (state->info->blocked_open) { - if (state->close_delay) { - msleep_interruptible(jiffies_to_msecs(state->close_delay)); - } + if (state->close_delay) + msleep_interruptible(state->close_delay); } else if (!uart_console(port)) { uart_change_pm(state, 3); } @@ -2082,8 +2086,8 @@ int uart_register_driver(struct uart_driver *drv) for (i = 0; i < drv->nr; i++) { struct uart_state *state = drv->state + i; - state->close_delay = 5 * HZ / 10; - state->closing_wait = 30 * HZ; + state->close_delay = 500; /* .5 seconds */ + state->closing_wait = 30000; /* 30 seconds */ init_MUTEX(&state->sem); } diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 1dd43bc63800..9666c572f65b 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -244,11 +244,11 @@ struct uart_port { * within. */ struct uart_state { - unsigned int close_delay; - unsigned int closing_wait; + unsigned int close_delay; /* msec */ + unsigned int closing_wait; /* msec */ #define USF_CLOSING_WAIT_INF (0) -#define USF_CLOSING_WAIT_NONE (65535) +#define USF_CLOSING_WAIT_NONE (~0U) int count; int pm_state; -- cgit v1.2.3