⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c2410-linux-2.6.11.1-apm-08.11.02.patch

📁 将s3c2410-linux-2.6.11.1-apm-08.11.02.patch复制到内核根目录。 执行patch –p1 < s3c2410-linux-2.6.11.1-apm-08.
💻 PATCH
📖 第 1 页 / 共 2 页
字号:
diff -urN s3c2410-linux-2.6.11.1/arch/arm/kernel/apm.c s3c2410-linux-2.6.11.1-apm-08.11.02/arch/arm/kernel/apm.c--- s3c2410-linux-2.6.11.1/arch/arm/kernel/apm.c	2005-03-04 12:26:46.000000000 -0500+++ s3c2410-linux-2.6.11.1-apm-08.11.02/arch/arm/kernel/apm.c	2008-11-02 08:32:12.000000000 -0500@@ -13,11 +13,11 @@ #include <linux/config.h> #include <linux/module.h> #include <linux/poll.h>-#include <linux/timer.h> #include <linux/slab.h> #include <linux/proc_fs.h> #include <linux/miscdevice.h> #include <linux/apm_bios.h>+#include <linux/capability.h> #include <linux/sched.h> #include <linux/pm.h> #include <linux/device.h>@@ -25,6 +25,8 @@ #include <linux/list.h> #include <linux/init.h> #include <linux/completion.h>+#include <linux/kthread.h>+#include <linux/delay.h>  #include <asm/apm.h> /* apm_power_info */ #include <asm/system.h>@@ -70,7 +72,8 @@ #define SUSPEND_PENDING	1		/* suspend pending read */ #define SUSPEND_READ	2		/* suspend read, pending ack */ #define SUSPEND_ACKED	3		/* suspend acked */-#define SUSPEND_DONE	4		/* suspend completed */+#define SUSPEND_WAIT	4		/* waiting for suspend */+#define SUSPEND_DONE	5		/* suspend completed */  	struct apm_queue	queue; };@@ -80,6 +83,7 @@  */ static int suspends_pending; static int apm_disabled;+static struct task_struct *kapmd_tsk;  static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);@@ -96,10 +100,10 @@  * to be suspending the system.  */ static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);-static DECLARE_COMPLETION(kapmd_exit); static DEFINE_SPINLOCK(kapmd_queue_lock); static struct apm_queue kapmd_queue; +static DECLARE_MUTEX(state_lock);  static const char driver_version[] = "1.13";	/* no spaces */ @@ -147,38 +151,60 @@ 	q->events[q->event_head] = event; } -static void queue_event_one_user(struct apm_user *as, apm_event_t event)+static void queue_event(apm_event_t event) {-	if (as->suser && as->writer) {-		switch (event) {-		case APM_SYS_SUSPEND:-		case APM_USER_SUSPEND:-			/*-			 * If this user already has a suspend pending,-			 * don't queue another one.-			 */-			if (as->suspend_state != SUSPEND_NONE)-				return;+	struct apm_user *as; -			as->suspend_state = SUSPEND_PENDING;-			suspends_pending++;-			break;-		}+	down_read(&user_list_lock);+	list_for_each_entry(as, &apm_user_list, list) {+		if (as->reader)+			queue_add_event(&as->queue, event); 	}-	queue_add_event(&as->queue, event);+	up_read(&user_list_lock);+	wake_up_interruptible(&apm_waitqueue); } -static void queue_event(apm_event_t event, struct apm_user *sender)+/*+ * queue_suspend_event - queue an APM suspend event.+ *+ * Check that we're in a state where we can suspend.  If not,+ * return -EBUSY.  Otherwise, queue an event to all "writer"+ * users.  If there are no "writer" users, return '1' to+ * indicate that we can immediately suspend.+ */+static int queue_suspend_event(apm_event_t event, struct apm_user *sender) { 	struct apm_user *as;+	int ret = 1; +	down(&state_lock); 	down_read(&user_list_lock);++	/*+	 * If a thread is still processing, we can't suspend, so reject+	 * the request.+	 */+	list_for_each_entry(as, &apm_user_list, list) {+		if (as != sender && as->reader && as->writer && as->suser &&+		    as->suspend_state != SUSPEND_NONE) {+			ret = -EBUSY;+			goto out;+		}+	}+ 	list_for_each_entry(as, &apm_user_list, list) {-		if (as != sender && as->reader)-			queue_event_one_user(as, event);+		if (as != sender && as->reader && as->writer && as->suser) {+			as->suspend_state = SUSPEND_PENDING;+			suspends_pending++;+			queue_add_event(&as->queue, event);+			ret = 0;+		} 	}+ out: 	up_read(&user_list_lock);+	up(&state_lock); 	wake_up_interruptible(&apm_waitqueue);+	return ret; }  static void apm_suspend(void)@@ -190,17 +216,22 @@ 	 * Anyone on the APM queues will think we're still suspended. 	 * Send a message so everyone knows we're now awake again. 	 */-	queue_event(APM_NORMAL_RESUME, NULL);+	queue_event(APM_NORMAL_RESUME);  	/* 	 * Finally, wake up anyone who is sleeping on the suspend. 	 */+	down(&state_lock); 	down_read(&user_list_lock); 	list_for_each_entry(as, &apm_user_list, list) {-		as->suspend_result = err;-		as->suspend_state = SUSPEND_DONE;+		if (as->suspend_state == SUSPEND_WAIT ||+		    as->suspend_state == SUSPEND_ACKED) {+	  		as->suspend_result = err;+			as->suspend_state = SUSPEND_DONE;+		} 	} 	up_read(&user_list_lock);+	up(&state_lock);  	wake_up(&apm_suspend_waitqueue); }@@ -226,8 +257,11 @@ 		if (copy_to_user(buf, &event, sizeof(event))) 			break; -		if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)+		down(&state_lock);+		if (as->suspend_state == SUSPEND_PENDING &&+		    (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)) 			as->suspend_state = SUSPEND_READ;+		up(&state_lock);  		buf += sizeof(event); 		i -= sizeof(event);@@ -269,9 +303,13 @@  	switch (cmd) { 	case APM_IOC_SUSPEND:+		down(&state_lock);+ 		as->suspend_result = -EINTR;  		if (as->suspend_state == SUSPEND_READ) {+			int pending;+ 			/* 			 * If we read a suspend command from /dev/apm_bios, 			 * then the corresponding APM_IOC_SUSPEND ioctl is@@ -279,47 +317,73 @@ 			 */ 			as->suspend_state = SUSPEND_ACKED; 			suspends_pending--;+			pending = suspends_pending == 0;+			up(&state_lock);++			/*+			 * If there are no further acknowledges required,+			 * suspend the system.+			 */+			if (pending)+				apm_suspend();++			/*+			 * Wait for the suspend/resume to complete.  If there+			 * are pending acknowledges, we wait here for them.+			 *+			 * Note: we need to ensure that the PM subsystem does+			 * not kick us out of the wait when it suspends the+			 * threads.+			 */+			flags = current->flags;+			current->flags |= PF_NOFREEZE;++			wait_event(apm_suspend_waitqueue,+				   as->suspend_state == SUSPEND_DONE); 		} else {+			as->suspend_state = SUSPEND_WAIT;+			up(&state_lock);+ 			/* 			 * Otherwise it is a request to suspend the system. 			 * Queue an event for all readers, and expect an 			 * acknowledge from all writers who haven't already 			 * acknowledged. 			 */-			queue_event(APM_USER_SUSPEND, as);-		}+			err = queue_suspend_event(APM_USER_SUSPEND, as);+			if (err < 0) {+				/*+				 * Avoid taking the lock here - this+				 * should be fine.+				 */+				as->suspend_state = SUSPEND_NONE;+				break;+			} -		/*-		 * If there are no further acknowledges required, suspend-		 * the system.-		 */-		if (suspends_pending == 0)-			apm_suspend();+			if (err > 0)+				apm_suspend(); -		/*-		 * Wait for the suspend/resume to complete.  If there are-		 * pending acknowledges, we wait here for them.-		 *-		 * Note that we need to ensure that the PM subsystem does-		 * not kick us out of the wait when it suspends the threads.-		 */-		flags = current->flags;-		current->flags |= PF_NOFREEZE;+			/*+			 * Wait for the suspend/resume to complete.  If there+			 * are pending acknowledges, we wait here for them.+			 *+			 * Note: we need to ensure that the PM subsystem does+			 * not kick us out of the wait when it suspends the+			 * threads.+			 */+			flags = current->flags;+			current->flags |= PF_NOFREEZE; -		/*-		 * Note: do not allow a thread which is acking the suspend-		 * to escape until the resume is complete.-		 */-		if (as->suspend_state == SUSPEND_ACKED)-			wait_event(apm_suspend_waitqueue,-					 as->suspend_state == SUSPEND_DONE);-		else 			wait_event_interruptible(apm_suspend_waitqueue, 					 as->suspend_state == SUSPEND_DONE);+		}  		current->flags = flags;++		down(&state_lock); 		err = as->suspend_result; 		as->suspend_state = SUSPEND_NONE;+		up(&state_lock); 		break; 	} @@ -329,6 +393,8 @@ static int apm_release(struct inode * inode, struct file * filp) { 	struct apm_user *as = filp->private_data;+	int pending = 0;+ 	filp->private_data = NULL;  	down_write(&user_list_lock);@@ -341,11 +407,14 @@ 	 * need to balance suspends_pending, which means the 	 * possibility of sleeping. 	 */+	down(&state_lock); 	if (as->suspend_state != SUSPEND_NONE) { 		suspends_pending -= 1;-		if (suspends_pending == 0)-			apm_suspend();+		pending = suspends_pending == 0; 	}+	up(&state_lock);+	if (pending)+		apm_suspend();  	kfree(as); 	return 0;@@ -358,7 +427,6 @@ 	as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL); 	if (as) { 		memset(as, 0, sizeof(*as));- 		/* 		 * XXX - this is a tiny bit broken, when we consider BSD 		 * process accounting. If the device is opened by root, we@@ -469,16 +537,14 @@  static int kapmd(void *arg) {-	daemonize("kapmd");-	current->flags |= PF_NOFREEZE;- 	do { 		apm_event_t event;+		int ret;  		wait_event_interruptible(kapmd_wait,-				!queue_empty(&kapmd_queue) || !pm_active);+				!queue_empty(&kapmd_queue) || kthread_should_stop()); -		if (!pm_active)+		if (kthread_should_stop()) 			break;  		spin_lock_irq(&kapmd_queue_lock);@@ -493,13 +559,20 @@  		case APM_LOW_BATTERY: 		case APM_POWER_STATUS_CHANGE:-			queue_event(event, NULL);+			queue_event(event); 			break;  		case APM_USER_SUSPEND: 		case APM_SYS_SUSPEND:-			queue_event(event, NULL);-			if (suspends_pending == 0)+			ret = queue_suspend_event(event, NULL);+			if (ret < 0) {+				/*+				 * We were busy.  Try again in 50ms.+				 */+				queue_add_event(&kapmd_queue, event);+				msleep(50);+			}+			if (ret > 0) 				apm_suspend(); 			break; @@ -509,7 +582,7 @@ 		} 	} while (1); -	complete_and_exit(&kapmd_exit, 0);+	return 0; }  static int __init apm_init(void)@@ -521,18 +594,14 @@ 		return -ENODEV; 	} -	if (PM_IS_ACTIVE()) {-		printk(KERN_NOTICE "apm: overridden by ACPI.\n");-		return -EINVAL;-	}--	pm_active = 1;--	ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);-	if (ret < 0) {-		pm_active = 0;+	kapmd_tsk = kthread_create(kapmd, NULL, "kapmd");+	if (IS_ERR(kapmd_tsk)) {+		ret = PTR_ERR(kapmd_tsk);+		kapmd_tsk = NULL; 		return ret; 	}+	kapmd_tsk->flags |= PF_NOFREEZE;+	wake_up_process(kapmd_tsk);  #ifdef CONFIG_PROC_FS 	create_proc_info_entry("apm", 0, NULL, apm_get_info);@@ -541,10 +610,7 @@ 	ret = misc_register(&apm_device); 	if (ret != 0) { 		remove_proc_entry("apm", NULL);--		pm_active = 0;-		wake_up(&kapmd_wait);-		wait_for_completion(&kapmd_exit);+		kthread_stop(kapmd_tsk); 	}  	return ret;@@ -555,9 +621,7 @@ 	misc_deregister(&apm_device); 	remove_proc_entry("apm", NULL); -	pm_active = 0;-	wake_up(&kapmd_wait);-	wait_for_completion(&kapmd_exit);+	kthread_stop(kapmd_tsk); }  module_init(apm_init);diff -urN s3c2410-linux-2.6.11.1/arch/arm/kernel/setup.c s3c2410-linux-2.6.11.1-apm-08.11.02/arch/arm/kernel/setup.c--- s3c2410-linux-2.6.11.1/arch/arm/kernel/setup.c	2005-06-01 19:38:57.000000000 -0400+++ s3c2410-linux-2.6.11.1-apm-08.11.02/arch/arm/kernel/setup.c	2008-11-02 08:32:12.000000000 -0500@@ -92,6 +92,14 @@ struct cpu_cache_fns cpu_cache; #endif +struct stack {+	u32 irq[3];+	u32 abt[3];+	u32 und[3];+} ____cacheline_aligned;++static struct stack stacks[NR_CPUS];+ char elf_platform[ELF_PLATFORM_SIZE]; EXPORT_SYMBOL(elf_platform); @@ -316,6 +324,48 @@ 	cpu_proc_init(); } +/*+ * cpu_init - initialise one CPU.+ *+ * cpu_init dumps the cache information, initialises SMP specific+ * information, and sets up the per-CPU stacks.+ */+void cpu_init(void)+{+	unsigned int cpu = smp_processor_id();+	struct stack *stk = &stacks[cpu];++	if (cpu >= NR_CPUS) {+		printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);+		BUG();+	}++	if (system_state == SYSTEM_BOOTING)+		dump_cpu_info(cpu);++	/*+	 * setup stacks for re-entrant exception handlers+	 */+	__asm__ (+	"msr	cpsr_c, %1\n\t"+	"add	sp, %0, %2\n\t"+	"msr	cpsr_c, %3\n\t"+	"add	sp, %0, %4\n\t"+	"msr	cpsr_c, %5\n\t"+	"add	sp, %0, %6\n\t"+	"msr	cpsr_c, %7"+	    :+	    : "r" (stk),+	      "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),+	      "I" (offsetof(struct stack, irq[0])),+	      "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),+	      "I" (offsetof(struct stack, abt[0])),+	      "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),+	      "I" (offsetof(struct stack, und[0])),+	      "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)+	    : "r14");+}+ static struct machine_desc * __init setup_machine(unsigned int nr) { 	struct machine_desc *list;diff -urN s3c2410-linux-2.6.11.1/arch/arm/mach-s3c2410/irq.c s3c2410-linux-2.6.11.1-apm-08.11.02/arch/arm/mach-s3c2410/irq.c--- s3c2410-linux-2.6.11.1/arch/arm/mach-s3c2410/irq.c	2005-06-01 19:38:57.000000000 -0400+++ s3c2410-linux-2.6.11.1-apm-08.11.02/arch/arm/mach-s3c2410/irq.c	2008-11-02 08:32:12.000000000 -0500@@ -81,7 +81,7 @@ unsigned long s3c_irqwake_eintallow	= 0x0000fff0L; unsigned long s3c_irqwake_eintmask	= 0xffffffffL; -static int+int s3c_irq_wake(unsigned int irqno, unsigned int state) { 	unsigned long irqbit = 1 << (irqno - IRQ_EINT0);diff -urN s3c2410-linux-2.6.11.1/arch/arm/mach-s3c2410/irq.h s3c2410-linux-2.6.11.1-apm-08.11.02/arch/arm/mach-s3c2410/irq.h--- s3c2410-linux-2.6.11.1/arch/arm/mach-s3c2410/irq.h	1969-12-31 19:00:00.000000000 -0500+++ s3c2410-linux-2.6.11.1-apm-08.11.02/arch/arm/mach-s3c2410/irq.h	2008-10-16 23:35:57.000000000 -0400@@ -0,0 +1,109 @@+/* arch/arm/mach-s3c2410/irq.h+ *+ * Copyright (c) 2004-2005 Simtec Electronics+ *	Ben Dooks <ben@simtec.co.uk>+ *+ * Header file for S3C24XX CPU IRQ support+ *+ * 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.+ *+ * Modifications:+*/++#define irqdbf(x...)+#define irqdbf2(x...)++#define EXTINT_OFF (IRQ_EINT4 - 4)++extern struct irqchip s3c_irq_level_chip;++static inline void+s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,+		int subcheck)+{+	unsigned long mask;+	unsigned long submask;++	submask = __raw_readl(S3C2410_INTSUBMSK);+	mask = __raw_readl(S3C2410_INTMSK);++	submask |= (1UL << (irqno - IRQ_S3CUART_RX0));++	/* check to see if we need to mask the parent IRQ */++	if ((submask  & subcheck) == subcheck) {+		__raw_writel(mask | parentbit, S3C2410_INTMSK);+	}++	/* write back masks */+	__raw_writel(submask, S3C2410_INTSUBMSK);+

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -